emacs-diffs
[Top][All Lists]
Advanced

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

feature/positioned-lambdas 7046203ed3c 2/3: Merge branch 'master' into f


From: Alan Mackenzie
Subject: feature/positioned-lambdas 7046203ed3c 2/3: Merge branch 'master' into feature/positioned-lambdas
Date: Mon, 4 Mar 2024 10:06:31 -0500 (EST)

branch: feature/positioned-lambdas
commit 7046203ed3c1503582ffcd77ad379fa096dc7d52
Merge: 1bd7bee1d6b 25bf8d3cdc6
Author: Alan Mackenzie <acm@muc.de>
Commit: Alan Mackenzie <acm@muc.de>

    Merge branch 'master' into feature/positioned-lambdas
---
 .dir-locals.el                                     |   10 +-
 .gitattributes                                     |    2 +-
 .gitignore                                         |    5 +-
 .gitlab-ci.yml                                     |    2 +-
 .mailmap                                           |    3 +-
 CONTRIBUTE                                         |    2 +-
 ChangeLog.1                                        |    2 +-
 ChangeLog.2                                        |   14 +-
 ChangeLog.3                                        |   92 +-
 ChangeLog.4                                        | 2229 +++++++++++---
 ChangeLog.android                                  |   28 +-
 GNUmakefile                                        |    2 +-
 INSTALL                                            |    2 +-
 INSTALL.REPO                                       |    2 +-
 Makefile.in                                        |    2 +-
 README                                             |    2 +-
 admin/ChangeLog.1                                  |    2 +-
 admin/README                                       |   20 +-
 admin/admin.el                                     |    2 +-
 admin/alloc-colors.c                               |    2 +-
 admin/authors.el                                   |    4 +-
 admin/automerge                                    |    2 +-
 admin/build-configs                                |    2 +-
 admin/charsets/Makefile.in                         |    2 +-
 admin/charsets/mapconv                             |    2 +-
 admin/charsets/mapfiles/README                     |    2 +-
 admin/check-man-pages                              |    2 +-
 admin/coccinelle/alloc_cast.cocci                  |    6 +
 admin/coccinelle/build_string.cocci                |    6 +
 admin/coccinelle/nilp.cocci                        |    6 +
 admin/coccinelle/unibyte_string.cocci              |    6 +
 admin/coccinelle/xsave.cocci                       |   11 -
 admin/codespell/README                             |   27 +
 admin/codespell/codespell.dictionary               |   17 +
 admin/codespell/codespell.exclude                  | 1585 ++++++++++
 admin/codespell/codespell.ignore                   |   41 +
 admin/codespell/codespell.rc                       |    4 +
 admin/cus-test.el                                  |   11 +-
 admin/diff-tar-files                               |    2 +-
 admin/emacs-shell-lib                              |    2 +-
 admin/emake                                        |    2 +-
 admin/find-gc.el                                   |    2 +-
 admin/git-bisect-start                             |   10 +-
 admin/gitmerge.el                                  |    2 +-
 admin/grammars/Makefile.in                         |    2 +-
 admin/grammars/c.by                                |    2 +-
 admin/grammars/grammar.wy                          |    2 +-
 admin/grammars/java-tags.wy                        |    2 +-
 admin/grammars/js.wy                               |    2 +-
 admin/grammars/make.by                             |    2 +-
 admin/grammars/python.wy                           |    2 +-
 admin/grammars/scheme.by                           |    2 +-
 admin/grammars/srecode-template.wy                 |    2 +-
 admin/last-chance.el                               |    2 +-
 admin/make-emacs                                   |    2 +-
 admin/make-manuals                                 |    2 +-
 admin/merge-gnulib                                 |    7 +-
 admin/merge-pkg-config                             |    2 +-
 admin/notes/copyright                              |    2 +-
 admin/notes/emba                                   |    2 +-
 admin/notes/hydra                                  |    2 +-
 admin/notes/java                                   |   10 +-
 admin/notes/multi-tty                              |    2 +-
 admin/notes/tree-sitter/build-module/batch.sh      |    1 +
 admin/notes/unicode                                |    2 +-
 admin/notes/www                                    |    2 +-
 admin/notes/years                                  |    2 +
 admin/nt/README-UNDUMP.W32                         |    2 +-
 admin/nt/dist-build/README-windows-binaries        |    2 +-
 admin/nt/dist-build/build-dep-zips.py              |    2 +-
 admin/nt/dist-build/build-zips.sh                  |    2 +-
 admin/quick-install-emacs                          |    2 +-
 admin/run-codespell                                |   68 +
 admin/unidata/Makefile.in                          |    2 +-
 admin/unidata/blocks.awk                           |    5 +-
 admin/unidata/emoji-zwj.awk                        |    2 +-
 admin/unidata/unidata-gen.el                       |    2 +-
 admin/unidata/uvs.el                               |    2 +-
 admin/update-copyright                             |    2 +-
 admin/update_autogen                               |    2 +-
 admin/upload-manuals                               |    2 +-
 autogen.sh                                         |   18 +-
 build-aux/config.guess                             |   17 +-
 build-aux/config.sub                               |  176 +-
 build-aux/git-hooks/commit-msg                     |    2 +-
 build-aux/git-hooks/commit-msg-files.awk           |    2 +-
 build-aux/git-hooks/post-commit                    |    2 +-
 build-aux/git-hooks/pre-commit                     |    2 +-
 build-aux/git-hooks/pre-push                       |    2 +-
 build-aux/git-hooks/prepare-commit-msg             |    2 +-
 build-aux/gitlog-to-changelog                      |    2 +-
 build-aux/gitlog-to-emacslog                       |    2 +-
 build-aux/install-sh                               |    8 +-
 build-aux/make-info-dir                            |    2 +-
 build-aux/makecounter.sh                           |    2 +-
 build-aux/move-if-change                           |    2 +-
 build-aux/msys-to-w32                              |    2 +-
 build-aux/ndk-build-helper-1.mk                    |    2 +-
 build-aux/ndk-build-helper-2.mk                    |    2 +-
 build-aux/ndk-build-helper-3.mk                    |    2 +-
 build-aux/ndk-build-helper-4.mk                    |    2 +-
 build-aux/ndk-build-helper.mk                      |    2 +-
 build-aux/update-copyright                         |  161 +-
 build-aux/update-subdirs                           |    2 +-
 config.bat                                         |    2 +-
 configure.ac                                       |   16 +-
 cross/Makefile.in                                  |    2 +-
 cross/langinfo.h                                   |    2 +-
 cross/ndk-build/Makefile.in                        |    2 +-
 cross/ndk-build/README                             |    6 +-
 cross/ndk-build/ndk-build-executable.mk            |    2 +-
 cross/ndk-build/ndk-build-shared-library.mk        |    2 +-
 cross/ndk-build/ndk-build-static-library.mk        |    2 +-
 cross/ndk-build/ndk-build.mk.in                    |    2 +-
 cross/ndk-build/ndk-clear-vars.mk                  |    2 +-
 cross/ndk-build/ndk-prebuilt-shared-library.mk     |    2 +-
 cross/ndk-build/ndk-prebuilt-static-library.mk     |    2 +-
 cross/ndk-build/ndk-resolve.mk                     |    2 +-
 cross/verbose.mk.android                           |    2 +-
 doc/emacs/ChangeLog.1                              |    6 +-
 doc/emacs/Makefile.in                              |    2 +-
 doc/emacs/abbrevs.texi                             |    2 +-
 doc/emacs/ack.texi                                 |    2 +-
 doc/emacs/android.texi                             |   26 +-
 doc/emacs/anti.texi                                |    2 +-
 doc/emacs/arevert-xtra.texi                        |    2 +-
 doc/emacs/back.texi                                |    4 +-
 doc/emacs/basic.texi                               |   17 +-
 doc/emacs/buffers.texi                             |   32 +-
 doc/emacs/building.texi                            |    2 +-
 doc/emacs/cal-xtra.texi                            |    2 +-
 doc/emacs/calendar.texi                            |    2 +-
 doc/emacs/cmdargs.texi                             |    7 +-
 doc/emacs/commands.texi                            |    2 +-
 doc/emacs/custom.texi                              |    9 +-
 doc/emacs/dired-xtra.texi                          |    2 +-
 doc/emacs/dired.texi                               |    6 +-
 doc/emacs/display.texi                             |    3 +-
 doc/emacs/emacs-xtra.texi                          |    2 +-
 doc/emacs/emacs.texi                               |    2 +-
 doc/emacs/emerge-xtra.texi                         |    2 +-
 doc/emacs/entering.texi                            |    2 +-
 doc/emacs/files.texi                               |    7 +-
 doc/emacs/fixit.texi                               |   30 +-
 doc/emacs/fortran-xtra.texi                        |    2 +-
 doc/emacs/frames.texi                              |    2 +-
 doc/emacs/glossary.texi                            |    2 +-
 doc/emacs/gnu.texi                                 |    2 +-
 doc/emacs/haiku.texi                               |    4 +-
 doc/emacs/help.texi                                |   17 +-
 doc/emacs/indent.texi                              |    2 +-
 doc/emacs/input.texi                               |    2 +-
 doc/emacs/killing.texi                             |    2 +-
 doc/emacs/kmacro.texi                              |    2 +-
 doc/emacs/m-x.texi                                 |    2 +-
 doc/emacs/macos.texi                               |    2 +-
 doc/emacs/maintaining.texi                         |   36 +-
 doc/emacs/mark.texi                                |    2 +-
 doc/emacs/mini.texi                                |    6 +-
 doc/emacs/misc.texi                                |    2 +-
 doc/emacs/modes.texi                               |    2 +-
 doc/emacs/msdos-xtra.texi                          |    2 +-
 doc/emacs/msdos.texi                               |   25 +-
 doc/emacs/mule.texi                                |    2 +-
 doc/emacs/package.texi                             |    2 +-
 doc/emacs/picture-xtra.texi                        |    2 +-
 doc/emacs/programs.texi                            |    2 +-
 doc/emacs/regs.texi                                |   60 +-
 doc/emacs/rmail.texi                               |    2 +-
 doc/emacs/screen.texi                              |    2 +-
 doc/emacs/search.texi                              |    2 +-
 doc/emacs/sending.texi                             |    2 +-
 doc/emacs/text.texi                                |    2 +-
 doc/emacs/trouble.texi                             |    2 +-
 doc/emacs/vc-xtra.texi                             |    2 +-
 doc/emacs/vc1-xtra.texi                            |    2 +-
 doc/emacs/windows.texi                             |    4 +-
 doc/emacs/xresources.texi                          |    2 +-
 doc/lang/fr/misc/ses-fr.texi                       | 1631 +++++++++++
 doc/lispintro/ChangeLog.1                          |    2 +-
 doc/lispintro/Makefile.in                          |    2 +-
 doc/lispintro/README                               |    2 +-
 doc/lispintro/cons-1.eps                           |    2 +-
 doc/lispintro/cons-2.eps                           |    2 +-
 doc/lispintro/cons-2a.eps                          |    2 +-
 doc/lispintro/cons-3.eps                           |    2 +-
 doc/lispintro/cons-4.eps                           |    2 +-
 doc/lispintro/cons-5.eps                           |    2 +-
 doc/lispintro/drawers.eps                          |    2 +-
 doc/lispintro/emacs-lisp-intro.texi                |  364 ++-
 doc/lispintro/lambda-1.eps                         |    2 +-
 doc/lispintro/lambda-2.eps                         |    2 +-
 doc/lispintro/lambda-3.eps                         |    2 +-
 doc/lispref/ChangeLog.1                            |    2 +-
 doc/lispref/Makefile.in                            |    2 +-
 doc/lispref/README                                 |    2 +-
 doc/lispref/abbrevs.texi                           |    2 +-
 doc/lispref/anti.texi                              |    2 +-
 doc/lispref/back.texi                              |    2 +-
 doc/lispref/backups.texi                           |    2 +-
 doc/lispref/buffers.texi                           |   15 +-
 doc/lispref/commands.texi                          |   38 +-
 doc/lispref/compile.texi                           |   83 +-
 doc/lispref/control.texi                           |  121 +-
 doc/lispref/customize.texi                         |    2 +-
 doc/lispref/debugging.texi                         |   19 +-
 doc/lispref/display.texi                           |   16 +-
 doc/lispref/edebug.texi                            |    2 +-
 doc/lispref/elisp.texi                             |    3 +-
 doc/lispref/errors.texi                            |    2 +-
 doc/lispref/eval.texi                              |   21 +-
 doc/lispref/files.texi                             |    9 +-
 doc/lispref/frames.texi                            |    8 +-
 doc/lispref/functions.texi                         |   55 +-
 doc/lispref/hash.texi                              |   56 +-
 doc/lispref/help.texi                              |    2 +-
 doc/lispref/hooks.texi                             |    2 +-
 doc/lispref/internals.texi                         |   12 +-
 doc/lispref/intro.texi                             |    2 +-
 doc/lispref/keymaps.texi                           |    4 +-
 doc/lispref/lay-flat.texi                          |    2 +-
 doc/lispref/lists.texi                             |    2 +-
 doc/lispref/loading.texi                           |   15 +-
 doc/lispref/macros.texi                            |    2 +-
 doc/lispref/maps.texi                              |    2 +-
 doc/lispref/markers.texi                           |    2 +-
 doc/lispref/minibuf.texi                           |   42 +-
 doc/lispref/modes.texi                             |   40 +-
 doc/lispref/nonascii.texi                          |    2 +-
 doc/lispref/numbers.texi                           |    2 +-
 doc/lispref/objects.texi                           |   20 +-
 doc/lispref/os.texi                                |    4 +-
 doc/lispref/package.texi                           |   11 +-
 doc/lispref/parsing.texi                           |    2 +-
 doc/lispref/positions.texi                         |    2 +-
 doc/lispref/processes.texi                         |   30 +-
 doc/lispref/records.texi                           |    2 +-
 doc/lispref/searching.texi                         |    4 +-
 doc/lispref/sequences.texi                         |   42 +-
 doc/lispref/streams.texi                           |    4 +-
 doc/lispref/strings.texi                           |    4 +-
 doc/lispref/symbols.texi                           |    4 +-
 doc/lispref/syntax.texi                            |    2 +-
 doc/lispref/text.texi                              |  114 +-
 doc/lispref/threads.texi                           |    2 +-
 doc/lispref/tips.texi                              |    2 +-
 doc/lispref/two-volume-cross-refs.txt              |    2 +-
 doc/lispref/two-volume.make                        |    2 +-
 doc/lispref/variables.texi                         |   35 +-
 doc/lispref/windows.texi                           |   45 +-
 doc/man/ChangeLog.1                                |    2 +-
 doc/man/ebrowse.1                                  |    2 +-
 doc/man/emacs.1.in                                 |    2 +-
 doc/man/emacsclient.1                              |   62 +-
 doc/man/etags.1                                    |    2 +-
 doc/misc/ChangeLog.1                               |    4 +-
 doc/misc/Makefile.in                               |    2 +-
 doc/misc/auth.texi                                 |    2 +-
 doc/misc/autotype.texi                             |    2 +-
 doc/misc/bovine.texi                               |    2 +-
 doc/misc/calc.texi                                 |   20 +-
 doc/misc/cc-mode.texi                              |    2 +-
 doc/misc/cl.texi                                   |    2 +-
 doc/misc/dbus.texi                                 |    2 +-
 doc/misc/dired-x.texi                              |    2 +-
 doc/misc/ebrowse.texi                              |    2 +-
 doc/misc/ede.texi                                  |    2 +-
 doc/misc/ediff.texi                                |    2 +-
 doc/misc/edt.texi                                  |    2 +-
 doc/misc/efaq-w32.texi                             |    2 +-
 doc/misc/efaq.texi                                 |   12 +-
 doc/misc/eglot.texi                                |   92 +-
 doc/misc/eieio.texi                                |    2 +-
 doc/misc/emacs-gnutls.texi                         |    2 +-
 doc/misc/emacs-mime.texi                           |    2 +-
 doc/misc/epa.texi                                  |    6 +-
 doc/misc/erc.texi                                  |  107 +-
 doc/misc/ert.texi                                  |   99 +-
 doc/misc/eshell.texi                               |   29 +-
 doc/misc/eudc.texi                                 |    2 +-
 doc/misc/eww.texi                                  |    2 +-
 doc/misc/flymake.texi                              |    2 +-
 doc/misc/forms.texi                                |    2 +-
 doc/misc/gnus-faq.texi                             |    2 +-
 doc/misc/gnus.texi                                 |   39 +-
 doc/misc/htmlfontify.texi                          |    2 +-
 doc/misc/idlwave.texi                              |    2 +-
 doc/misc/ido.texi                                  |    2 +-
 doc/misc/info.texi                                 |    3 +-
 doc/misc/mairix-el.texi                            |    2 +-
 doc/misc/message.texi                              |    2 +-
 doc/misc/mh-e.texi                                 |    2 +-
 doc/misc/modus-themes.org                          |   24 +-
 doc/misc/newsticker.texi                           |    2 +-
 doc/misc/nxml-mode.texi                            |    2 +-
 doc/misc/octave-mode.texi                          |    2 +-
 doc/misc/org-setup.org                             |    2 +-
 doc/misc/org.org                                   |    6 +-
 doc/misc/pcl-cvs.texi                              |    2 +-
 doc/misc/pgg.texi                                  |    2 +-
 doc/misc/rcirc.texi                                |    6 +-
 doc/misc/reftex.texi                               |    2 +-
 doc/misc/remember.texi                             |    2 +-
 doc/misc/sasl.texi                                 |    2 +-
 doc/misc/sc.texi                                   |    2 +-
 doc/misc/sem-user.texi                             |    2 +-
 doc/misc/semantic.texi                             |    2 +-
 doc/misc/ses.texi                                  |  282 +-
 doc/misc/sieve.texi                                |    2 +-
 doc/misc/smtpmail.texi                             |    2 +-
 doc/misc/speedbar.texi                             |    2 +-
 doc/misc/srecode.texi                              |    2 +-
 doc/misc/texinfo.tex                               |   54 +-
 doc/misc/todo-mode.texi                            |    2 +-
 doc/misc/tramp.texi                                |   55 +-
 doc/misc/trampver.texi                             |    4 +-
 doc/misc/transient.texi                            |  971 +++---
 doc/misc/url.texi                                  |    4 +-
 doc/misc/use-package.texi                          |    2 +-
 doc/misc/vhdl-mode.texi                            |    2 +-
 doc/misc/vip.texi                                  |    2 +-
 doc/misc/viper.texi                                |    2 +-
 doc/misc/vtable.texi                               |    2 +-
 doc/misc/widget.texi                               |  230 +-
 doc/misc/wisent.texi                               |    2 +-
 doc/misc/woman.texi                                |    2 +-
 etc/CALC-NEWS                                      |    2 +-
 etc/ChangeLog.1                                    |    2 +-
 etc/DEBUG                                          |   57 +-
 etc/DISTRIB                                        |    2 +-
 etc/EGLOT-NEWS                                     |   83 +-
 etc/ERC-NEWS                                       |  207 +-
 etc/ETAGS.EBNF                                     |    2 +-
 etc/ETAGS.README                                   |    2 +-
 etc/HELLO                                          |    2 +-
 etc/HISTORY                                        |    2 +
 etc/MACHINES                                       |    2 +-
 etc/MH-E-NEWS                                      |    2 +-
 etc/NEWS                                           |  415 ++-
 etc/NEWS.1-17                                      |    2 +-
 etc/NEWS.18                                        |    2 +-
 etc/NEWS.19                                        |    2 +-
 etc/NEWS.20                                        |    2 +-
 etc/NEWS.21                                        |    2 +-
 etc/NEWS.22                                        |    2 +-
 etc/NEWS.23                                        |    2 +-
 etc/NEWS.24                                        |    2 +-
 etc/NEWS.25                                        |    2 +-
 etc/NEWS.26                                        |    2 +-
 etc/NEWS.27                                        |    3 +-
 etc/NEWS.28                                        |    2 +-
 etc/NEWS.29                                        |   47 +-
 etc/NEXTSTEP                                       |    2 +-
 etc/NXML-NEWS                                      |    2 +-
 etc/ORG-NEWS                                       |    4 +-
 etc/PROBLEMS                                       |  140 +-
 etc/README                                         |    2 +-
 etc/TERMS                                          |    2 +-
 etc/TODO                                           |   18 +-
 etc/charsets/README                                |    2 +-
 etc/compilation.txt                                |   15 +-
 etc/edt-user.el                                    |    2 +-
 etc/emacs-buffer.gdb                               |    2 +-
 etc/emacs.metainfo.xml                             |    2 +-
 etc/emacs_lldb.py                                  |    2 +-
 etc/enriched.txt                                   |    2 +-
 etc/forms/forms-d2.el                              |    2 +-
 etc/gnus-tut.txt                                   |    2 +-
 etc/grep.txt                                       |    2 +-
 etc/images/README                                  |   19 +-
 etc/images/commit.pbm                              |  Bin 0 -> 81 bytes
 etc/images/commit.xpm                              |  101 +
 etc/images/custom/README                           |    2 +-
 etc/images/ezimage/README                          |    2 +-
 etc/images/gen-changelog.pbm                       |  Bin 0 -> 81 bytes
 etc/images/gen-changelog.xpm                       |  152 +
 etc/images/gnus/README                             |    6 +-
 etc/images/gnus/gnus-pointer.svg                   |    2 +-
 etc/images/gnus/gnus.svg                           |    2 +-
 etc/images/gud/README                              |    2 +-
 etc/images/icons/README                            |    8 +-
 etc/images/icons/hicolor/scalable/apps/emacs.svg   |    2 +-
 etc/images/icons/hicolor/scalable/apps/emacs23.svg |    2 +-
 .../scalable/mimetypes/emacs-document23.svg        |    2 +-
 etc/images/ins-changelog.pbm                       |    3 +
 etc/images/ins-changelog.xpm                       |   67 +
 etc/images/load-changelog.pbm                      |  Bin 0 -> 81 bytes
 etc/images/load-changelog.xpm                      |   82 +
 etc/images/mpc/README                              |    2 +-
 etc/images/newsticker/README                       |    2 +-
 etc/images/smilies/README                          |    2 +-
 etc/images/smilies/grayscale/README                |    2 +-
 etc/images/smilies/medium/README                   |    2 +-
 etc/images/splash.svg                              |    2 +-
 etc/images/symbols/README                          |    2 +-
 etc/images/symbols/minus_16.pbm                    |  Bin 41 -> 41 bytes
 etc/images/symbols/minus_16.svg                    |    2 +-
 etc/images/symbols/plus_16.pbm                     |  Bin 41 -> 41 bytes
 etc/images/symbols/plus_16.svg                     |    2 +-
 etc/images/tabs/README                             |    2 +-
 etc/images/tree-widget/default/README              |    2 +-
 etc/images/tree-widget/folder/README               |    2 +-
 etc/images/view-diff.pbm                           |  Bin 0 -> 81 bytes
 etc/images/view-diff.xpm                           |   93 +
 etc/org.gnu.emacs.defaults.gschema.xml             |    2 +-
 etc/org/README                                     |    2 +-
 etc/ps-prin0.ps                                    |    2 +-
 etc/ps-prin1.ps                                    |    2 +-
 etc/publicsuffix.txt                               |  573 +++-
 etc/refcards/Makefile                              |    2 +-
 etc/refcards/README                                |    4 +-
 etc/refcards/calccard.tex                          |    2 +-
 etc/refcards/cs-dired-ref.tex                      |    2 +-
 etc/refcards/cs-refcard.tex                        |    2 +-
 etc/refcards/cs-survival.tex                       |    2 +-
 etc/refcards/de-refcard.tex                        |    2 +-
 etc/refcards/dired-ref.tex                         |    2 +-
 etc/refcards/emacsver.tex.in                       |    2 +-
 etc/refcards/fr-dired-ref.tex                      |    2 +-
 etc/refcards/fr-refcard.tex                        |    2 +-
 etc/refcards/fr-survival.tex                       |    2 +-
 etc/refcards/gnus-logo.eps                         |    2 +-
 etc/refcards/gnus-refcard.tex                      |    2 +-
 etc/refcards/orgcard.tex                           |    4 +-
 etc/refcards/pdflayout.sty                         |    2 +-
 etc/refcards/pl-refcard.tex                        |    2 +-
 etc/refcards/pt-br-refcard.tex                     |    2 +-
 etc/refcards/refcard.tex                           |    2 +-
 etc/refcards/ru-refcard.tex                        |    6 +-
 etc/refcards/sk-dired-ref.tex                      |    2 +-
 etc/refcards/sk-refcard.tex                        |    2 +-
 etc/refcards/sk-survival.tex                       |    2 +-
 etc/refcards/survival.tex                          |    2 +-
 etc/refcards/vipcard.tex                           |    2 +-
 etc/refcards/viperCard.tex                         |    2 +-
 etc/schema/locate.rnc                              |    2 +-
 etc/schema/relaxng.rnc                             |    2 +-
 etc/schema/schemas.xml                             |    2 +-
 etc/ses-example.ses                                |    2 +-
 etc/srecode/c.srt                                  |    2 +-
 etc/srecode/cpp.srt                                |    2 +-
 etc/srecode/default.srt                            |    2 +-
 etc/srecode/doc-cpp.srt                            |    2 +-
 etc/srecode/doc-default.srt                        |    2 +-
 etc/srecode/doc-java.srt                           |    2 +-
 etc/srecode/ede-autoconf.srt                       |    2 +-
 etc/srecode/ede-make.srt                           |    2 +-
 etc/srecode/el.srt                                 |    2 +-
 etc/srecode/getset-cpp.srt                         |    2 +-
 etc/srecode/java.srt                               |    2 +-
 etc/srecode/make.srt                               |    2 +-
 etc/srecode/proj-test.srt                          |    2 +-
 etc/srecode/template.srt                           |    2 +-
 etc/srecode/test.srt                               |    2 +-
 etc/srecode/texi.srt                               |    2 +-
 etc/srecode/wisent.srt                             |    2 +-
 etc/themes/adwaita-theme.el                        |    2 +-
 etc/themes/deeper-blue-theme.el                    |    2 +-
 etc/themes/dichromacy-theme.el                     |    2 +-
 etc/themes/leuven-dark-theme.el                    |    2 +-
 etc/themes/leuven-theme.el                         |    2 +-
 etc/themes/light-blue-theme.el                     |    2 +-
 etc/themes/manoj-dark-theme.el                     |   15 +-
 etc/themes/misterioso-theme.el                     |    2 +-
 etc/themes/modus-operandi-deuteranopia-theme.el    |    2 +-
 etc/themes/modus-operandi-theme.el                 |    2 +-
 etc/themes/modus-operandi-tinted-theme.el          |    6 +-
 etc/themes/modus-operandi-tritanopia-theme.el      |    2 +-
 etc/themes/modus-themes.el                         |    4 +-
 etc/themes/modus-vivendi-deuteranopia-theme.el     |    2 +-
 etc/themes/modus-vivendi-theme.el                  |    2 +-
 etc/themes/modus-vivendi-tinted-theme.el           |    2 +-
 etc/themes/modus-vivendi-tritanopia-theme.el       |    2 +-
 etc/themes/tango-dark-theme.el                     |    2 +-
 etc/themes/tango-theme.el                          |    2 +-
 etc/themes/tsdh-dark-theme.el                      |    2 +-
 etc/themes/tsdh-light-theme.el                     |    2 +-
 etc/themes/wheatgrass-theme.el                     |    2 +-
 etc/themes/whiteboard-theme.el                     |    2 +-
 etc/themes/wombat-theme.el                         |    2 +-
 etc/tutorials/TUTORIAL                             |    2 +-
 etc/tutorials/TUTORIAL.bg                          |    2 +-
 etc/tutorials/TUTORIAL.cn                          |    4 +-
 etc/tutorials/TUTORIAL.cs                          |    2 +-
 etc/tutorials/TUTORIAL.de                          |    2 +-
 etc/tutorials/TUTORIAL.el_GR                       |    2 +-
 etc/tutorials/TUTORIAL.eo                          |    2 +-
 etc/tutorials/TUTORIAL.es                          |    2 +-
 etc/tutorials/TUTORIAL.fa                          |    3 +-
 etc/tutorials/TUTORIAL.fr                          |    2 +-
 etc/tutorials/TUTORIAL.he                          |    2 +-
 etc/tutorials/TUTORIAL.it                          |    2 +-
 etc/tutorials/TUTORIAL.ja                          |    2 +-
 etc/tutorials/TUTORIAL.ko                          |    2 +-
 etc/tutorials/TUTORIAL.nl                          |    4 +-
 etc/tutorials/TUTORIAL.pl                          |   16 +-
 etc/tutorials/TUTORIAL.pt_BR                       |    2 +-
 etc/tutorials/TUTORIAL.ro                          |    4 +-
 etc/tutorials/TUTORIAL.ru                          |    2 +-
 etc/tutorials/TUTORIAL.sk                          |    2 +-
 etc/tutorials/TUTORIAL.sl                          |    2 +-
 etc/tutorials/TUTORIAL.sv                          |    2 +-
 etc/tutorials/TUTORIAL.th                          |    2 +-
 etc/tutorials/TUTORIAL.uk                          |    2 +-
 etc/tutorials/TUTORIAL.zh                          |    2 +-
 etc/w32-feature.el                                 |    2 +-
 exec/Makefile.in                                   |    7 +-
 exec/config-mips.m4.in                             |    2 +-
 exec/config.guess                                  | 1803 ------------
 exec/config.sub                                    | 1895 ------------
 exec/configure.ac                                  |   21 +-
 exec/deps.mk                                       |    2 +-
 exec/exec.c                                        |    2 +-
 exec/exec.h                                        |    6 +-
 exec/exec1.c                                       |    4 +-
 exec/install-sh                                    |  541 ----
 exec/loader-aarch64.s                              |    2 +-
 exec/loader-armeabi.s                              |    4 +-
 exec/loader-mips64el.s                             |    4 +-
 exec/loader-mipsel.s                               |    4 +-
 exec/loader-x86.s                                  |    2 +-
 exec/loader-x86_64.s                               |    2 +-
 exec/mipsel-user.h                                 |    2 +-
 exec/mipsfpu.c                                     |    2 +-
 exec/mipsfpu.h                                     |    2 +-
 exec/test.c                                        |    2 +-
 exec/trace.c                                       |  139 +-
 java/AndroidManifest.xml.in                        |    6 +-
 java/INSTALL                                       |    6 +-
 java/Makefile.in                                   |    2 +-
 java/debug.sh                                      |    2 +-
 java/org/gnu/emacs/EmacsActivity.java              |    2 +-
 java/org/gnu/emacs/EmacsApplication.java           |    2 +-
 java/org/gnu/emacs/EmacsClipboard.java             |    2 +-
 java/org/gnu/emacs/EmacsContextMenu.java           |   32 +-
 java/org/gnu/emacs/EmacsCursor.java                |    2 +-
 java/org/gnu/emacs/EmacsDesktopNotification.java   |    2 +-
 java/org/gnu/emacs/EmacsDialog.java                |   27 +-
 java/org/gnu/emacs/EmacsDialogButtonLayout.java    |    2 +-
 java/org/gnu/emacs/EmacsDirectoryEntry.java        |    2 +-
 java/org/gnu/emacs/EmacsDocumentsProvider.java     |    2 +-
 java/org/gnu/emacs/EmacsDrawLine.java              |    2 +-
 java/org/gnu/emacs/EmacsDrawPoint.java             |    2 +-
 java/org/gnu/emacs/EmacsDrawRectangle.java         |    2 +-
 java/org/gnu/emacs/EmacsDrawable.java              |    2 +-
 java/org/gnu/emacs/EmacsFillPolygon.java           |    2 +-
 java/org/gnu/emacs/EmacsFillRectangle.java         |    2 +-
 java/org/gnu/emacs/EmacsFontDriver.java            |    2 +-
 java/org/gnu/emacs/EmacsGC.java                    |    2 +-
 java/org/gnu/emacs/EmacsHandleObject.java          |    2 +-
 java/org/gnu/emacs/EmacsHolder.java                |    2 +-
 java/org/gnu/emacs/EmacsInputConnection.java       |    4 +-
 .../emacs/EmacsLauncherPreferencesActivity.java    |    2 +-
 java/org/gnu/emacs/EmacsMultitaskActivity.java     |    2 +-
 java/org/gnu/emacs/EmacsNative.java                |    2 +-
 java/org/gnu/emacs/EmacsNoninteractive.java        |    2 +-
 java/org/gnu/emacs/EmacsOpenActivity.java          |    4 +-
 java/org/gnu/emacs/EmacsPixmap.java                |    2 +-
 java/org/gnu/emacs/EmacsPreferencesActivity.java   |    2 +-
 java/org/gnu/emacs/EmacsSafThread.java             |   14 +-
 java/org/gnu/emacs/EmacsSdk11Clipboard.java        |    2 +-
 java/org/gnu/emacs/EmacsSdk23FontDriver.java       |    2 +-
 java/org/gnu/emacs/EmacsSdk7FontDriver.java        |    2 +-
 java/org/gnu/emacs/EmacsSdk8Clipboard.java         |    2 +-
 java/org/gnu/emacs/EmacsService.java               |  218 +-
 java/org/gnu/emacs/EmacsSurfaceView.java           |    2 +-
 java/org/gnu/emacs/EmacsThread.java                |    2 +-
 java/org/gnu/emacs/EmacsView.java                  |   31 +-
 java/org/gnu/emacs/EmacsWindow.java                |   62 +-
 .../gnu/emacs/EmacsWindowAttachmentManager.java    |    2 +-
 java/res/drawable/emacs_background.xml             |    2 +-
 java/res/drawable/emacs_foreground.xml             |    2 +-
 java/res/layout/sdk8_notifications_view.xml        |    2 +-
 java/res/mipmap-v26/emacs_icon.xml                 |    2 +-
 java/res/values-v11/style.xml                      |    2 +-
 java/res/values-v14/style.xml                      |    2 +-
 java/res/values-v19/bool.xml                       |    2 +-
 java/res/values-v24/bool.xml                       |    2 +-
 java/res/values-v29/style.xml                      |    2 +-
 java/res/values/bool.xml                           |    2 +-
 java/res/values/strings.xml                        |    2 +-
 java/res/values/style.xml                          |    2 +-
 java/res/xml/preferences.xml                       |    2 +-
 leim/ChangeLog.1                                   |    2 +-
 leim/Makefile.in                                   |    2 +-
 leim/README                                        |    2 +-
 leim/leim-ext.el                                   |    2 +-
 lib-src/ChangeLog.1                                |    2 +-
 lib-src/Makefile.in                                |    2 +-
 lib-src/asset-directory-tool.c                     |    2 +-
 lib-src/be_resources.cc                            |    2 +-
 lib-src/ebrowse.c                                  |    2 +-
 lib-src/emacsclient.c                              |    2 +-
 lib-src/etags.c                                    |    8 +-
 lib-src/hexl.c                                     |    2 +-
 lib-src/make-docfile.c                             |    2 +-
 lib-src/make-fingerprint.c                         |    2 +-
 lib-src/movemail.c                                 |    2 +-
 lib-src/ntlib.c                                    |    2 +-
 lib-src/ntlib.h                                    |    2 +-
 lib-src/pop.c                                      |    2 +-
 lib-src/pop.h                                      |    2 +-
 lib-src/rcs2log                                    |    4 +-
 lib-src/seccomp-filter.c                           |    6 +-
 lib-src/update-game-score.c                        |    2 +-
 lib/Makefile.in                                    |    2 +-
 lib/_Noreturn.h                                    |    2 +-
 lib/acl-errno-valid.c                              |    2 +-
 lib/acl-internal.c                                 |    2 +-
 lib/acl-internal.h                                 |    5 +-
 lib/acl.h                                          |    2 +-
 lib/acl_entries.c                                  |    2 +-
 lib/af_alg.h                                       |    2 +-
 lib/alloca.in.h                                    |    2 +-
 lib/allocator.c                                    |    2 +-
 lib/allocator.h                                    |    2 +-
 lib/arg-nonnull.h                                  |    2 +-
 lib/assert.in.h                                    |    2 +-
 lib/at-func.c                                      |    2 +-
 lib/attribute.h                                    |    4 +-
 lib/binary-io.c                                    |    2 +-
 lib/binary-io.h                                    |    2 +-
 lib/boot-time-aux.h                                |   18 +-
 lib/boot-time.c                                    |   11 +-
 lib/boot-time.h                                    |    2 +-
 lib/byteswap.in.h                                  |    2 +-
 lib/c++defs.h                                      |    2 +-
 lib/c-ctype.c                                      |    2 +-
 lib/c-ctype.h                                      |    2 +-
 lib/c-strcase.h                                    |    2 +-
 lib/c-strcasecmp.c                                 |    2 +-
 lib/c-strncasecmp.c                                |    2 +-
 lib/canonicalize-lgpl.c                            |    2 +-
 lib/careadlinkat.c                                 |    2 +-
 lib/careadlinkat.h                                 |    2 +-
 lib/cdefs.h                                        |    6 +-
 lib/cloexec.c                                      |    2 +-
 lib/cloexec.h                                      |    2 +-
 lib/close-stream.c                                 |    2 +-
 lib/close-stream.h                                 |    2 +-
 lib/copy-file-range.c                              |    2 +-
 lib/count-leading-zeros.c                          |    2 +-
 lib/count-leading-zeros.h                          |    2 +-
 lib/count-one-bits.c                               |    2 +-
 lib/count-one-bits.h                               |    2 +-
 lib/count-trailing-zeros.c                         |    2 +-
 lib/count-trailing-zeros.h                         |    2 +-
 lib/diffseq.h                                      |    2 +-
 lib/dirent-private.h                               |    2 +-
 lib/dirent.in.h                                    |    8 +-
 lib/dirfd.c                                        |   67 +-
 lib/dtoastr.c                                      |    2 +-
 lib/dtotimespec.c                                  |    2 +-
 lib/dup2.c                                         |    2 +-
 lib/dynarray.h                                     |    2 +-
 lib/eloop-threshold.h                              |    2 +-
 lib/errno.in.h                                     |    2 +-
 lib/euidaccess.c                                   |    2 +-
 lib/execinfo.c                                     |    2 +-
 lib/execinfo.in.h                                  |    2 +-
 lib/explicit_bzero.c                               |    2 +-
 lib/faccessat.c                                    |    8 +-
 lib/fchmodat.c                                     |    2 +-
 lib/fcntl.c                                        |    2 +-
 lib/fcntl.in.h                                     |    2 +-
 lib/fdopendir.c                                    |   38 +-
 lib/file-has-acl.c                                 |    2 +-
 lib/filemode.c                                     |    2 +-
 lib/filemode.h                                     |    2 +-
 lib/filename.h                                     |    2 +-
 lib/filevercmp.c                                   |    2 +-
 lib/filevercmp.h                                   |    2 +-
 lib/fingerprint.c                                  |    2 +-
 lib/fingerprint.h                                  |    2 +-
 lib/flexmember.h                                   |    2 +-
 lib/fpending.c                                     |    2 +-
 lib/fpending.h                                     |    2 +-
 lib/free.c                                         |    2 +-
 lib/fstatat.c                                      |    2 +-
 lib/fsusage.c                                      |    2 +-
 lib/fsusage.h                                      |    2 +-
 lib/fsync.c                                        |    2 +-
 lib/ftoastr.c                                      |    2 +-
 lib/ftoastr.h                                      |    2 +-
 lib/futimens.c                                     |    2 +-
 lib/get-permissions.c                              |    2 +-
 lib/getdelim.c                                     |    2 +-
 lib/getdtablesize.c                                |    2 +-
 lib/getgroups.c                                    |    2 +-
 lib/getline.c                                      |    2 +-
 lib/getloadavg.c                                   |    2 +-
 lib/getopt-cdefs.in.h                              |    8 +-
 lib/getopt-core.h                                  |    2 +-
 lib/getopt-ext.h                                   |    2 +-
 lib/getopt-pfx-core.h                              |    2 +-
 lib/getopt-pfx-ext.h                               |    2 +-
 lib/getopt.c                                       |   35 +-
 lib/getopt.in.h                                    |    2 +-
 lib/getopt1.c                                      |    4 +-
 lib/getopt_int.h                                   |    2 +-
 lib/getrandom.c                                    |    2 +-
 lib/gettext.h                                      |    2 +-
 lib/gettime.c                                      |    2 +-
 lib/gettimeofday.c                                 |    2 +-
 lib/gnulib.mk.in                                   |   15 +-
 lib/group-member.c                                 |    2 +-
 lib/idx.h                                          |    2 +-
 lib/ieee754.in.h                                   |    2 +-
 lib/ignore-value.h                                 |    2 +-
 lib/intprops-internal.h                            |    7 +-
 lib/intprops.h                                     |    2 +-
 lib/inttypes.in.h                                  |    2 +-
 lib/lchmod.c                                       |    2 +-
 lib/libc-config.h                                  |    2 +-
 lib/limits.in.h                                    |    2 +-
 lib/lstat.c                                        |    2 +-
 lib/malloc.c                                       |    2 +-
 lib/malloc/dynarray-skeleton.c                     |    2 +-
 lib/malloc/dynarray.h                              |    2 +-
 lib/malloc/dynarray_at_failure.c                   |    2 +-
 lib/malloc/dynarray_emplace_enlarge.c              |    2 +-
 lib/malloc/dynarray_finalize.c                     |    2 +-
 lib/malloc/dynarray_resize.c                       |    2 +-
 lib/malloc/dynarray_resize_clear.c                 |    2 +-
 lib/malloc/scratch_buffer.h                        |    2 +-
 lib/malloc/scratch_buffer_dupfree.c                |    2 +-
 lib/malloc/scratch_buffer_grow.c                   |    2 +-
 lib/malloc/scratch_buffer_grow_preserve.c          |    2 +-
 lib/malloc/scratch_buffer_set_array_size.c         |    2 +-
 lib/md5-stream.c                                   |    2 +-
 lib/md5.c                                          |    2 +-
 lib/md5.h                                          |   24 +-
 lib/memmem.c                                       |    2 +-
 lib/mempcpy.c                                      |    2 +-
 lib/memrchr.c                                      |    2 +-
 lib/memset_explicit.c                              |    2 +-
 lib/mini-gmp-gnulib.c                              |    2 +-
 lib/minmax.h                                       |    2 +-
 lib/mkostemp.c                                     |    2 +-
 lib/mktime-internal.h                              |    2 +-
 lib/mktime.c                                       |    2 +-
 lib/nanosleep.c                                    |    2 +-
 lib/nproc.c                                        |    2 +-
 lib/nproc.h                                        |    2 +-
 lib/nstrftime.c                                    |    2 +-
 lib/open.c                                         |    8 +-
 lib/openat-priv.h                                  |    2 +-
 lib/openat-proc.c                                  |    2 +-
 lib/openat.h                                       |    2 +-
 lib/pathmax.h                                      |    2 +-
 lib/pipe2.c                                        |    2 +-
 lib/pselect.c                                      |    2 +-
 lib/pthread_sigmask.c                              |    2 +-
 lib/qcopy-acl.c                                    |    2 +-
 lib/rawmemchr.c                                    |   28 +-
 lib/rawmemchr.valgrind                             |    2 +-
 lib/readlink.c                                     |    2 +-
 lib/readlinkat.c                                   |    2 +-
 lib/readutmp.h                                     |   26 +-
 lib/realloc.c                                      |    2 +-
 lib/regcomp.c                                      |    2 +-
 lib/regex.c                                        |    6 +-
 lib/regex.h                                        |    2 +-
 lib/regex_internal.c                               |    2 +-
 lib/regex_internal.h                               |    2 +-
 lib/regexec.c                                      |    2 +-
 lib/root-uid.h                                     |    2 +-
 lib/save-cwd.c                                     |    2 +-
 lib/save-cwd.h                                     |    2 +-
 lib/scratch_buffer.h                               |    2 +-
 lib/set-permissions.c                              |    3 +-
 lib/sha1.c                                         |    2 +-
 lib/sha1.h                                         |   18 +-
 lib/sha256.c                                       |    2 +-
 lib/sha256.h                                       |   18 +-
 lib/sha512.c                                       |    2 +-
 lib/sha512.h                                       |   18 +-
 lib/sig2str.c                                      |    2 +-
 lib/sig2str.h                                      |    2 +-
 lib/sigdescr_np.c                                  |    2 +-
 lib/signal.in.h                                    |    2 +-
 lib/stat-time.c                                    |    2 +-
 lib/stat-time.h                                    |   15 +-
 lib/stdalign.in.h                                  |    2 +-
 lib/stdckdint.in.h                                 |    2 +-
 lib/stddef.in.h                                    |   30 +-
 lib/stdint.in.h                                    |    4 +-
 lib/stdio-impl.h                                   |    2 +-
 lib/stdio.in.h                                     |   53 +-
 lib/stdlib.in.h                                    |  144 +-
 lib/stpcpy.c                                       |    2 +-
 lib/str-two-way.h                                  |    2 +-
 lib/strftime.h                                     |    2 +-
 lib/string.in.h                                    |  141 +-
 lib/strnlen.c                                      |    2 +-
 lib/strtoimax.c                                    |    2 +-
 lib/strtol.c                                       |    2 +-
 lib/strtoll.c                                      |    2 +-
 lib/symlink.c                                      |    2 +-
 lib/sys_random.in.h                                |    2 +-
 lib/sys_select.in.h                                |    2 +-
 lib/sys_stat.in.h                                  |   32 +-
 lib/sys_time.in.h                                  |    2 +-
 lib/sys_types.in.h                                 |    2 +-
 lib/tempname.c                                     |    6 +-
 lib/tempname.h                                     |    2 +-
 lib/time-internal.h                                |    2 +-
 lib/time.in.h                                      |   16 +-
 lib/time_r.c                                       |    2 +-
 lib/time_rz.c                                      |    2 +-
 lib/timegm.c                                       |    2 +-
 lib/timespec-add.c                                 |    2 +-
 lib/timespec-sub.c                                 |    2 +-
 lib/timespec.c                                     |    2 +-
 lib/timespec.h                                     |    2 +-
 lib/u64.c                                          |    2 +-
 lib/u64.h                                          |    2 +-
 lib/unistd.c                                       |    4 +-
 lib/unistd.in.h                                    |   33 +-
 lib/unlocked-io.h                                  |    4 +-
 lib/utimens.c                                      |    6 +-
 lib/utimens.h                                      |    2 +-
 lib/utimensat.c                                    |    2 +-
 lib/verify.h                                       |   12 +-
 lib/vla.h                                          |    2 +-
 lib/warn-on-use.h                                  |    2 +-
 lib/xalloc-oversized.h                             |   10 +-
 lisp/ChangeLog.1                                   |    2 +-
 lisp/ChangeLog.10                                  |    2 +-
 lisp/ChangeLog.11                                  |    2 +-
 lisp/ChangeLog.12                                  |    4 +-
 lisp/ChangeLog.13                                  |    4 +-
 lisp/ChangeLog.14                                  |    8 +-
 lisp/ChangeLog.15                                  |    4 +-
 lisp/ChangeLog.16                                  |    6 +-
 lisp/ChangeLog.17                                  |    4 +-
 lisp/ChangeLog.2                                   |    2 +-
 lisp/ChangeLog.3                                   |    2 +-
 lisp/ChangeLog.4                                   |    2 +-
 lisp/ChangeLog.5                                   |    2 +-
 lisp/ChangeLog.6                                   |    2 +-
 lisp/ChangeLog.7                                   |    4 +-
 lisp/ChangeLog.8                                   |    2 +-
 lisp/ChangeLog.9                                   |    2 +-
 lisp/Makefile.in                                   |    2 +-
 lisp/abbrev.el                                     |    4 +-
 lisp/align.el                                      |    2 +-
 lisp/allout-widgets.el                             |    2 +-
 lisp/allout.el                                     |    6 +-
 lisp/ansi-color.el                                 |    2 +-
 lisp/ansi-osc.el                                   |    5 +-
 lisp/apropos.el                                    |    2 +-
 lisp/arc-mode.el                                   |   20 +-
 lisp/array.el                                      |    2 +-
 lisp/auth-source-pass.el                           |    2 +-
 lisp/auth-source.el                                |   21 +-
 lisp/autoinsert.el                                 |    2 +-
 lisp/autorevert.el                                 |    2 +-
 lisp/avoid.el                                      |    2 +-
 lisp/battery.el                                    |    2 +-
 lisp/bind-key.el                                   |    2 +-
 lisp/bindings.el                                   |    2 +-
 lisp/bookmark.el                                   |    4 +-
 lisp/bs.el                                         |    2 +-
 lisp/buff-menu.el                                  |   20 +-
 lisp/button.el                                     |    4 +-
 lisp/calc/calc-aent.el                             |   48 +-
 lisp/calc/calc-alg.el                              |    2 +-
 lisp/calc/calc-arith.el                            |    2 +-
 lisp/calc/calc-bin.el                              |    2 +-
 lisp/calc/calc-comb.el                             |    2 +-
 lisp/calc/calc-cplx.el                             |    2 +-
 lisp/calc/calc-embed.el                            |    2 +-
 lisp/calc/calc-ext.el                              |    2 +-
 lisp/calc/calc-fin.el                              |    2 +-
 lisp/calc/calc-forms.el                            |    2 +-
 lisp/calc/calc-frac.el                             |    2 +-
 lisp/calc/calc-funcs.el                            |    2 +-
 lisp/calc/calc-graph.el                            |    2 +-
 lisp/calc/calc-help.el                             |    2 +-
 lisp/calc/calc-incom.el                            |    2 +-
 lisp/calc/calc-keypd.el                            |    2 +-
 lisp/calc/calc-lang.el                             |    2 +-
 lisp/calc/calc-macs.el                             |    2 +-
 lisp/calc/calc-map.el                              |    2 +-
 lisp/calc/calc-math.el                             |    2 +-
 lisp/calc/calc-menu.el                             |    2 +-
 lisp/calc/calc-misc.el                             |    2 +-
 lisp/calc/calc-mode.el                             |    2 +-
 lisp/calc/calc-mtx.el                              |    2 +-
 lisp/calc/calc-nlfit.el                            |    2 +-
 lisp/calc/calc-poly.el                             |    2 +-
 lisp/calc/calc-prog.el                             |    2 +-
 lisp/calc/calc-rewr.el                             |    2 +-
 lisp/calc/calc-rules.el                            |    2 +-
 lisp/calc/calc-sel.el                              |    2 +-
 lisp/calc/calc-stat.el                             |    2 +-
 lisp/calc/calc-store.el                            |    2 +-
 lisp/calc/calc-stuff.el                            |    2 +-
 lisp/calc/calc-trail.el                            |    2 +-
 lisp/calc/calc-undo.el                             |    2 +-
 lisp/calc/calc-units.el                            |    2 +-
 lisp/calc/calc-vec.el                              |    2 +-
 lisp/calc/calc-yank.el                             |    2 +-
 lisp/calc/calc.el                                  |    4 +-
 lisp/calc/calcalg2.el                              |    2 +-
 lisp/calc/calcalg3.el                              |    2 +-
 lisp/calc/calccomp.el                              |    2 +-
 lisp/calc/calcsel2.el                              |    2 +-
 lisp/calculator.el                                 |    2 +-
 lisp/calendar/appt.el                              |    2 +-
 lisp/calendar/cal-bahai.el                         |    2 +-
 lisp/calendar/cal-china.el                         |    2 +-
 lisp/calendar/cal-coptic.el                        |    2 +-
 lisp/calendar/cal-dst.el                           |    2 +-
 lisp/calendar/cal-french.el                        |    2 +-
 lisp/calendar/cal-hebrew.el                        |    2 +-
 lisp/calendar/cal-html.el                          |    2 +-
 lisp/calendar/cal-islam.el                         |    2 +-
 lisp/calendar/cal-iso.el                           |    2 +-
 lisp/calendar/cal-julian.el                        |    2 +-
 lisp/calendar/cal-mayan.el                         |    2 +-
 lisp/calendar/cal-menu.el                          |    2 +-
 lisp/calendar/cal-move.el                          |    2 +-
 lisp/calendar/cal-persia.el                        |    2 +-
 lisp/calendar/cal-tex.el                           |    2 +-
 lisp/calendar/cal-x.el                             |    2 +-
 lisp/calendar/calendar.el                          |   12 +-
 lisp/calendar/diary-lib.el                         |    2 +-
 lisp/calendar/holidays.el                          |    2 +-
 lisp/calendar/icalendar.el                         |    3 +-
 lisp/calendar/iso8601.el                           |    2 +-
 lisp/calendar/lunar.el                             |    2 +-
 lisp/calendar/parse-time.el                        |    2 +-
 lisp/calendar/solar.el                             |    2 +-
 lisp/calendar/time-date.el                         |    3 +-
 lisp/calendar/timeclock.el                         |    2 +-
 lisp/calendar/todo-mode.el                         |   30 +-
 lisp/case-table.el                                 |    2 +-
 lisp/cdl.el                                        |    2 +-
 lisp/cedet/ChangeLog.1                             |    4 +-
 lisp/cedet/cedet-cscope.el                         |    2 +-
 lisp/cedet/cedet-files.el                          |    2 +-
 lisp/cedet/cedet-global.el                         |    2 +-
 lisp/cedet/cedet-idutils.el                        |    2 +-
 lisp/cedet/cedet.el                                |    2 +-
 lisp/cedet/data-debug.el                           |    2 +-
 lisp/cedet/ede.el                                  |    2 +-
 lisp/cedet/ede/auto.el                             |    2 +-
 lisp/cedet/ede/autoconf-edit.el                    |    2 +-
 lisp/cedet/ede/base.el                             |    2 +-
 lisp/cedet/ede/config.el                           |    2 +-
 lisp/cedet/ede/cpp-root.el                         |    2 +-
 lisp/cedet/ede/custom.el                           |    2 +-
 lisp/cedet/ede/detect.el                           |    2 +-
 lisp/cedet/ede/dired.el                            |    2 +-
 lisp/cedet/ede/emacs.el                            |    2 +-
 lisp/cedet/ede/files.el                            |    2 +-
 lisp/cedet/ede/generic.el                          |    2 +-
 lisp/cedet/ede/linux.el                            |    2 +-
 lisp/cedet/ede/locate.el                           |    2 +-
 lisp/cedet/ede/make.el                             |    2 +-
 lisp/cedet/ede/makefile-edit.el                    |    2 +-
 lisp/cedet/ede/pconf.el                            |    2 +-
 lisp/cedet/ede/pmake.el                            |    2 +-
 lisp/cedet/ede/proj-archive.el                     |    2 +-
 lisp/cedet/ede/proj-aux.el                         |    2 +-
 lisp/cedet/ede/proj-comp.el                        |    2 +-
 lisp/cedet/ede/proj-elisp.el                       |    2 +-
 lisp/cedet/ede/proj-info.el                        |    2 +-
 lisp/cedet/ede/proj-misc.el                        |    2 +-
 lisp/cedet/ede/proj-obj.el                         |    2 +-
 lisp/cedet/ede/proj-prog.el                        |    2 +-
 lisp/cedet/ede/proj-scheme.el                      |    2 +-
 lisp/cedet/ede/proj-shared.el                      |    2 +-
 lisp/cedet/ede/proj.el                             |    2 +-
 lisp/cedet/ede/project-am.el                       |    2 +-
 lisp/cedet/ede/shell.el                            |    2 +-
 lisp/cedet/ede/simple.el                           |    2 +-
 lisp/cedet/ede/source.el                           |    2 +-
 lisp/cedet/ede/speedbar.el                         |    2 +-
 lisp/cedet/ede/srecode.el                          |    2 +-
 lisp/cedet/ede/system.el                           |    2 +-
 lisp/cedet/ede/util.el                             |    2 +-
 lisp/cedet/mode-local.el                           |    2 +-
 lisp/cedet/pulse.el                                |    2 +-
 lisp/cedet/semantic.el                             |    2 +-
 lisp/cedet/semantic/analyze.el                     |    2 +-
 lisp/cedet/semantic/analyze/complete.el            |    2 +-
 lisp/cedet/semantic/analyze/debug.el               |    2 +-
 lisp/cedet/semantic/analyze/fcn.el                 |    2 +-
 lisp/cedet/semantic/analyze/refs.el                |    2 +-
 lisp/cedet/semantic/bovine.el                      |    2 +-
 lisp/cedet/semantic/bovine/c.el                    |    2 +-
 lisp/cedet/semantic/bovine/debug.el                |    2 +-
 lisp/cedet/semantic/bovine/el.el                   |    2 +-
 lisp/cedet/semantic/bovine/gcc.el                  |    2 +-
 lisp/cedet/semantic/bovine/grammar.el              |    2 +-
 lisp/cedet/semantic/bovine/make.el                 |    2 +-
 lisp/cedet/semantic/bovine/scm.el                  |    2 +-
 lisp/cedet/semantic/chart.el                       |    2 +-
 lisp/cedet/semantic/complete.el                    |    4 +-
 lisp/cedet/semantic/ctxt.el                        |    2 +-
 lisp/cedet/semantic/db-debug.el                    |    2 +-
 lisp/cedet/semantic/db-ebrowse.el                  |    2 +-
 lisp/cedet/semantic/db-el.el                       |    2 +-
 lisp/cedet/semantic/db-file.el                     |    2 +-
 lisp/cedet/semantic/db-find.el                     |    2 +-
 lisp/cedet/semantic/db-global.el                   |    2 +-
 lisp/cedet/semantic/db-javascript.el               |    2 +-
 lisp/cedet/semantic/db-mode.el                     |    2 +-
 lisp/cedet/semantic/db-ref.el                      |    2 +-
 lisp/cedet/semantic/db-typecache.el                |    2 +-
 lisp/cedet/semantic/db.el                          |    6 +-
 lisp/cedet/semantic/debug.el                       |    2 +-
 lisp/cedet/semantic/decorate.el                    |    2 +-
 lisp/cedet/semantic/decorate/include.el            |    2 +-
 lisp/cedet/semantic/decorate/mode.el               |    2 +-
 lisp/cedet/semantic/dep.el                         |    2 +-
 lisp/cedet/semantic/doc.el                         |    2 +-
 lisp/cedet/semantic/ede-grammar.el                 |    2 +-
 lisp/cedet/semantic/edit.el                        |    2 +-
 lisp/cedet/semantic/find.el                        |    2 +-
 lisp/cedet/semantic/format.el                      |    2 +-
 lisp/cedet/semantic/fw.el                          |    2 +-
 lisp/cedet/semantic/grammar.el                     |    2 +-
 lisp/cedet/semantic/grm-wy-boot.el                 |    2 +-
 lisp/cedet/semantic/html.el                        |    2 +-
 lisp/cedet/semantic/ia-sb.el                       |    2 +-
 lisp/cedet/semantic/ia.el                          |    2 +-
 lisp/cedet/semantic/idle.el                        |    2 +-
 lisp/cedet/semantic/imenu.el                       |    2 +-
 lisp/cedet/semantic/java.el                        |    2 +-
 lisp/cedet/semantic/lex-spp.el                     |    2 +-
 lisp/cedet/semantic/lex.el                         |    2 +-
 lisp/cedet/semantic/mru-bookmark.el                |    2 +-
 lisp/cedet/semantic/sb.el                          |    2 +-
 lisp/cedet/semantic/scope.el                       |    2 +-
 lisp/cedet/semantic/senator.el                     |    2 +-
 lisp/cedet/semantic/sort.el                        |    2 +-
 lisp/cedet/semantic/symref.el                      |    2 +-
 lisp/cedet/semantic/symref/cscope.el               |    2 +-
 lisp/cedet/semantic/symref/filter.el               |    2 +-
 lisp/cedet/semantic/symref/global.el               |    2 +-
 lisp/cedet/semantic/symref/grep.el                 |    2 +-
 lisp/cedet/semantic/symref/idutils.el              |    2 +-
 lisp/cedet/semantic/symref/list.el                 |    2 +-
 lisp/cedet/semantic/tag-file.el                    |    2 +-
 lisp/cedet/semantic/tag-ls.el                      |    2 +-
 lisp/cedet/semantic/tag-write.el                   |    2 +-
 lisp/cedet/semantic/tag.el                         |    2 +-
 lisp/cedet/semantic/texi.el                        |    2 +-
 lisp/cedet/semantic/util-modes.el                  |    2 +-
 lisp/cedet/semantic/util.el                        |    2 +-
 lisp/cedet/semantic/wisent.el                      |    2 +-
 lisp/cedet/semantic/wisent/comp.el                 |    2 +-
 lisp/cedet/semantic/wisent/grammar.el              |    2 +-
 lisp/cedet/semantic/wisent/java-tags.el            |    2 +-
 lisp/cedet/semantic/wisent/javascript.el           |    2 +-
 lisp/cedet/semantic/wisent/python.el               |    2 +-
 lisp/cedet/semantic/wisent/wisent.el               |    2 +-
 lisp/cedet/srecode.el                              |    2 +-
 lisp/cedet/srecode/args.el                         |    2 +-
 lisp/cedet/srecode/compile.el                      |    2 +-
 lisp/cedet/srecode/cpp.el                          |    2 +-
 lisp/cedet/srecode/ctxt.el                         |    2 +-
 lisp/cedet/srecode/dictionary.el                   |    2 +-
 lisp/cedet/srecode/document.el                     |    2 +-
 lisp/cedet/srecode/el.el                           |    2 +-
 lisp/cedet/srecode/expandproto.el                  |    2 +-
 lisp/cedet/srecode/extract.el                      |    4 +-
 lisp/cedet/srecode/fields.el                       |    2 +-
 lisp/cedet/srecode/filters.el                      |    2 +-
 lisp/cedet/srecode/find.el                         |    2 +-
 lisp/cedet/srecode/getset.el                       |    2 +-
 lisp/cedet/srecode/insert.el                       |    2 +-
 lisp/cedet/srecode/java.el                         |    2 +-
 lisp/cedet/srecode/map.el                          |    2 +-
 lisp/cedet/srecode/mode.el                         |    2 +-
 lisp/cedet/srecode/semantic.el                     |    2 +-
 lisp/cedet/srecode/srt-mode.el                     |    4 +-
 lisp/cedet/srecode/srt.el                          |    2 +-
 lisp/cedet/srecode/table.el                        |    2 +-
 lisp/cedet/srecode/template.el                     |    2 +-
 lisp/cedet/srecode/texi.el                         |    2 +-
 lisp/char-fold.el                                  |    4 +-
 lisp/chistory.el                                   |    2 +-
 lisp/cmuscheme.el                                  |    2 +-
 lisp/color.el                                      |    2 +-
 lisp/comint.el                                     |    2 +-
 lisp/completion-preview.el                         |   32 +-
 lisp/completion.el                                 |    2 +-
 lisp/composite.el                                  |    2 +-
 lisp/cus-dep.el                                    |    2 +-
 lisp/cus-edit.el                                   |   62 +-
 lisp/cus-face.el                                   |    4 +-
 lisp/cus-start.el                                  |    4 +-
 lisp/cus-theme.el                                  |    2 +-
 lisp/custom.el                                     |    2 +-
 lisp/dabbrev.el                                    |    2 +-
 lisp/delim-col.el                                  |    2 +-
 lisp/delsel.el                                     |    2 +-
 lisp/descr-text.el                                 |    2 +-
 lisp/desktop.el                                    |   25 +-
 lisp/dframe.el                                     |    2 +-
 lisp/dired-aux.el                                  |   45 +-
 lisp/dired-x.el                                    |    5 +-
 lisp/dired.el                                      |  292 +-
 lisp/dirtrack.el                                   |    2 +-
 lisp/disp-table.el                                 |    2 +-
 lisp/display-fill-column-indicator.el              |    2 +-
 lisp/display-line-numbers.el                       |    2 +-
 lisp/dnd.el                                        |    2 +-
 lisp/doc-view.el                                   |    6 +-
 lisp/dom.el                                        |    4 +-
 lisp/dos-fns.el                                    |    2 +-
 lisp/dos-vars.el                                   |    2 +-
 lisp/dos-w32.el                                    |    2 +-
 lisp/double.el                                     |    2 +-
 lisp/dynamic-setting.el                            |    2 +-
 lisp/ebuff-menu.el                                 |    2 +-
 lisp/echistory.el                                  |    2 +-
 lisp/ecomplete.el                                  |    2 +-
 lisp/edmacro.el                                    |   24 +-
 lisp/ehelp.el                                      |    2 +-
 lisp/elec-pair.el                                  |    2 +-
 lisp/electric.el                                   |    2 +-
 lisp/elide-head.el                                 |    2 +-
 lisp/emacs-lisp/advice.el                          |    2 +-
 lisp/emacs-lisp/avl-tree.el                        |    2 +-
 lisp/emacs-lisp/backquote.el                       |    2 +-
 lisp/emacs-lisp/backtrace.el                       |    2 +-
 lisp/emacs-lisp/benchmark.el                       |    2 +-
 lisp/emacs-lisp/bindat.el                          |    2 +-
 lisp/emacs-lisp/byte-opt.el                        |   37 +-
 lisp/emacs-lisp/byte-run.el                        |    2 +-
 lisp/emacs-lisp/bytecomp.el                        | 1057 ++++---
 lisp/emacs-lisp/cconv.el                           |  580 ++--
 lisp/emacs-lisp/chart.el                           |    2 +-
 lisp/emacs-lisp/check-declare.el                   |    4 +-
 lisp/emacs-lisp/checkdoc.el                        |   12 +-
 lisp/emacs-lisp/cl-extra.el                        |    2 +-
 lisp/emacs-lisp/cl-generic.el                      |    4 +-
 lisp/emacs-lisp/cl-indent.el                       |    2 +-
 lisp/emacs-lisp/cl-lib.el                          |    2 +-
 lisp/emacs-lisp/cl-macs.el                         |    4 +-
 lisp/emacs-lisp/cl-preloaded.el                    |    2 +-
 lisp/emacs-lisp/cl-print.el                        |    2 +-
 lisp/emacs-lisp/cl-seq.el                          |    2 +-
 lisp/emacs-lisp/comp-common.el                     |   11 +-
 lisp/emacs-lisp/comp-cstr.el                       |    6 +-
 lisp/emacs-lisp/comp-run.el                        |    2 +-
 lisp/emacs-lisp/comp.el                            |  213 +-
 lisp/emacs-lisp/copyright.el                       |    2 +-
 lisp/emacs-lisp/crm.el                             |    2 +-
 lisp/emacs-lisp/cursor-sensor.el                   |    2 +-
 lisp/emacs-lisp/debug-early.el                     |   50 +-
 lisp/emacs-lisp/debug.el                           |   64 +-
 lisp/emacs-lisp/derived.el                         |  137 +-
 lisp/emacs-lisp/disass.el                          |    4 +-
 lisp/emacs-lisp/easy-mmode.el                      |    2 +-
 lisp/emacs-lisp/easymenu.el                        |    2 +-
 lisp/emacs-lisp/edebug.el                          |    2 +-
 lisp/emacs-lisp/eieio-base.el                      |    2 +-
 lisp/emacs-lisp/eieio-core.el                      |    2 +-
 lisp/emacs-lisp/eieio-custom.el                    |    2 +-
 lisp/emacs-lisp/eieio-datadebug.el                 |    2 +-
 lisp/emacs-lisp/eieio-opt.el                       |    2 +-
 lisp/emacs-lisp/eieio-speedbar.el                  |    2 +-
 lisp/emacs-lisp/eieio.el                           |    2 +-
 lisp/emacs-lisp/eldoc.el                           |   44 +-
 lisp/emacs-lisp/elint.el                           |    2 +-
 lisp/emacs-lisp/elp.el                             |    2 +-
 lisp/emacs-lisp/ert-font-lock.el                   |    4 +-
 lisp/emacs-lisp/ert-x.el                           |    6 +-
 lisp/emacs-lisp/ert.el                             |  143 +-
 lisp/emacs-lisp/ewoc.el                            |    2 +-
 lisp/emacs-lisp/faceup.el                          |    2 +-
 lisp/emacs-lisp/find-func.el                       |    2 +-
 lisp/emacs-lisp/float-sup.el                       |    2 +-
 lisp/emacs-lisp/generate-lisp-file.el              |    2 +-
 lisp/emacs-lisp/generator.el                       |    2 +-
 lisp/emacs-lisp/generic.el                         |    2 +-
 lisp/emacs-lisp/gv.el                              |    4 +-
 lisp/emacs-lisp/helper.el                          |    2 +-
 lisp/emacs-lisp/hierarchy.el                       |    2 +-
 lisp/emacs-lisp/icons.el                           |   16 +-
 lisp/emacs-lisp/inline.el                          |    6 +-
 lisp/emacs-lisp/let-alist.el                       |    2 +-
 lisp/emacs-lisp/lisp-mnt.el                        |   35 +-
 lisp/emacs-lisp/lisp-mode.el                       |   12 +-
 lisp/emacs-lisp/lisp.el                            |    4 +-
 lisp/emacs-lisp/loaddefs-gen.el                    |    2 +-
 lisp/emacs-lisp/macroexp.el                        |   14 +-
 lisp/emacs-lisp/map-ynp.el                         |    2 +-
 lisp/emacs-lisp/map.el                             |    2 +-
 lisp/emacs-lisp/memory-report.el                   |    2 +-
 lisp/emacs-lisp/multisession.el                    |    2 +-
 lisp/emacs-lisp/nadvice.el                         |   38 +-
 lisp/emacs-lisp/oclosure.el                        |    2 +-
 lisp/emacs-lisp/package-vc.el                      |   17 +-
 lisp/emacs-lisp/package-x.el                       |    2 +-
 lisp/emacs-lisp/package.el                         |  109 +-
 lisp/emacs-lisp/pcase.el                           |   10 +-
 lisp/emacs-lisp/pp.el                              |    2 +-
 lisp/emacs-lisp/radix-tree.el                      |    2 +-
 lisp/emacs-lisp/range.el                           |    2 +-
 lisp/emacs-lisp/re-builder.el                      |    2 +-
 lisp/emacs-lisp/regexp-opt.el                      |    2 +-
 lisp/emacs-lisp/regi.el                            |    2 +-
 lisp/emacs-lisp/ring.el                            |    2 +-
 lisp/emacs-lisp/rmc.el                             |    2 +-
 lisp/emacs-lisp/rx.el                              |    2 +-
 lisp/emacs-lisp/seq.el                             |    2 +-
 lisp/emacs-lisp/shadow.el                          |    2 +-
 lisp/emacs-lisp/shortdoc.el                        |    7 +-
 lisp/emacs-lisp/shorthands.el                      |    2 +-
 lisp/emacs-lisp/smie.el                            |    2 +-
 lisp/emacs-lisp/subr-x.el                          |    2 +-
 lisp/emacs-lisp/syntax.el                          |    2 +-
 lisp/emacs-lisp/tabulated-list.el                  |    2 +-
 lisp/emacs-lisp/tcover-ses.el                      |    2 +-
 lisp/emacs-lisp/testcover.el                       |    2 +-
 lisp/emacs-lisp/text-property-search.el            |    2 +-
 lisp/emacs-lisp/thunk.el                           |    2 +-
 lisp/emacs-lisp/timer-list.el                      |    2 +-
 lisp/emacs-lisp/timer.el                           |    2 +-
 lisp/emacs-lisp/tq.el                              |    2 +-
 lisp/emacs-lisp/trace.el                           |  122 +-
 lisp/emacs-lisp/unsafep.el                         |    2 +-
 lisp/emacs-lisp/vtable.el                          |    2 +-
 lisp/emacs-lisp/warnings.el                        |    2 +-
 lisp/emacs-lock.el                                 |    2 +-
 lisp/emulation/cua-base.el                         |    2 +-
 lisp/emulation/cua-gmrk.el                         |    2 +-
 lisp/emulation/cua-rect.el                         |    2 +-
 lisp/emulation/edt-lk201.el                        |    2 +-
 lisp/emulation/edt-mapper.el                       |    2 +-
 lisp/emulation/edt-pc.el                           |    2 +-
 lisp/emulation/edt-vt100.el                        |    2 +-
 lisp/emulation/edt.el                              |    2 +-
 lisp/emulation/keypad.el                           |    2 +-
 lisp/emulation/viper-cmd.el                        |    4 +-
 lisp/emulation/viper-ex.el                         |    2 +-
 lisp/emulation/viper-init.el                       |   12 +-
 lisp/emulation/viper-keym.el                       |    2 +-
 lisp/emulation/viper-macs.el                       |    2 +-
 lisp/emulation/viper-mous.el                       |    2 +-
 lisp/emulation/viper-util.el                       |    2 +-
 lisp/emulation/viper.el                            |    2 +-
 lisp/env.el                                        |    2 +-
 lisp/epa-dired.el                                  |    2 +-
 lisp/epa-file.el                                   |    2 +-
 lisp/epa-hook.el                                   |    2 +-
 lisp/epa-ks.el                                     |    2 +-
 lisp/epa-mail.el                                   |    2 +-
 lisp/epa.el                                        |    4 +-
 lisp/epg-config.el                                 |    2 +-
 lisp/epg.el                                        |    2 +-
 lisp/erc/ChangeLog.1                               |    2 +-
 lisp/erc/ChangeLog.2                               |    2 +-
 lisp/erc/erc-autoaway.el                           |    2 +-
 lisp/erc/erc-backend.el                            |  226 +-
 lisp/erc/erc-button.el                             |  111 +-
 lisp/erc/erc-capab.el                              |    2 +-
 lisp/erc/erc-common.el                             |  186 +-
 lisp/erc/erc-compat.el                             |    2 +-
 lisp/erc/erc-dcc.el                                |   17 +-
 lisp/erc/erc-desktop-notifications.el              |    2 +-
 lisp/erc/erc-ezbounce.el                           |    2 +-
 lisp/erc/erc-fill.el                               |  153 +-
 lisp/erc/erc-goodies.el                            |  126 +-
 lisp/erc/erc-ibuffer.el                            |    2 +-
 lisp/erc/erc-identd.el                             |    2 +-
 lisp/erc/erc-imenu.el                              |    2 +-
 lisp/erc/erc-join.el                               |    2 +-
 lisp/erc/erc-lang.el                               |    2 +-
 lisp/erc/erc-list.el                               |    2 +-
 lisp/erc/erc-log.el                                |    7 +-
 lisp/erc/erc-match.el                              |    2 +-
 lisp/erc/erc-menu.el                               |    2 +-
 lisp/erc/erc-netsplit.el                           |   15 +-
 lisp/erc/erc-networks.el                           |   52 +-
 lisp/erc/erc-nicks.el                              |   94 +-
 lisp/erc/erc-notify.el                             |   83 +-
 lisp/erc/erc-page.el                               |    5 +-
 lisp/erc/erc-pcomplete.el                          |    4 +-
 lisp/erc/erc-replace.el                            |    2 +-
 lisp/erc/erc-ring.el                               |    2 +-
 lisp/erc/erc-sasl.el                               |   16 +-
 lisp/erc/erc-services.el                           |    4 +-
 lisp/erc/erc-sound.el                              |    5 +-
 lisp/erc/erc-speedbar.el                           |   74 +-
 lisp/erc/erc-spelling.el                           |    2 +-
 lisp/erc/erc-stamp.el                              |   82 +-
 lisp/erc/erc-status-sidebar.el                     |   17 +-
 lisp/erc/erc-track.el                              |  272 +-
 lisp/erc/erc-truncate.el                           |    4 +-
 lisp/erc/erc-xdcc.el                               |    2 +-
 lisp/erc/erc.el                                    | 1561 ++++++----
 lisp/eshell/em-alias.el                            |    2 +-
 lisp/eshell/em-banner.el                           |    2 +-
 lisp/eshell/em-basic.el                            |   26 +-
 lisp/eshell/em-cmpl.el                             |    2 +-
 lisp/eshell/em-dirs.el                             |    5 +-
 lisp/eshell/em-elecslash.el                        |    2 +-
 lisp/eshell/em-extpipe.el                          |    2 +-
 lisp/eshell/em-glob.el                             |    2 +-
 lisp/eshell/em-hist.el                             |   20 +-
 lisp/eshell/em-ls.el                               |    2 +-
 lisp/eshell/em-pred.el                             |    2 +-
 lisp/eshell/em-prompt.el                           |    2 +-
 lisp/eshell/em-rebind.el                           |    2 +-
 lisp/eshell/em-script.el                           |    2 +-
 lisp/eshell/em-smart.el                            |    2 +-
 lisp/eshell/em-term.el                             |    2 +-
 lisp/eshell/em-tramp.el                            |   24 +-
 lisp/eshell/em-unix.el                             |   20 +-
 lisp/eshell/em-xtra.el                             |    2 +-
 lisp/eshell/esh-arg.el                             |    7 +-
 lisp/eshell/esh-cmd.el                             |   56 +-
 lisp/eshell/esh-ext.el                             |    2 +-
 lisp/eshell/esh-io.el                              |    2 +-
 lisp/eshell/esh-mode.el                            |   19 +-
 lisp/eshell/esh-module.el                          |    2 +-
 lisp/eshell/esh-opt.el                             |    2 +-
 lisp/eshell/esh-proc.el                            |    4 +-
 lisp/eshell/esh-util.el                            |    2 +-
 lisp/eshell/esh-var.el                             |   99 +-
 lisp/eshell/eshell.el                              |    2 +-
 lisp/expand.el                                     |    2 +-
 lisp/external-completion.el                        |    2 +-
 lisp/ezimage.el                                    |    2 +-
 lisp/face-remap.el                                 |    2 +-
 lisp/facemenu.el                                   |    2 +-
 lisp/faces.el                                      |    6 +-
 lisp/ffap.el                                       |   16 +-
 lisp/filecache.el                                  |    2 +-
 lisp/fileloop.el                                   |    2 +-
 lisp/filenotify.el                                 |    2 +-
 lisp/files-x.el                                    |   45 +-
 lisp/files.el                                      |  535 ++--
 lisp/filesets.el                                   |   18 +-
 lisp/find-cmd.el                                   |    2 +-
 lisp/find-dired.el                                 |    2 +-
 lisp/find-file.el                                  |    2 +-
 lisp/find-lisp.el                                  |    2 +-
 lisp/finder.el                                     |    5 +-
 lisp/flow-ctrl.el                                  |    2 +-
 lisp/foldout.el                                    |    2 +-
 lisp/follow.el                                     |    6 +-
 lisp/font-core.el                                  |    2 +-
 lisp/font-lock.el                                  |    2 +-
 lisp/format-spec.el                                |    2 +-
 lisp/format.el                                     |    2 +-
 lisp/forms.el                                      |    4 +-
 lisp/frame.el                                      |    2 +-
 lisp/frameset.el                                   |    2 +-
 lisp/fringe.el                                     |    2 +-
 lisp/generic-x.el                                  |    3 +-
 lisp/gnus/ChangeLog.1                              |    6 +-
 lisp/gnus/ChangeLog.2                              |    6 +-
 lisp/gnus/ChangeLog.3                              |    6 +-
 lisp/gnus/canlock.el                               |    2 +-
 lisp/gnus/deuglify.el                              |    2 +-
 lisp/gnus/gmm-utils.el                             |    2 +-
 lisp/gnus/gnus-agent.el                            |    2 +-
 lisp/gnus/gnus-art.el                              |   17 +-
 lisp/gnus/gnus-async.el                            |    2 +-
 lisp/gnus/gnus-bcklg.el                            |    2 +-
 lisp/gnus/gnus-bookmark.el                         |    2 +-
 lisp/gnus/gnus-cache.el                            |    2 +-
 lisp/gnus/gnus-cite.el                             |   38 +-
 lisp/gnus/gnus-cloud.el                            |    2 +-
 lisp/gnus/gnus-cus.el                              |    2 +-
 lisp/gnus/gnus-dbus.el                             |    2 +-
 lisp/gnus/gnus-delay.el                            |    2 +-
 lisp/gnus/gnus-demon.el                            |    2 +-
 lisp/gnus/gnus-diary.el                            |    2 +-
 lisp/gnus/gnus-dired.el                            |    2 +-
 lisp/gnus/gnus-draft.el                            |    2 +-
 lisp/gnus/gnus-dup.el                              |    2 +-
 lisp/gnus/gnus-eform.el                            |    2 +-
 lisp/gnus/gnus-fun.el                              |    2 +-
 lisp/gnus/gnus-gravatar.el                         |    2 +-
 lisp/gnus/gnus-group.el                            |    8 +-
 lisp/gnus/gnus-html.el                             |    2 +-
 lisp/gnus/gnus-icalendar.el                        |    2 +-
 lisp/gnus/gnus-int.el                              |    2 +-
 lisp/gnus/gnus-kill.el                             |    2 +-
 lisp/gnus/gnus-logic.el                            |    2 +-
 lisp/gnus/gnus-mh.el                               |    2 +-
 lisp/gnus/gnus-ml.el                               |    2 +-
 lisp/gnus/gnus-mlspl.el                            |    2 +-
 lisp/gnus/gnus-msg.el                              |   28 +-
 lisp/gnus/gnus-notifications.el                    |    2 +-
 lisp/gnus/gnus-picon.el                            |    2 +-
 lisp/gnus/gnus-range.el                            |    2 +-
 lisp/gnus/gnus-registry.el                         |    2 +-
 lisp/gnus/gnus-rfc1843.el                          |    2 +-
 lisp/gnus/gnus-rmail.el                            |    2 +-
 lisp/gnus/gnus-salt.el                             |    2 +-
 lisp/gnus/gnus-score.el                            |    2 +-
 lisp/gnus/gnus-search.el                           |    4 +-
 lisp/gnus/gnus-sieve.el                            |    2 +-
 lisp/gnus/gnus-spec.el                             |    2 +-
 lisp/gnus/gnus-srvr.el                             |    2 +-
 lisp/gnus/gnus-start.el                            |    2 +-
 lisp/gnus/gnus-sum.el                              |   12 +-
 lisp/gnus/gnus-topic.el                            |    2 +-
 lisp/gnus/gnus-undo.el                             |    2 +-
 lisp/gnus/gnus-util.el                             |    2 +-
 lisp/gnus/gnus-uu.el                               |    2 +-
 lisp/gnus/gnus-vm.el                               |    2 +-
 lisp/gnus/gnus-win.el                              |    2 +-
 lisp/gnus/gnus.el                                  |    2 +-
 lisp/gnus/gssapi.el                                |    2 +-
 lisp/gnus/legacy-gnus-agent.el                     |    2 +-
 lisp/gnus/mail-source.el                           |    2 +-
 lisp/gnus/message.el                               |   12 +-
 lisp/gnus/mm-archive.el                            |    2 +-
 lisp/gnus/mm-bodies.el                             |    2 +-
 lisp/gnus/mm-decode.el                             |    2 +-
 lisp/gnus/mm-encode.el                             |    2 +-
 lisp/gnus/mm-extern.el                             |    2 +-
 lisp/gnus/mm-partial.el                            |    2 +-
 lisp/gnus/mm-url.el                                |    2 +-
 lisp/gnus/mm-util.el                               |    2 +-
 lisp/gnus/mm-uu.el                                 |    2 +-
 lisp/gnus/mm-view.el                               |    2 +-
 lisp/gnus/mml-sec.el                               |    2 +-
 lisp/gnus/mml-smime.el                             |    2 +-
 lisp/gnus/mml.el                                   |    2 +-
 lisp/gnus/mml1991.el                               |    2 +-
 lisp/gnus/mml2015.el                               |    2 +-
 lisp/gnus/nnagent.el                               |    2 +-
 lisp/gnus/nnbabyl.el                               |    2 +-
 lisp/gnus/nndiary.el                               |    4 +-
 lisp/gnus/nndir.el                                 |    2 +-
 lisp/gnus/nndoc.el                                 |    2 +-
 lisp/gnus/nndraft.el                               |    2 +-
 lisp/gnus/nneething.el                             |    2 +-
 lisp/gnus/nnfolder.el                              |    2 +-
 lisp/gnus/nngateway.el                             |    2 +-
 lisp/gnus/nnheader.el                              |    2 +-
 lisp/gnus/nnimap.el                                |    2 +-
 lisp/gnus/nnmail.el                                |    2 +-
 lisp/gnus/nnmairix.el                              |    2 +-
 lisp/gnus/nnmbox.el                                |    2 +-
 lisp/gnus/nnmh.el                                  |    2 +-
 lisp/gnus/nnml.el                                  |    4 +-
 lisp/gnus/nnoo.el                                  |    2 +-
 lisp/gnus/nnregistry.el                            |    2 +-
 lisp/gnus/nnrss.el                                 |    2 +-
 lisp/gnus/nnselect.el                              |    2 +-
 lisp/gnus/nnspool.el                               |    2 +-
 lisp/gnus/nntp.el                                  |    2 +-
 lisp/gnus/nnvirtual.el                             |    2 +-
 lisp/gnus/nnweb.el                                 |    2 +-
 lisp/gnus/score-mode.el                            |    2 +-
 lisp/gnus/smiley.el                                |    2 +-
 lisp/gnus/smime.el                                 |    2 +-
 lisp/gnus/spam-report.el                           |    2 +-
 lisp/gnus/spam-stat.el                             |    2 +-
 lisp/gnus/spam-wash.el                             |    2 +-
 lisp/gnus/spam.el                                  |    2 +-
 lisp/help-at-pt.el                                 |    2 +-
 lisp/help-fns.el                                   |   29 +-
 lisp/help-macro.el                                 |    2 +-
 lisp/help-mode.el                                  |    2 +-
 lisp/help.el                                       |   15 +-
 lisp/hex-util.el                                   |    2 +-
 lisp/hexl.el                                       |    2 +-
 lisp/hfy-cmap.el                                   |    2 +-
 lisp/hi-lock.el                                    |    2 +-
 lisp/hilit-chg.el                                  |    2 +-
 lisp/hippie-exp.el                                 |    2 +-
 lisp/hl-line.el                                    |    2 +-
 lisp/htmlfontify.el                                |    2 +-
 lisp/ibuf-ext.el                                   |    2 +-
 lisp/ibuf-macs.el                                  |    2 +-
 lisp/ibuffer.el                                    |  240 +-
 lisp/icomplete.el                                  |    8 +-
 lisp/ido.el                                        |    2 +-
 lisp/ielm.el                                       |    2 +-
 lisp/iimage.el                                     |    2 +-
 lisp/image-file.el                                 |    2 +-
 lisp/image-mode.el                                 |    2 +-
 lisp/image.el                                      |    2 +-
 lisp/image/compface.el                             |    2 +-
 lisp/image/exif.el                                 |    2 +-
 lisp/image/gravatar.el                             |    2 +-
 lisp/image/image-converter.el                      |    2 +-
 lisp/image/image-crop.el                           |    2 +-
 lisp/image/image-dired-dired.el                    |    4 +-
 lisp/image/image-dired-external.el                 |    2 +-
 lisp/image/image-dired-tags.el                     |    3 +-
 lisp/image/image-dired-util.el                     |    2 +-
 lisp/image/image-dired.el                          |    2 +-
 lisp/image/wallpaper.el                            |    2 +-
 lisp/imenu.el                                      |    2 +-
 lisp/indent-aux.el                                 |    2 +-
 lisp/indent.el                                     |    4 +-
 lisp/info-look.el                                  |    2 +-
 lisp/info-xref.el                                  |   10 +-
 lisp/info.el                                       |  185 +-
 lisp/informat.el                                   |    2 +-
 lisp/international/ccl.el                          |    2 +-
 lisp/international/characters.el                   |    5 +-
 lisp/international/emoji.el                        |   13 +-
 lisp/international/fontset.el                      |   16 +-
 lisp/international/isearch-x.el                    |    2 +-
 lisp/international/iso-ascii.el                    |    2 +-
 lisp/international/iso-cvt.el                      |    2 +-
 lisp/international/iso-transl.el                   |    2 +-
 lisp/international/ja-dic-cnv.el                   |    2 +-
 lisp/international/kinsoku.el                      |    2 +-
 lisp/international/kkc.el                          |    2 +-
 lisp/international/latexenc.el                     |    2 +-
 lisp/international/latin1-disp.el                  |    2 +-
 lisp/international/mule-cmds.el                    |    6 +-
 lisp/international/mule-conf.el                    |    2 +-
 lisp/international/mule-diag.el                    |    2 +-
 lisp/international/mule-util.el                    |    2 +-
 lisp/international/mule.el                         |    2 +-
 lisp/international/ogonek.el                       |    6 +-
 lisp/international/quail.el                        |   10 +-
 lisp/international/rfc1843.el                      |    2 +-
 lisp/international/textsec-check.el                |    2 +-
 lisp/international/textsec.el                      |    2 +-
 lisp/international/titdic-cnv.el                   |    2 +-
 lisp/international/ucs-normalize.el                |    2 +-
 lisp/international/utf-7.el                        |    2 +-
 lisp/international/utf7.el                         |    2 +-
 lisp/isearch.el                                    |   11 +-
 lisp/isearchb.el                                   |    2 +-
 lisp/jit-lock.el                                   |    3 +-
 lisp/jka-cmpr-hook.el                              |    2 +-
 lisp/jka-compr.el                                  |    2 +-
 lisp/json.el                                       |    2 +-
 lisp/jsonrpc.el                                    |  831 ++++--
 lisp/kermit.el                                     |    2 +-
 lisp/keymap.el                                     |   14 +-
 lisp/kmacro.el                                     |    2 +-
 lisp/language/china-util.el                        |    2 +-
 lisp/language/chinese.el                           |    2 +-
 lisp/language/cyril-util.el                        |    2 +-
 lisp/language/cyrillic.el                          |    2 +-
 lisp/language/czech.el                             |    2 +-
 lisp/language/english.el                           |    2 +-
 lisp/language/ethio-util.el                        |    2 +-
 lisp/language/ethiopic.el                          |    2 +-
 lisp/language/european.el                          |    2 +-
 lisp/language/georgian.el                          |    2 +-
 lisp/language/greek.el                             |    2 +-
 lisp/language/hanja-util.el                        |    4 +-
 lisp/language/hebrew.el                            |    2 +-
 lisp/language/ind-util.el                          |    2 +-
 lisp/language/indian.el                            |    2 +-
 lisp/language/indonesian.el                        |    2 +-
 lisp/language/japan-util.el                        |    2 +-
 lisp/language/japanese.el                          |    2 +-
 lisp/language/korea-util.el                        |    2 +-
 lisp/language/korean.el                            |    2 +-
 lisp/language/lao-util.el                          |    2 +-
 lisp/language/lao.el                               |    2 +-
 lisp/language/misc-lang.el                         |    2 +-
 lisp/language/philippine.el                        |    2 +-
 lisp/language/romanian.el                          |    2 +-
 lisp/language/sinhala.el                           |    6 +-
 lisp/language/slovak.el                            |    2 +-
 lisp/language/tai-viet.el                          |    2 +-
 lisp/language/thai-util.el                         |    2 +-
 lisp/language/thai.el                              |    2 +-
 lisp/language/tibet-util.el                        |    2 +-
 lisp/language/tibetan.el                           |    2 +-
 lisp/language/utf-8-lang.el                        |    2 +-
 lisp/language/viet-util.el                         |    2 +-
 lisp/language/vietnamese.el                        |    2 +-
 lisp/ldefs-boot.el                                 |  903 ++++--
 lisp/leim/quail/arabic.el                          |    2 +-
 lisp/leim/quail/cham.el                            |    2 +-
 lisp/leim/quail/compose.el                         |    2 +-
 lisp/leim/quail/croatian.el                        |    2 +-
 lisp/leim/quail/cyril-jis.el                       |    2 +-
 lisp/leim/quail/cyrillic.el                        |    6 +-
 lisp/leim/quail/czech.el                           |    2 +-
 lisp/leim/quail/emoji.el                           |    2 +-
 lisp/leim/quail/georgian.el                        |    2 +-
 lisp/leim/quail/greek.el                           |    2 +-
 lisp/leim/quail/hangul.el                          |    2 +-
 lisp/leim/quail/hanja.el                           |    2 +-
 lisp/leim/quail/hanja3.el                          |    2 +-
 lisp/leim/quail/indian.el                          |    4 +-
 lisp/leim/quail/indonesian.el                      |    2 +-
 lisp/leim/quail/ipa-praat.el                       |    2 +-
 lisp/leim/quail/ipa.el                             |    2 +-
 lisp/leim/quail/japanese.el                        |    2 +-
 lisp/leim/quail/latin-alt.el                       |    2 +-
 lisp/leim/quail/latin-ltx.el                       |    2 +-
 lisp/leim/quail/latin-post.el                      |    2 +-
 lisp/leim/quail/latin-pre.el                       |    2 +-
 lisp/leim/quail/lrt.el                             |    2 +-
 lisp/leim/quail/misc-lang.el                       |    2 +-
 lisp/leim/quail/pakistan.el                        |    2 +-
 lisp/leim/quail/persian.el                         |    4 +-
 lisp/leim/quail/philippine.el                      |    2 +-
 lisp/leim/quail/programmer-dvorak.el               |    2 +-
 lisp/leim/quail/py-punct.el                        |    2 +-
 lisp/leim/quail/rfc1345.el                         |    2 +-
 lisp/leim/quail/sami.el                            |    2 +-
 lisp/leim/quail/sgml-input.el                      |    2 +-
 lisp/leim/quail/sisheng.el                         |    2 +-
 lisp/leim/quail/slovak.el                          |    2 +-
 lisp/leim/quail/symbol-ksc.el                      |    2 +-
 lisp/leim/quail/tamil-dvorak.el                    |    2 +-
 lisp/leim/quail/tibetan.el                         |    2 +-
 lisp/leim/quail/uni-input.el                       |    2 +-
 lisp/leim/quail/vntelex.el                         |    2 +-
 lisp/leim/quail/vnvni.el                           |    2 +-
 lisp/leim/quail/welsh.el                           |    2 +-
 lisp/loadhist.el                                   |    2 +-
 lisp/loadup.el                                     |   30 +-
 lisp/locate.el                                     |    2 +-
 lisp/lpr.el                                        |    2 +-
 lisp/ls-lisp.el                                    |  185 +-
 lisp/macros.el                                     |    6 +-
 lisp/mail/binhex.el                                |    2 +-
 lisp/mail/blessmail.el                             |    2 +-
 lisp/mail/emacsbug.el                              |    6 +-
 lisp/mail/flow-fill.el                             |    2 +-
 lisp/mail/footnote.el                              |    2 +-
 lisp/mail/hashcash.el                              |    2 +-
 lisp/mail/ietf-drums-date.el                       |    2 +-
 lisp/mail/ietf-drums.el                            |    2 +-
 lisp/mail/mail-extr.el                             |    2 +-
 lisp/mail/mail-hist.el                             |    2 +-
 lisp/mail/mail-parse.el                            |    2 +-
 lisp/mail/mail-prsvr.el                            |    2 +-
 lisp/mail/mail-utils.el                            |    2 +-
 lisp/mail/mailabbrev.el                            |    2 +-
 lisp/mail/mailalias.el                             |    2 +-
 lisp/mail/mailclient.el                            |    2 +-
 lisp/mail/mailheader.el                            |    2 +-
 lisp/mail/mspools.el                               |    2 +-
 lisp/mail/qp.el                                    |    2 +-
 lisp/mail/reporter.el                              |    2 +-
 lisp/mail/rfc2045.el                               |    2 +-
 lisp/mail/rfc2047.el                               |    2 +-
 lisp/mail/rfc2231.el                               |    2 +-
 lisp/mail/rfc6068.el                               |    2 +-
 lisp/mail/rfc822.el                                |    2 +-
 lisp/mail/rmail-spam-filter.el                     |    2 +-
 lisp/mail/rmail.el                                 |   45 +-
 lisp/mail/rmailedit.el                             |    2 +-
 lisp/mail/rmailkwd.el                              |    2 +-
 lisp/mail/rmailmm.el                               |    2 +-
 lisp/mail/rmailmsc.el                              |    2 +-
 lisp/mail/rmailout.el                              |    4 +-
 lisp/mail/rmailsort.el                             |    2 +-
 lisp/mail/rmailsum.el                              |   26 +-
 lisp/mail/sendmail.el                              |    2 +-
 lisp/mail/smtpmail.el                              |    2 +-
 lisp/mail/supercite.el                             |    8 +-
 lisp/mail/undigest.el                              |    2 +-
 lisp/mail/unrmail.el                               |    2 +-
 lisp/mail/uudecode.el                              |    2 +-
 lisp/mail/yenc.el                                  |    2 +-
 lisp/man.el                                        |   10 +-
 lisp/master.el                                     |    2 +-
 lisp/mb-depth.el                                   |    2 +-
 lisp/md4.el                                        |    2 +-
 lisp/menu-bar.el                                   |   10 +-
 lisp/mh-e/ChangeLog.1                              |    4 +-
 lisp/mh-e/ChangeLog.2                              |    4 +-
 lisp/mh-e/mh-acros.el                              |   77 +-
 lisp/mh-e/mh-alias.el                              |    2 +-
 lisp/mh-e/mh-buffers.el                            |    2 +-
 lisp/mh-e/mh-comp.el                               |    4 +-
 lisp/mh-e/mh-e.el                                  |    2 +-
 lisp/mh-e/mh-folder.el                             |    2 +-
 lisp/mh-e/mh-funcs.el                              |    4 +-
 lisp/mh-e/mh-gnus.el                               |    2 +-
 lisp/mh-e/mh-identity.el                           |    2 +-
 lisp/mh-e/mh-inc.el                                |    2 +-
 lisp/mh-e/mh-junk.el                               |    2 +-
 lisp/mh-e/mh-letter.el                             |    2 +-
 lisp/mh-e/mh-limit.el                              |    2 +-
 lisp/mh-e/mh-mime.el                               |    2 +-
 lisp/mh-e/mh-print.el                              |    2 +-
 lisp/mh-e/mh-scan.el                               |    2 +-
 lisp/mh-e/mh-search.el                             |    4 +-
 lisp/mh-e/mh-seq.el                                |    2 +-
 lisp/mh-e/mh-show.el                               |    2 +-
 lisp/mh-e/mh-speed.el                              |    2 +-
 lisp/mh-e/mh-thread.el                             |    2 +-
 lisp/mh-e/mh-tool-bar.el                           |    2 +-
 lisp/mh-e/mh-utils.el                              |    4 +-
 lisp/mh-e/mh-xface.el                              |    2 +-
 lisp/midnight.el                                   |    2 +-
 lisp/minibuf-eldef.el                              |    2 +-
 lisp/minibuffer.el                                 |  173 +-
 lisp/misc.el                                       |    2 +-
 lisp/misearch.el                                   |    2 +-
 lisp/mouse-copy.el                                 |    2 +-
 lisp/mouse-drag.el                                 |    2 +-
 lisp/mouse.el                                      |    2 +-
 lisp/mpc.el                                        |    2 +-
 lisp/msb.el                                        |    2 +-
 lisp/mwheel.el                                     |  175 +-
 lisp/net/ange-ftp.el                               |   41 +-
 lisp/net/browse-url.el                             |    2 +-
 lisp/net/dbus.el                                   |    2 +-
 lisp/net/dictionary-connection.el                  |    2 +-
 lisp/net/dictionary.el                             |    2 +-
 lisp/net/dig.el                                    |    2 +-
 lisp/net/dns.el                                    |    2 +-
 lisp/net/eudc-bob.el                               |    2 +-
 lisp/net/eudc-capf.el                              |    2 +-
 lisp/net/eudc-export.el                            |    2 +-
 lisp/net/eudc-hotlist.el                           |    2 +-
 lisp/net/eudc-vars.el                              |    2 +-
 lisp/net/eudc.el                                   |    2 +-
 lisp/net/eudcb-bbdb.el                             |    2 +-
 lisp/net/eudcb-ecomplete.el                        |    2 +-
 lisp/net/eudcb-ldap.el                             |    2 +-
 lisp/net/eudcb-mab.el                              |    2 +-
 lisp/net/eudcb-macos-contacts.el                   |    2 +-
 lisp/net/eudcb-mailabbrev.el                       |    2 +-
 lisp/net/eww.el                                    |   11 +-
 lisp/net/gnutls.el                                 |    2 +-
 lisp/net/goto-addr.el                              |    2 +-
 lisp/net/hmac-def.el                               |    2 +-
 lisp/net/hmac-md5.el                               |    2 +-
 lisp/net/imap.el                                   |    2 +-
 lisp/net/ldap.el                                   |    2 +-
 lisp/net/mailcap.el                                |    2 +-
 lisp/net/mairix.el                                 |    2 +-
 lisp/net/net-utils.el                              |    2 +-
 lisp/net/network-stream.el                         |    2 +-
 lisp/net/newst-backend.el                          |    2 +-
 lisp/net/newst-plainview.el                        |    2 +-
 lisp/net/newst-reader.el                           |    2 +-
 lisp/net/newst-ticker.el                           |    2 +-
 lisp/net/newst-treeview.el                         |    4 +-
 lisp/net/newsticker.el                             |    2 +-
 lisp/net/nsm.el                                    |    2 +-
 lisp/net/ntlm.el                                   |    2 +-
 lisp/net/pop3.el                                   |    2 +-
 lisp/net/puny.el                                   |    2 +-
 lisp/net/rcirc.el                                  |   10 +-
 lisp/net/rfc2104.el                                |    2 +-
 lisp/net/sasl-cram.el                              |    2 +-
 lisp/net/sasl-digest.el                            |    2 +-
 lisp/net/sasl-ntlm.el                              |    2 +-
 lisp/net/sasl-scram-rfc.el                         |    2 +-
 lisp/net/sasl-scram-sha256.el                      |    2 +-
 lisp/net/sasl.el                                   |    2 +-
 lisp/net/secrets.el                                |    2 +-
 lisp/net/shr-color.el                              |    2 +-
 lisp/net/shr.el                                    |   88 +-
 lisp/net/sieve-manage.el                           |    6 +-
 lisp/net/sieve-mode.el                             |    2 +-
 lisp/net/sieve.el                                  |    2 +-
 lisp/net/snmp-mode.el                              |    2 +-
 lisp/net/soap-client.el                            |    4 +-
 lisp/net/soap-inspect.el                           |    2 +-
 lisp/net/socks.el                                  |    2 +-
 lisp/net/telnet.el                                 |    2 +-
 lisp/net/tramp-adb.el                              |    2 +-
 lisp/net/tramp-archive.el                          |    2 +-
 lisp/net/tramp-cache.el                            |   10 +-
 lisp/net/tramp-cmds.el                             |    2 +-
 lisp/net/tramp-compat.el                           |   25 +-
 lisp/net/tramp-container.el                        |    2 +-
 lisp/net/tramp-crypt.el                            |   27 +-
 lisp/net/tramp-ftp.el                              |    2 +-
 lisp/net/tramp-fuse.el                             |    2 +-
 lisp/net/tramp-gvfs.el                             |    2 +-
 lisp/net/tramp-integration.el                      |    2 +-
 lisp/net/tramp-message.el                          |    4 +-
 lisp/net/tramp-rclone.el                           |    2 +-
 lisp/net/tramp-sh.el                               |  116 +-
 lisp/net/tramp-smb.el                              |    2 +-
 lisp/net/tramp-sshfs.el                            |    2 +-
 lisp/net/tramp-sudoedit.el                         |    2 +-
 lisp/net/tramp-uu.el                               |    2 +-
 lisp/net/tramp.el                                  |  184 +-
 lisp/net/trampver.el                               |    8 +-
 lisp/net/webjump.el                                |    2 +-
 lisp/net/zeroconf.el                               |    2 +-
 lisp/newcomment.el                                 |    2 +-
 lisp/notifications.el                              |    4 +-
 lisp/novice.el                                     |    9 +-
 lisp/nxml/nxml-enc.el                              |    4 +-
 lisp/nxml/nxml-maint.el                            |    4 +-
 lisp/nxml/nxml-mode.el                             |    4 +-
 lisp/nxml/nxml-ns.el                               |    4 +-
 lisp/nxml/nxml-outln.el                            |    4 +-
 lisp/nxml/nxml-parse.el                            |    4 +-
 lisp/nxml/nxml-rap.el                              |    4 +-
 lisp/nxml/nxml-util.el                             |    4 +-
 lisp/nxml/rng-cmpct.el                             |    4 +-
 lisp/nxml/rng-dt.el                                |    4 +-
 lisp/nxml/rng-loc.el                               |    4 +-
 lisp/nxml/rng-maint.el                             |    4 +-
 lisp/nxml/rng-match.el                             |    4 +-
 lisp/nxml/rng-nxml.el                              |    4 +-
 lisp/nxml/rng-parse.el                             |    4 +-
 lisp/nxml/rng-pttrn.el                             |    4 +-
 lisp/nxml/rng-uri.el                               |    4 +-
 lisp/nxml/rng-util.el                              |    4 +-
 lisp/nxml/rng-valid.el                             |    4 +-
 lisp/nxml/rng-xsd.el                               |    4 +-
 lisp/nxml/xmltok.el                                |    4 +-
 lisp/nxml/xsd-regexp.el                            |    4 +-
 lisp/obarray.el                                    |    2 +-
 lisp/obsolete/autoarg.el                           |    2 +-
 lisp/obsolete/autoload.el                          |    2 +-
 lisp/obsolete/bruce.el                             |    2 +-
 lisp/obsolete/cc-compat.el                         |    2 +-
 lisp/obsolete/cl-compat.el                         |    2 +-
 lisp/obsolete/cl.el                                |    2 +-
 lisp/obsolete/crisp.el                             |    2 +-
 lisp/obsolete/eieio-compat.el                      |    2 +-
 lisp/obsolete/eudcb-ph.el                          |    2 +-
 lisp/obsolete/gs.el                                |    2 +-
 lisp/obsolete/gulp.el                              |    2 +-
 lisp/obsolete/html2text.el                         |    2 +-
 lisp/obsolete/info-edit.el                         |    2 +-
 lisp/obsolete/inversion.el                         |    2 +-
 lisp/obsolete/iswitchb.el                          |    2 +-
 lisp/obsolete/landmark.el                          |    2 +-
 lisp/obsolete/linum.el                             |    2 +-
 lisp/obsolete/longlines.el                         |    4 +-
 lisp/obsolete/makesum.el                           |    2 +-
 lisp/obsolete/mantemp.el                           |    2 +-
 lisp/obsolete/messcompat.el                        |    2 +-
 lisp/obsolete/metamail.el                          |    2 +-
 lisp/obsolete/mh-compat.el                         |    2 +-
 lisp/obsolete/netrc.el                             |    2 +-
 lisp/obsolete/nnir.el                              |    2 +-
 lisp/obsolete/otodo-mode.el                        |    2 +-
 lisp/obsolete/pgg-def.el                           |    2 +-
 lisp/obsolete/pgg-gpg.el                           |    2 +-
 lisp/obsolete/pgg-parse.el                         |    2 +-
 lisp/obsolete/pgg-pgp.el                           |    2 +-
 lisp/obsolete/pgg-pgp5.el                          |    2 +-
 lisp/obsolete/pgg.el                               |    2 +-
 lisp/obsolete/ps-def.el                            |    4 +-
 lisp/obsolete/quickurl.el                          |    2 +-
 lisp/obsolete/rcompile.el                          |    2 +-
 lisp/obsolete/rfc2368.el                           |    2 +-
 lisp/obsolete/rlogin.el                            |    2 +-
 lisp/obsolete/sb-image.el                          |    2 +-
 lisp/obsolete/starttls.el                          |    2 +-
 lisp/obsolete/sup-mouse.el                         |    2 +-
 lisp/obsolete/terminal.el                          |    2 +-
 lisp/obsolete/thumbs.el                            |    2 +-
 lisp/obsolete/tls.el                               |    2 +-
 lisp/obsolete/tpu-edt.el                           |    2 +-
 lisp/obsolete/tpu-extras.el                        |    2 +-
 lisp/obsolete/tpu-mapper.el                        |    2 +-
 lisp/obsolete/uce.el                               |    2 +-
 lisp/obsolete/url-about.el                         |    2 +-
 lisp/obsolete/url-dired.el                         |    2 +-
 lisp/obsolete/url-ns.el                            |    2 +-
 lisp/obsolete/vc-arch.el                           |    2 +-
 lisp/obsolete/vc-mtn.el                            |    2 +-
 lisp/obsolete/vip.el                               |    2 +-
 lisp/obsolete/vt-control.el                        |    2 +-
 lisp/obsolete/vt100-led.el                         |    2 +-
 lisp/obsolete/ws-mode.el                           |    2 +-
 lisp/obsolete/yow.el                               |    2 +-
 lisp/org/ChangeLog.1                               |   18 +-
 lisp/org/ob-C.el                                   |    2 +-
 lisp/org/ob-R.el                                   |    2 +-
 lisp/org/ob-awk.el                                 |    2 +-
 lisp/org/ob-calc.el                                |    2 +-
 lisp/org/ob-clojure.el                             |    2 +-
 lisp/org/ob-comint.el                              |    2 +-
 lisp/org/ob-core.el                                |    2 +-
 lisp/org/ob-css.el                                 |    2 +-
 lisp/org/ob-ditaa.el                               |    2 +-
 lisp/org/ob-dot.el                                 |    2 +-
 lisp/org/ob-emacs-lisp.el                          |    2 +-
 lisp/org/ob-eshell.el                              |    2 +-
 lisp/org/ob-eval.el                                |    2 +-
 lisp/org/ob-exp.el                                 |    2 +-
 lisp/org/ob-forth.el                               |    2 +-
 lisp/org/ob-fortran.el                             |    2 +-
 lisp/org/ob-gnuplot.el                             |    2 +-
 lisp/org/ob-groovy.el                              |    2 +-
 lisp/org/ob-haskell.el                             |    2 +-
 lisp/org/ob-java.el                                |    2 +-
 lisp/org/ob-js.el                                  |    2 +-
 lisp/org/ob-julia.el                               |    2 +-
 lisp/org/ob-latex.el                               |    2 +-
 lisp/org/ob-lilypond.el                            |    2 +-
 lisp/org/ob-lisp.el                                |    2 +-
 lisp/org/ob-lob.el                                 |    2 +-
 lisp/org/ob-lua.el                                 |    2 +-
 lisp/org/ob-makefile.el                            |    2 +-
 lisp/org/ob-matlab.el                              |    2 +-
 lisp/org/ob-maxima.el                              |    2 +-
 lisp/org/ob-ocaml.el                               |    2 +-
 lisp/org/ob-octave.el                              |    2 +-
 lisp/org/ob-org.el                                 |    2 +-
 lisp/org/ob-perl.el                                |    2 +-
 lisp/org/ob-plantuml.el                            |    4 +-
 lisp/org/ob-processing.el                          |    2 +-
 lisp/org/ob-python.el                              |    2 +-
 lisp/org/ob-ref.el                                 |    2 +-
 lisp/org/ob-ruby.el                                |    2 +-
 lisp/org/ob-sass.el                                |    2 +-
 lisp/org/ob-scheme.el                              |    2 +-
 lisp/org/ob-screen.el                              |    2 +-
 lisp/org/ob-sed.el                                 |    2 +-
 lisp/org/ob-shell.el                               |    2 +-
 lisp/org/ob-sql.el                                 |    2 +-
 lisp/org/ob-sqlite.el                              |    2 +-
 lisp/org/ob-table.el                               |    2 +-
 lisp/org/ob-tangle.el                              |    2 +-
 lisp/org/ob.el                                     |    2 +-
 lisp/org/oc-basic.el                               |    2 +-
 lisp/org/oc-biblatex.el                            |    4 +-
 lisp/org/oc-bibtex.el                              |    2 +-
 lisp/org/oc-csl.el                                 |    2 +-
 lisp/org/oc-natbib.el                              |    2 +-
 lisp/org/oc.el                                     |    4 +-
 lisp/org/ol-bbdb.el                                |    4 +-
 lisp/org/ol-bibtex.el                              |    4 +-
 lisp/org/ol-docview.el                             |    4 +-
 lisp/org/ol-doi.el                                 |    2 +-
 lisp/org/ol-eshell.el                              |    2 +-
 lisp/org/ol-eww.el                                 |    2 +-
 lisp/org/ol-gnus.el                                |    4 +-
 lisp/org/ol-info.el                                |    4 +-
 lisp/org/ol-irc.el                                 |    2 +-
 lisp/org/ol-man.el                                 |    4 +-
 lisp/org/ol-mhe.el                                 |    4 +-
 lisp/org/ol-rmail.el                               |    4 +-
 lisp/org/ol-w3m.el                                 |    4 +-
 lisp/org/ol.el                                     |    4 +-
 lisp/org/org-agenda.el                             |    4 +-
 lisp/org/org-archive.el                            |    4 +-
 lisp/org/org-attach-git.el                         |    2 +-
 lisp/org/org-attach.el                             |    2 +-
 lisp/org/org-capture.el                            |    6 +-
 lisp/org/org-clock.el                              |    4 +-
 lisp/org/org-colview.el                            |    4 +-
 lisp/org/org-compat.el                             |    6 +-
 lisp/org/org-crypt.el                              |    2 +-
 lisp/org/org-ctags.el                              |    4 +-
 lisp/org/org-cycle.el                              |    2 +-
 lisp/org/org-datetree.el                           |    4 +-
 lisp/org/org-duration.el                           |    4 +-
 lisp/org/org-element.el                            |   16 +-
 lisp/org/org-entities.el                           |   25 +-
 lisp/org/org-faces.el                              |    4 +-
 lisp/org/org-feed.el                               |    4 +-
 lisp/org/org-fold-core.el                          |    4 +-
 lisp/org/org-fold.el                               |    2 +-
 lisp/org/org-footnote.el                           |    4 +-
 lisp/org/org-goto.el                               |    4 +-
 lisp/org/org-habit.el                              |    4 +-
 lisp/org/org-id.el                                 |    4 +-
 lisp/org/org-indent.el                             |    4 +-
 lisp/org/org-inlinetask.el                         |    4 +-
 lisp/org/org-keys.el                               |    2 +-
 lisp/org/org-lint.el                               |    4 +-
 lisp/org/org-list.el                               |    4 +-
 lisp/org/org-macro.el                              |    4 +-
 lisp/org/org-macs.el                               |   34 +-
 lisp/org/org-mobile.el                             |    4 +-
 lisp/org/org-mouse.el                              |    2 +-
 lisp/org/org-num.el                                |    4 +-
 lisp/org/org-pcomplete.el                          |    4 +-
 lisp/org/org-persist.el                            |   21 +-
 lisp/org/org-plot.el                               |    2 +-
 lisp/org/org-protocol.el                           |   25 +-
 lisp/org/org-refile.el                             |    4 +-
 lisp/org/org-src.el                                |   11 +-
 lisp/org/org-table.el                              |    6 +-
 lisp/org/org-tempo.el                              |    4 +-
 lisp/org/org-timer.el                              |    4 +-
 lisp/org/org-version.el                            |    4 +-
 lisp/org/org.el                                    |   16 +-
 lisp/org/ox-ascii.el                               |    4 +-
 lisp/org/ox-beamer.el                              |    6 +-
 lisp/org/ox-html.el                                |    4 +-
 lisp/org/ox-icalendar.el                           |    4 +-
 lisp/org/ox-koma-letter.el                         |    4 +-
 lisp/org/ox-latex.el                               |   15 +-
 lisp/org/ox-man.el                                 |    4 +-
 lisp/org/ox-md.el                                  |    6 +-
 lisp/org/ox-odt.el                                 |    4 +-
 lisp/org/ox-org.el                                 |    4 +-
 lisp/org/ox-publish.el                             |    4 +-
 lisp/org/ox-texinfo.el                             |    4 +-
 lisp/org/ox.el                                     |    4 +-
 lisp/outline.el                                    |    4 +-
 lisp/paren.el                                      |    2 +-
 lisp/password-cache.el                             |    2 +-
 lisp/pcmpl-cvs.el                                  |    2 +-
 lisp/pcmpl-git.el                                  |    4 +-
 lisp/pcmpl-gnu.el                                  |    2 +-
 lisp/pcmpl-linux.el                                |    6 +-
 lisp/pcmpl-rpm.el                                  |    2 +-
 lisp/pcmpl-unix.el                                 |    2 +-
 lisp/pcmpl-x.el                                    |    2 +-
 lisp/pcomplete.el                                  |   16 +-
 lisp/pgtk-dnd.el                                   |    2 +-
 lisp/pixel-scroll.el                               |    2 +-
 lisp/play/5x5.el                                   |    2 +-
 lisp/play/animate.el                               |    2 +-
 lisp/play/blackbox.el                              |    2 +-
 lisp/play/bubbles.el                               |    2 +-
 lisp/play/cookie1.el                               |    2 +-
 lisp/play/decipher.el                              |    8 +-
 lisp/play/dissociate.el                            |    2 +-
 lisp/play/doctor.el                                |    2 +-
 lisp/play/dunnet.el                                |    2 +-
 lisp/play/fortune.el                               |    2 +-
 lisp/play/gamegrid.el                              |    2 +-
 lisp/play/gametree.el                              |    2 +-
 lisp/play/gomoku.el                                |    2 +-
 lisp/play/handwrite.el                             |    4 +-
 lisp/play/life.el                                  |    2 +-
 lisp/play/morse.el                                 |    2 +-
 lisp/play/mpuz.el                                  |    2 +-
 lisp/play/pong.el                                  |    2 +-
 lisp/play/snake.el                                 |    2 +-
 lisp/play/solitaire.el                             |    2 +-
 lisp/play/spook.el                                 |    2 +-
 lisp/play/tetris.el                                |    2 +-
 lisp/play/zone.el                                  |    2 +-
 lisp/plstore.el                                    |    2 +-
 lisp/printing.el                                   |    4 +-
 lisp/proced.el                                     |    2 +-
 lisp/profiler.el                                   |    2 +-
 lisp/progmodes/antlr-mode.el                       |    2 +-
 lisp/progmodes/asm-mode.el                         |    8 +-
 lisp/progmodes/autoconf.el                         |    2 +-
 lisp/progmodes/bat-mode.el                         |    2 +-
 lisp/progmodes/bug-reference.el                    |    2 +-
 lisp/progmodes/c-ts-common.el                      |   13 +-
 lisp/progmodes/c-ts-mode.el                        |   73 +-
 lisp/progmodes/cc-align.el                         |    2 +-
 lisp/progmodes/cc-awk.el                           |    2 +-
 lisp/progmodes/cc-bytecomp.el                      |    2 +-
 lisp/progmodes/cc-cmds.el                          |    2 +-
 lisp/progmodes/cc-defs.el                          |    2 +-
 lisp/progmodes/cc-engine.el                        |   10 +-
 lisp/progmodes/cc-fonts.el                         |    4 +-
 lisp/progmodes/cc-guess.el                         |    2 +-
 lisp/progmodes/cc-langs.el                         |    4 +-
 lisp/progmodes/cc-menus.el                         |    2 +-
 lisp/progmodes/cc-mode.el                          |   15 +-
 lisp/progmodes/cc-styles.el                        |    2 +-
 lisp/progmodes/cc-vars.el                          |    2 +-
 lisp/progmodes/cfengine.el                         |    2 +-
 lisp/progmodes/cl-font-lock.el                     |    4 +-
 lisp/progmodes/cmacexp.el                          |    2 +-
 lisp/progmodes/cmake-ts-mode.el                    |   48 +-
 lisp/progmodes/compile.el                          |   64 +-
 lisp/progmodes/cperl-mode.el                       |  123 +-
 lisp/progmodes/cpp.el                              |    2 +-
 lisp/progmodes/csharp-mode.el                      |    2 +-
 lisp/progmodes/cwarn.el                            |    2 +-
 lisp/progmodes/dcl-mode.el                         |    2 +-
 lisp/progmodes/dockerfile-ts-mode.el               |   49 +-
 lisp/progmodes/ebnf-abn.el                         |    4 +-
 lisp/progmodes/ebnf-bnf.el                         |    4 +-
 lisp/progmodes/ebnf-dtd.el                         |    4 +-
 lisp/progmodes/ebnf-ebx.el                         |    4 +-
 lisp/progmodes/ebnf-iso.el                         |    4 +-
 lisp/progmodes/ebnf-otz.el                         |    4 +-
 lisp/progmodes/ebnf-yac.el                         |    4 +-
 lisp/progmodes/ebnf2ps.el                          |    4 +-
 lisp/progmodes/ebrowse.el                          |    2 +-
 lisp/progmodes/eglot.el                            |  353 +--
 lisp/progmodes/elisp-mode.el                       |   33 +-
 lisp/progmodes/elixir-ts-mode.el                   |    2 +-
 lisp/progmodes/erts-mode.el                        |    2 +-
 lisp/progmodes/etags-regen.el                      |  431 +++
 lisp/progmodes/etags.el                            |    3 +-
 lisp/progmodes/executable.el                       |    2 +-
 lisp/progmodes/f90.el                              |    2 +-
 lisp/progmodes/flymake-cc.el                       |    2 +-
 lisp/progmodes/flymake-proc.el                     |    2 +-
 lisp/progmodes/flymake.el                          |   10 +-
 lisp/progmodes/fortran.el                          |    2 +-
 lisp/progmodes/gdb-mi.el                           |   71 +-
 lisp/progmodes/glasses.el                          |    2 +-
 lisp/progmodes/go-ts-mode.el                       |    2 +-
 lisp/progmodes/grep.el                             |    2 +-
 lisp/progmodes/gud.el                              |   10 +-
 lisp/progmodes/heex-ts-mode.el                     |    2 +-
 lisp/progmodes/hideif.el                           |    6 +-
 lisp/progmodes/hideshow.el                         |    2 +-
 lisp/progmodes/icon.el                             |    2 +-
 lisp/progmodes/idlw-complete-structtag.el          |    2 +-
 lisp/progmodes/idlw-help.el                        |    2 +-
 lisp/progmodes/idlw-shell.el                       |    4 +-
 lisp/progmodes/idlw-toolbar.el                     |    2 +-
 lisp/progmodes/idlwave.el                          |    4 +-
 lisp/progmodes/inf-lisp.el                         |    2 +-
 lisp/progmodes/java-ts-mode.el                     |    2 +-
 lisp/progmodes/js.el                               |   93 +-
 lisp/progmodes/json-ts-mode.el                     |    2 +-
 lisp/progmodes/ld-script.el                        |    2 +-
 lisp/progmodes/lua-ts-mode.el                      |   59 +-
 lisp/progmodes/m4-mode.el                          |    2 +-
 lisp/progmodes/make-mode.el                        |    2 +-
 lisp/progmodes/meta-mode.el                        |    2 +-
 lisp/progmodes/mixal-mode.el                       |    2 +-
 lisp/progmodes/octave.el                           |    2 +-
 lisp/progmodes/opascal.el                          |    2 +-
 lisp/progmodes/pascal.el                           |    2 +-
 lisp/progmodes/perl-mode.el                        |    6 +-
 lisp/progmodes/prog-mode.el                        |    2 +-
 lisp/progmodes/project.el                          |   69 +-
 lisp/progmodes/prolog.el                           |    6 +-
 lisp/progmodes/ps-mode.el                          |    2 +-
 lisp/progmodes/python.el                           |  269 +-
 lisp/progmodes/ruby-mode.el                        |   26 +-
 lisp/progmodes/ruby-ts-mode.el                     |   28 +-
 lisp/progmodes/rust-ts-mode.el                     |   13 +-
 lisp/progmodes/scheme.el                           |    2 +-
 lisp/progmodes/sh-script.el                        |   12 +-
 lisp/progmodes/simula.el                           |    2 +-
 lisp/progmodes/sql.el                              |    2 +-
 lisp/progmodes/subword.el                          |    2 +-
 lisp/progmodes/tcl.el                              |    2 +-
 lisp/progmodes/typescript-ts-mode.el               |    4 +-
 lisp/progmodes/vera-mode.el                        |    2 +-
 lisp/progmodes/verilog-mode.el                     |    2 +-
 lisp/progmodes/vhdl-mode.el                        |   34 +-
 lisp/progmodes/which-func.el                       |    2 +-
 lisp/progmodes/xref.el                             |    2 +-
 lisp/progmodes/xscheme.el                          |    2 +-
 lisp/ps-bdf.el                                     |    4 +-
 lisp/ps-mule.el                                    |    4 +-
 lisp/ps-print.el                                   |    4 +-
 lisp/ps-samp.el                                    |    4 +-
 lisp/recentf.el                                    |   20 +-
 lisp/rect.el                                       |   13 +-
 lisp/register.el                                   |  449 ++-
 lisp/registry.el                                   |    2 +-
 lisp/repeat.el                                     |    2 +-
 lisp/replace.el                                    |    2 +-
 lisp/reposition.el                                 |    2 +-
 lisp/reveal.el                                     |    2 +-
 lisp/rfn-eshadow.el                                |    2 +-
 lisp/rot13.el                                      |    2 +-
 lisp/rtree.el                                      |    2 +-
 lisp/ruler-mode.el                                 |    2 +-
 lisp/savehist.el                                   |    2 +-
 lisp/saveplace.el                                  |    2 +-
 lisp/scroll-all.el                                 |    2 +-
 lisp/scroll-bar.el                                 |    2 +-
 lisp/scroll-lock.el                                |    2 +-
 lisp/select.el                                     |    2 +-
 lisp/server.el                                     |    6 +-
 lisp/ses.el                                        |   92 +-
 lisp/shadowfile.el                                 |    2 +-
 lisp/shell.el                                      |    2 +-
 lisp/simple.el                                     |   91 +-
 lisp/skeleton.el                                   |    2 +-
 lisp/so-long.el                                    |    2 +-
 lisp/sort.el                                       |   23 +-
 lisp/soundex.el                                    |    2 +-
 lisp/speedbar.el                                   |    2 +-
 lisp/sqlite-mode.el                                |    2 +-
 lisp/sqlite.el                                     |    2 +-
 lisp/startup.el                                    |  224 +-
 lisp/strokes.el                                    |    2 +-
 lisp/subr.el                                       |   54 +-
 lisp/svg.el                                        |    2 +-
 lisp/t-mouse.el                                    |    2 +-
 lisp/tab-bar.el                                    |   14 +-
 lisp/tab-line.el                                   |    4 +-
 lisp/tabify.el                                     |    2 +-
 lisp/talk.el                                       |    2 +-
 lisp/tar-mode.el                                   |    2 +-
 lisp/tempo.el                                      |   15 +-
 lisp/term.el                                       |   17 +-
 lisp/term/AT386.el                                 |    2 +-
 lisp/term/README                                   |    2 +-
 lisp/term/android-win.el                           |   63 +-
 lisp/term/common-win.el                            |    2 +-
 lisp/term/fbterm.el                                |    2 +-
 lisp/term/haiku-win.el                             |    2 +-
 lisp/term/internal.el                              |    2 +-
 lisp/term/iris-ansi.el                             |    2 +-
 lisp/term/konsole.el                               |    2 +-
 lisp/term/linux.el                                 |    6 +-
 lisp/term/news.el                                  |    2 +-
 lisp/term/ns-win.el                                |    2 +-
 lisp/term/pc-win.el                                |    4 +-
 lisp/term/pgtk-win.el                              |    2 +-
 lisp/term/rxvt.el                                  |    2 +-
 lisp/term/screen.el                                |    2 +-
 lisp/term/st.el                                    |    2 +-
 lisp/term/sun.el                                   |    2 +-
 lisp/term/tmux.el                                  |    2 +-
 lisp/term/tty-colors.el                            |    2 +-
 lisp/term/tvi970.el                                |    2 +-
 lisp/term/vt100.el                                 |    2 +-
 lisp/term/w32-win.el                               |    2 +-
 lisp/term/w32console.el                            |    2 +-
 lisp/term/wyse50.el                                |    2 +-
 lisp/term/x-win.el                                 |    2 +-
 lisp/term/xterm.el                                 |    2 +-
 lisp/textmodes/artist.el                           |    2 +-
 lisp/textmodes/bib-mode.el                         |    2 +-
 lisp/textmodes/bibtex-style.el                     |    2 +-
 lisp/textmodes/bibtex.el                           |   16 +-
 lisp/textmodes/conf-mode.el                        |    2 +-
 lisp/textmodes/css-mode.el                         |    2 +-
 lisp/textmodes/dns-mode.el                         |    2 +-
 lisp/textmodes/emacs-authors-mode.el               |    2 +-
 lisp/textmodes/emacs-news-mode.el                  |    2 +-
 lisp/textmodes/enriched.el                         |    4 +-
 lisp/textmodes/fill.el                             |    4 +-
 lisp/textmodes/flyspell.el                         |    2 +-
 lisp/textmodes/glyphless-mode.el                   |    2 +-
 lisp/textmodes/html-ts-mode.el                     |    2 +-
 lisp/textmodes/ispell.el                           |   16 +-
 lisp/textmodes/less-css-mode.el                    |    2 +-
 lisp/textmodes/makeinfo.el                         |    2 +-
 lisp/textmodes/mhtml-mode.el                       |    4 +-
 lisp/textmodes/nroff-mode.el                       |    4 +-
 lisp/textmodes/page-ext.el                         |    4 +-
 lisp/textmodes/page.el                             |   12 +-
 lisp/textmodes/paragraphs.el                       |    4 +-
 lisp/textmodes/picture.el                          |    4 +-
 lisp/textmodes/pixel-fill.el                       |   70 +-
 lisp/textmodes/po.el                               |    2 +-
 lisp/textmodes/refbib.el                           |    2 +-
 lisp/textmodes/refer.el                            |    2 +-
 lisp/textmodes/refill.el                           |    8 +-
 lisp/textmodes/reftex-auc.el                       |    2 +-
 lisp/textmodes/reftex-cite.el                      |    2 +-
 lisp/textmodes/reftex-dcr.el                       |    2 +-
 lisp/textmodes/reftex-global.el                    |    2 +-
 lisp/textmodes/reftex-index.el                     |    2 +-
 lisp/textmodes/reftex-parse.el                     |    2 +-
 lisp/textmodes/reftex-ref.el                       |    2 +-
 lisp/textmodes/reftex-sel.el                       |    2 +-
 lisp/textmodes/reftex-toc.el                       |    2 +-
 lisp/textmodes/reftex-vars.el                      |    2 +-
 lisp/textmodes/reftex.el                           |    2 +-
 lisp/textmodes/remember.el                         |    9 +-
 lisp/textmodes/rst.el                              |    2 +-
 lisp/textmodes/sgml-mode.el                        |    4 +-
 lisp/textmodes/string-edit.el                      |    2 +-
 lisp/textmodes/table.el                            |    4 +-
 lisp/textmodes/tex-mode.el                         |    3 +-
 lisp/textmodes/texinfmt.el                         |    2 +-
 lisp/textmodes/texinfo.el                          |    2 +-
 lisp/textmodes/texnfo-upd.el                       |    2 +-
 lisp/textmodes/text-mode.el                        |   23 +-
 lisp/textmodes/tildify.el                          |    4 +-
 lisp/textmodes/toml-ts-mode.el                     |    2 +-
 lisp/textmodes/two-column.el                       |    4 +-
 lisp/textmodes/underline.el                        |    4 +-
 lisp/textmodes/word-wrap-mode.el                   |    2 +-
 lisp/textmodes/yaml-ts-mode.el                     |   28 +-
 lisp/thingatpt.el                                  |    4 +-
 lisp/thread.el                                     |    2 +-
 lisp/time-stamp.el                                 |    2 +-
 lisp/time.el                                       |    4 +-
 lisp/timezone.el                                   |    2 +-
 lisp/tmm.el                                        |    2 +-
 lisp/tool-bar.el                                   |   21 +-
 lisp/tooltip.el                                    |    2 +-
 lisp/touch-screen.el                               |   12 +-
 lisp/transient.el                                  | 1618 +++++-----
 lisp/tree-widget.el                                |    2 +-
 lisp/treesit.el                                    |  179 +-
 lisp/tutorial.el                                   |    2 +-
 lisp/type-break.el                                 |    2 +-
 lisp/uniquify.el                                   |    2 +-
 lisp/url/ChangeLog.1                               |    2 +-
 lisp/url/url-auth.el                               |    2 +-
 lisp/url/url-cache.el                              |    2 +-
 lisp/url/url-cid.el                                |    2 +-
 lisp/url/url-cookie.el                             |    2 +-
 lisp/url/url-dav.el                                |    2 +-
 lisp/url/url-domsuf.el                             |    2 +-
 lisp/url/url-expand.el                             |    2 +-
 lisp/url/url-file.el                               |    2 +-
 lisp/url/url-ftp.el                                |    2 +-
 lisp/url/url-future.el                             |    2 +-
 lisp/url/url-gw.el                                 |    2 +-
 lisp/url/url-handlers.el                           |    2 +-
 lisp/url/url-history.el                            |    2 +-
 lisp/url/url-http.el                               |    6 +-
 lisp/url/url-imap.el                               |    2 +-
 lisp/url/url-irc.el                                |    2 +-
 lisp/url/url-ldap.el                               |    2 +-
 lisp/url/url-mailto.el                             |    2 +-
 lisp/url/url-methods.el                            |    2 +-
 lisp/url/url-misc.el                               |    2 +-
 lisp/url/url-news.el                               |    2 +-
 lisp/url/url-nfs.el                                |    2 +-
 lisp/url/url-parse.el                              |    2 +-
 lisp/url/url-privacy.el                            |   12 +-
 lisp/url/url-proxy.el                              |    2 +-
 lisp/url/url-queue.el                              |    2 +-
 lisp/url/url-tramp.el                              |    2 +-
 lisp/url/url-util.el                               |    4 +-
 lisp/url/url-vars.el                               |   11 +-
 lisp/url/url.el                                    |    2 +-
 lisp/use-package/use-package-bind-key.el           |    2 +-
 lisp/use-package/use-package-core.el               |    6 +-
 lisp/use-package/use-package-delight.el            |    2 +-
 lisp/use-package/use-package-diminish.el           |    2 +-
 .../use-package-ensure-system-package.el           |    3 +-
 lisp/use-package/use-package-ensure.el             |    2 +-
 lisp/use-package/use-package-jump.el               |    2 +-
 lisp/use-package/use-package-lint.el               |    2 +-
 lisp/use-package/use-package.el                    |    2 +-
 lisp/userlock.el                                   |    2 +-
 lisp/vc/add-log.el                                 |    2 +-
 lisp/vc/compare-w.el                               |    2 +-
 lisp/vc/cvs-status.el                              |    2 +-
 lisp/vc/diff-mode.el                               |    4 +-
 lisp/vc/diff.el                                    |    2 +-
 lisp/vc/ediff-diff.el                              |    2 +-
 lisp/vc/ediff-help.el                              |    2 +-
 lisp/vc/ediff-hook.el                              |    2 +-
 lisp/vc/ediff-init.el                              |    2 +-
 lisp/vc/ediff-merg.el                              |    2 +-
 lisp/vc/ediff-mult.el                              |    2 +-
 lisp/vc/ediff-ptch.el                              |    2 +-
 lisp/vc/ediff-util.el                              |    2 +-
 lisp/vc/ediff-vers.el                              |    2 +-
 lisp/vc/ediff-wind.el                              |    2 +-
 lisp/vc/ediff.el                                   |    2 +-
 lisp/vc/log-edit.el                                |  235 +-
 lisp/vc/log-view.el                                |    8 +-
 lisp/vc/pcvs-defs.el                               |    2 +-
 lisp/vc/pcvs-info.el                               |    2 +-
 lisp/vc/pcvs-parse.el                              |    2 +-
 lisp/vc/pcvs-util.el                               |    2 +-
 lisp/vc/pcvs.el                                    |    2 +-
 lisp/vc/smerge-mode.el                             |    2 +-
 lisp/vc/vc-annotate.el                             |   12 +-
 lisp/vc/vc-bzr.el                                  |    2 +-
 lisp/vc/vc-cvs.el                                  |    2 +-
 lisp/vc/vc-dav.el                                  |    2 +-
 lisp/vc/vc-dir.el                                  |    2 +-
 lisp/vc/vc-dispatcher.el                           |    2 +-
 lisp/vc/vc-filewise.el                             |    2 +-
 lisp/vc/vc-git.el                                  |   59 +-
 lisp/vc/vc-hg.el                                   |   23 +-
 lisp/vc/vc-hooks.el                                |   16 +-
 lisp/vc/vc-rcs.el                                  |    4 +-
 lisp/vc/vc-sccs.el                                 |    2 +-
 lisp/vc/vc-src.el                                  |    2 +-
 lisp/vc/vc-svn.el                                  |    2 +-
 lisp/vc/vc.el                                      |  129 +-
 lisp/vcursor.el                                    |    2 +-
 lisp/version.el                                    |    2 +-
 lisp/view.el                                       |    2 +-
 lisp/visual-wrap.el                                |  204 ++
 lisp/w32-fns.el                                    |    2 +-
 lisp/w32-vars.el                                   |    2 +-
 lisp/wdired.el                                     |    2 +-
 lisp/whitespace.el                                 |    8 +-
 lisp/wid-browse.el                                 |    2 +-
 lisp/wid-edit.el                                   |    2 +-
 lisp/widget.el                                     |    2 +-
 lisp/windmove.el                                   |    4 +-
 lisp/window.el                                     |   65 +-
 lisp/winner.el                                     |    2 +-
 lisp/woman.el                                      |    5 +-
 lisp/x-dnd.el                                      |    2 +-
 lisp/xdg.el                                        |    2 +-
 lisp/xml.el                                        |    2 +-
 lisp/xt-mouse.el                                   |   43 +-
 lisp/xwidget.el                                    |    2 +-
 lisp/yank-media.el                                 |    2 +-
 lwlib/ChangeLog.1                                  |    2 +-
 lwlib/Makefile.in                                  |    2 +-
 lwlib/deps.mk                                      |    2 +-
 lwlib/lwlib-Xaw.c                                  |    2 +-
 lwlib/lwlib-Xlw.c                                  |    2 +-
 lwlib/lwlib-Xm.c                                   |    2 +-
 lwlib/lwlib-int.h                                  |    2 +-
 lwlib/lwlib-utils.c                                |    2 +-
 lwlib/lwlib-widget.h                               |    2 +-
 lwlib/lwlib.c                                      |    2 +-
 lwlib/lwlib.h                                      |    2 +-
 lwlib/xlwmenu.c                                    |    2 +-
 lwlib/xlwmenu.h                                    |    2 +-
 lwlib/xlwmenuP.h                                   |    2 +-
 m4/00gnulib.m4                                     |   12 +-
 m4/__inline.m4                                     |    2 +-
 m4/absolute-header.m4                              |    6 +-
 m4/acl.m4                                          |    8 +-
 m4/alloca.m4                                       |    2 +-
 m4/assert_h.m4                                     |    8 +-
 m4/builtin-expect.m4                               |    2 +-
 m4/byteswap.m4                                     |    2 +-
 m4/c-bool.m4                                       |    2 +-
 m4/canonicalize.m4                                 |   28 +-
 m4/clock_time.m4                                   |    6 +-
 m4/codeset.m4                                      |    2 +-
 m4/copy-file-range.m4                              |   43 +-
 m4/d-type.m4                                       |    2 +-
 m4/dirent_h.m4                                     |   11 +-
 m4/dirfd.m4                                        |   15 +-
 m4/double-slash-root.m4                            |    2 +-
 m4/dup2.m4                                         |    6 +-
 m4/eealloc.m4                                      |    2 +-
 m4/environ.m4                                      |    2 +-
 m4/errno_h.m4                                      |    2 +-
 m4/euidaccess.m4                                   |    2 +-
 m4/execinfo.m4                                     |    2 +-
 m4/explicit_bzero.m4                               |    2 +-
 m4/extensions.m4                                   |    2 +-
 m4/extern-inline.m4                                |    2 +-
 m4/faccessat.m4                                    |    2 +-
 m4/fchmodat.m4                                     |    2 +-
 m4/fcntl.m4                                        |    2 +-
 m4/fcntl_h.m4                                      |    2 +-
 m4/fdopendir.m4                                    |    2 +-
 m4/filemode.m4                                     |    2 +-
 m4/flexmember.m4                                   |    2 +-
 m4/fpending.m4                                     |    2 +-
 m4/fpieee.m4                                       |    2 +-
 m4/free.m4                                         |    2 +-
 m4/fstatat.m4                                      |    6 +-
 m4/fsusage.m4                                      |    2 +-
 m4/fsync.m4                                        |    2 +-
 m4/futimens.m4                                     |    2 +-
 m4/getdelim.m4                                     |    2 +-
 m4/getdtablesize.m4                                |    2 +-
 m4/getgroups.m4                                    |    8 +-
 m4/getline.m4                                      |    2 +-
 m4/getloadavg.m4                                   |   12 +-
 m4/getopt.m4                                       |    8 +-
 m4/getrandom.m4                                    |    8 +-
 m4/gettime.m4                                      |    6 +-
 m4/gettimeofday.m4                                 |    6 +-
 m4/gnulib-common.m4                                |   62 +-
 m4/gnulib-comp.m4                                  |   11 +-
 m4/group-member.m4                                 |    2 +-
 m4/ieee754-h.m4                                    |    2 +-
 m4/include_next.m4                                 |   12 +-
 m4/inttypes.m4                                     |    2 +-
 m4/largefile.m4                                    |    6 +-
 m4/lchmod.m4                                       |    2 +-
 m4/libgmp.m4                                       |    2 +-
 m4/limits-h.m4                                     |    2 +-
 m4/lstat.m4                                        |    8 +-
 m4/malloc.m4                                       |   11 +-
 m4/manywarnings.m4                                 |   12 +-
 m4/mbstate_t.m4                                    |    2 +-
 m4/md5.m4                                          |    2 +-
 m4/memmem.m4                                       |    2 +-
 m4/mempcpy.m4                                      |    2 +-
 m4/memrchr.m4                                      |    2 +-
 m4/memset_explicit.m4                              |    8 +-
 m4/minmax.m4                                       |    2 +-
 m4/mkostemp.m4                                     |    2 +-
 m4/mktime.m4                                       |   12 +-
 m4/mode_t.m4                                       |    2 +-
 m4/multiarch.m4                                    |    2 +-
 m4/musl.m4                                         |    2 +-
 m4/nanosleep.m4                                    |   17 +-
 m4/ndk-build.m4                                    |    2 +-
 m4/nocrash.m4                                      |    2 +-
 m4/nproc.m4                                        |    2 +-
 m4/nstrftime.m4                                    |    2 +-
 m4/off_t.m4                                        |    2 +-
 m4/open-cloexec.m4                                 |    2 +-
 m4/open-slash.m4                                   |    2 +-
 m4/open.m4                                         |    6 +-
 m4/pathmax.m4                                      |    2 +-
 m4/pid_t.m4                                        |    2 +-
 m4/pipe2.m4                                        |    2 +-
 m4/printf-posix-rpl.m4                             |    2 +-
 m4/pselect.m4                                      |    2 +-
 m4/pthread_sigmask.m4                              |   16 +-
 m4/rawmemchr.m4                                    |    2 +-
 m4/readlink.m4                                     |    2 +-
 m4/readlinkat.m4                                   |    2 +-
 m4/readutmp.m4                                     |    8 +-
 m4/realloc.m4                                      |    9 +-
 m4/regex.m4                                        |   12 +-
 m4/sha1.m4                                         |    2 +-
 m4/sha256.m4                                       |    2 +-
 m4/sha512.m4                                       |    2 +-
 m4/sig2str.m4                                      |    2 +-
 m4/sigdescr_np.m4                                  |    2 +-
 m4/signal_h.m4                                     |    2 +-
 m4/socklen.m4                                      |    2 +-
 m4/ssize_t.m4                                      |    2 +-
 m4/st_dm_mode.m4                                   |    2 +-
 m4/stat-time.m4                                    |    2 +-
 m4/std-gnu11.m4                                    |    2 +-
 m4/stdalign.m4                                     |   14 +-
 m4/stddef_h.m4                                     |    2 +-
 m4/stdint.m4                                       |   12 +-
 m4/stdio_h.m4                                      |    2 +-
 m4/stdlib_h.m4                                     |    6 +-
 m4/stpcpy.m4                                       |    2 +-
 m4/string_h.m4                                     |    6 +-
 m4/strnlen.m4                                      |    2 +-
 m4/strtoimax.m4                                    |   16 +-
 m4/strtoll.m4                                      |    6 +-
 m4/symlink.m4                                      |    2 +-
 m4/sys_random_h.m4                                 |    2 +-
 m4/sys_select_h.m4                                 |    2 +-
 m4/sys_socket_h.m4                                 |    2 +-
 m4/sys_stat_h.m4                                   |    2 +-
 m4/sys_time_h.m4                                   |    2 +-
 m4/sys_types_h.m4                                  |    2 +-
 m4/tempname.m4                                     |    2 +-
 m4/time_h.m4                                       |    5 +-
 m4/time_r.m4                                       |    2 +-
 m4/time_rz.m4                                      |    2 +-
 m4/timegm.m4                                       |    2 +-
 m4/timer_time.m4                                   |    2 +-
 m4/timespec.m4                                     |    2 +-
 m4/tm_gmtoff.m4                                    |    2 +-
 m4/unistd_h.m4                                     |    5 +-
 m4/unlocked-io.m4                                  |    2 +-
 m4/utimens.m4                                      |    2 +-
 m4/utimensat.m4                                    |    2 +-
 m4/utimes.m4                                       |   14 +-
 m4/vararrays.m4                                    |    2 +-
 m4/warnings.m4                                     |    8 +-
 m4/wchar_t.m4                                      |    2 +-
 m4/xattr.m4                                        |    2 +-
 m4/year2038.m4                                     |    2 +-
 m4/zzgnulib.m4                                     |    2 +-
 make-dist                                          |    4 +-
 modules/modhelp.py                                 |    2 +-
 msdos/ChangeLog.1                                  |    2 +-
 msdos/INSTALL                                      |    2 +-
 msdos/README                                       |    4 +-
 msdos/autogen/Makefile.in                          |    2 +-
 msdos/autogen/config.in                            |    2 +-
 msdos/depfiles.bat                                 |    2 +-
 msdos/inttypes.h                                   |    2 +-
 msdos/langinfo.h                                   |    2 +-
 msdos/mainmake.v2                                  |    2 +-
 msdos/sed1v2.inp                                   |    2 +-
 msdos/sed1x.inp                                    |    2 +-
 msdos/sed2v2.inp                                   |    4 +-
 msdos/sed2x.inp                                    |    2 +-
 msdos/sed3v2.inp                                   |    2 +-
 msdos/sed4.inp                                     |    2 +-
 msdos/sed5x.inp                                    |    2 +-
 msdos/sed6.inp                                     |    2 +-
 msdos/sedadmin.inp                                 |    2 +-
 msdos/sedalloc.inp                                 |    2 +-
 msdos/sedleim.inp                                  |    6 +-
 msdos/sedlibcf.inp                                 |    2 +-
 msdos/sedlibmk.inp                                 |    2 +-
 msdos/sedlisp.inp                                  |    2 +-
 nextstep/ChangeLog.1                               |    2 +-
 nextstep/INSTALL                                   |    2 +-
 nextstep/Makefile.in                               |   14 +-
 nextstep/README                                    |    2 +-
 nextstep/templates/Info.plist.in                   |    2 +-
 nt/ChangeLog.1                                     |    2 +-
 nt/INSTALL                                         |    2 +-
 nt/INSTALL.W64                                     |    2 +-
 nt/Makefile.in                                     |    2 +-
 nt/README                                          |    2 +-
 nt/README.W32                                      |    2 +-
 nt/addpm.c                                         |    2 +-
 nt/cmdproxy.c                                      |    2 +-
 msdos/depfiles.bat => nt/configure.bat             |   13 +-
 nt/ddeclient.c                                     |    2 +-
 nt/epaths.nt                                       |    2 +-
 nt/gnulib-cfg.mk                                   |    2 +-
 nt/icons/README                                    |    6 +-
 nt/inc/grp.h                                       |    2 +-
 nt/inc/inttypes.h                                  |    2 +-
 nt/inc/langinfo.h                                  |    2 +-
 nt/inc/ms-w32.h                                    |    2 +-
 nt/inc/nl_types.h                                  |    2 +-
 nt/inc/stdint.h                                    |    2 +-
 nt/inc/sys/resource.h                              |    2 +-
 nt/inc/sys/socket.h                                |    2 +-
 nt/inc/sys/stat.h                                  |    2 +-
 nt/inc/sys/wait.h                                  |    2 +-
 nt/preprep.c                                       |  830 ++++++
 nt/runemacs.c                                      |    2 +-
 oldXMenu/Activate.c                                |    2 +-
 oldXMenu/ChangeLog.1                               |    2 +-
 oldXMenu/Create.c                                  |    2 +-
 oldXMenu/FindSel.c                                 |    2 +-
 oldXMenu/Internal.c                                |    2 +-
 oldXMenu/Makefile.in                               |    2 +-
 oldXMenu/deps.mk                                   |    2 +-
 oldXMenu/insque.c                                  |    2 +-
 src/.gdbinit                                       |    6 +-
 src/.lldbinit                                      |    2 +-
 src/ChangeLog.1                                    |    2 +-
 src/ChangeLog.10                                   |    2 +-
 src/ChangeLog.11                                   |    8 +-
 src/ChangeLog.12                                   |    2 +-
 src/ChangeLog.13                                   |    8 +-
 src/ChangeLog.2                                    |    2 +-
 src/ChangeLog.3                                    |    2 +-
 src/ChangeLog.4                                    |    2 +-
 src/ChangeLog.5                                    |    2 +-
 src/ChangeLog.6                                    |    2 +-
 src/ChangeLog.7                                    |    2 +-
 src/ChangeLog.8                                    |    4 +-
 src/ChangeLog.9                                    |    4 +-
 src/Makefile.in                                    |    2 +-
 src/README                                         |    2 +-
 src/alloc.c                                        |  302 +-
 src/android-asset.h                                |    2 +-
 src/android-emacs.c                                |    2 +-
 src/android.c                                      |   76 +-
 src/android.h                                      |    4 +-
 src/androidfns.c                                   |  231 +-
 src/androidfont.c                                  |    2 +-
 src/androidgui.h                                   |    3 +-
 src/androidmenu.c                                  |    4 +-
 src/androidselect.c                                |    8 +-
 src/androidterm.c                                  |   16 +-
 src/androidterm.h                                  |    8 +-
 src/androidvfs.c                                   |   14 +-
 src/atimer.c                                       |    2 +-
 src/atimer.h                                       |    2 +-
 src/bidi.c                                         |    4 +-
 src/bignum.c                                       |    2 +-
 src/bignum.h                                       |    2 +-
 src/blockinput.h                                   |    2 +-
 src/buffer.c                                       |   52 +-
 src/buffer.h                                       |    5 +-
 src/bytecode.c                                     |   53 +-
 src/callint.c                                      |    2 +-
 src/callproc.c                                     |    2 +-
 src/casefiddle.c                                   |    2 +-
 src/casetab.c                                      |    2 +-
 src/category.c                                     |   10 +-
 src/ccl.c                                          |   18 +-
 src/ccl.h                                          |    2 +-
 src/character.c                                    |    2 +-
 src/charset.c                                      |   30 +-
 src/charset.h                                      |   77 +-
 src/cm.c                                           |    2 +-
 src/cm.h                                           |    2 +-
 src/cmds.c                                         |    2 +-
 src/coding.c                                       |   23 +-
 src/coding.h                                       |   27 +-
 src/commands.h                                     |    2 +-
 src/comp.c                                         |   46 +-
 src/comp.h                                         |    2 +-
 src/composite.c                                    |   45 +-
 src/composite.h                                    |   72 +-
 src/conf_post.h                                    |   10 +-
 src/cygw32.c                                       |    2 +-
 src/cygw32.h                                       |    2 +-
 src/data.c                                         |    2 +-
 src/dbusbind.c                                     |    2 +-
 src/decompress.c                                   |    2 +-
 src/deps.mk                                        |    2 +-
 src/dired.c                                        |    2 +-
 src/dispextern.h                                   |   71 +-
 src/dispnew.c                                      |    8 +-
 src/disptab.h                                      |   10 +-
 src/dmpstruct.awk                                  |    2 +-
 src/doc.c                                          |   60 +-
 src/doprnt.c                                       |    2 +-
 src/dosfns.c                                       |    7 +-
 src/dosfns.h                                       |    2 +-
 src/dynlib.c                                       |    2 +-
 src/dynlib.h                                       |    2 +-
 src/editfns.c                                      |   10 +-
 src/emacs-icon.h                                   |    2 +-
 src/emacs-module.c                                 |   22 +-
 src/emacs-module.h.in                              |    2 +-
 src/emacs.c                                        |   28 +-
 src/emacsgtkfixed.c                                |    2 +-
 src/emacsgtkfixed.h                                |    6 +-
 src/epaths.in                                      |    2 +-
 src/eval.c                                         |  456 ++-
 src/fileio.c                                       |    4 +-
 src/filelock.c                                     |    4 +-
 src/firstfile.c                                    |    2 +-
 src/floatfns.c                                     |    2 +-
 src/fns.c                                          |  956 +++---
 src/font.c                                         |    2 +-
 src/font.h                                         |   28 +-
 src/fontset.c                                      |   14 +-
 src/fontset.h                                      |    2 +-
 src/frame.c                                        |    9 +-
 src/frame.h                                        |   12 +-
 src/fringe.c                                       |    2 +-
 src/ftcrfont.c                                     |    2 +-
 src/ftfont.c                                       |    8 +-
 src/getpagesize.h                                  |    2 +-
 src/gfilenotify.c                                  |    2 +-
 src/gmalloc.c                                      |    2 +-
 src/gnutls.c                                       |    2 +-
 src/gnutls.h                                       |    2 +-
 src/gtkutil.c                                      |    6 +-
 src/gtkutil.h                                      |    2 +-
 src/haiku.c                                        |    2 +-
 src/haiku_draw_support.cc                          |    2 +-
 src/haiku_font_support.cc                          |    2 +-
 src/haiku_io.c                                     |    2 +-
 src/haiku_select.cc                                |    6 +-
 src/haiku_support.cc                               |    2 +-
 src/haiku_support.h                                |    2 +-
 src/haikufns.c                                     |    2 +-
 src/haikufont.c                                    |    2 +-
 src/haikugui.h                                     |    2 +-
 src/haikuimage.c                                   |    2 +-
 src/haikumenu.c                                    |    2 +-
 src/haikuselect.c                                  |    4 +-
 src/haikuselect.h                                  |    2 +-
 src/haikuterm.c                                    |    2 +-
 src/haikuterm.h                                    |    2 +-
 src/hbfont.c                                       |    2 +-
 src/image.c                                        |   67 +-
 src/indent.c                                       |    2 +-
 src/indent.h                                       |    2 +-
 src/inotify.c                                      |    2 +-
 src/insdel.c                                       |   15 +-
 src/intervals.c                                    |    4 +-
 src/intervals.h                                    |    6 +-
 src/itree.c                                        |    4 +-
 src/itree.h                                        |    2 +-
 src/json.c                                         |   55 +-
 src/keyboard.c                                     |   28 +-
 src/keyboard.h                                     |   28 +-
 src/keymap.c                                       |    4 +-
 src/keymap.h                                       |    2 +-
 src/kqueue.c                                       |    2 +-
 src/lastfile.c                                     |    2 +-
 src/lcms.c                                         |    2 +-
 src/lisp.h                                         |  512 ++--
 src/lread.c                                        |  135 +-
 src/macfont.h                                      |    6 +-
 src/macfont.m                                      |  107 +-
 src/macros.c                                       |    2 +-
 src/macros.h                                       |    2 +-
 src/marker.c                                       |    7 +-
 src/menu.c                                         |    2 +-
 src/menu.h                                         |    2 +-
 src/minibuf.c                                      |   33 +-
 src/msdos.c                                        |   16 +-
 src/msdos.h                                        |    2 +-
 src/nsfns.m                                        |    2 +-
 src/nsfont.m                                       |    6 +-
 src/nsgui.h                                        |    2 +-
 src/nsimage.m                                      |    2 +-
 src/nsmenu.m                                       |    2 +-
 src/nsselect.m                                     |    2 +-
 src/nsterm.h                                       |    9 +-
 src/nsterm.m                                       |   23 +-
 src/nsxwidget.h                                    |    2 +-
 src/nsxwidget.m                                    |    2 +-
 src/pdumper.c                                      |  231 +-
 src/pdumper.h                                      |    4 +-
 src/pgtkfns.c                                      |    2 +-
 src/pgtkgui.h                                      |    2 +-
 src/pgtkim.c                                       |    2 +-
 src/pgtkmenu.c                                     |    2 +-
 src/pgtkselect.c                                   |    2 +-
 src/pgtkterm.c                                     |   11 +-
 src/pgtkterm.h                                     |    4 +-
 src/print.c                                        |  124 +-
 src/process.c                                      |    4 +-
 src/process.h                                      |    2 +-
 src/profiler.c                                     |  487 +--
 src/puresize.h                                     |    2 +-
 src/ralloc.c                                       |    2 +-
 src/regex-emacs.c                                  |   34 +-
 src/regex-emacs.h                                  |    2 +-
 src/region-cache.c                                 |    2 +-
 src/region-cache.h                                 |    2 +-
 src/scroll.c                                       |    2 +-
 src/search.c                                       |   12 +-
 src/sfnt.c                                         | 3092 ++++++++++++++------
 src/sfnt.h                                         |   20 +-
 src/sfntfont-android.c                             |    6 +-
 src/sfntfont.c                                     |  191 +-
 src/sfntfont.h                                     |    2 +-
 src/sheap.c                                        |    2 +-
 src/sheap.h                                        |    2 +-
 src/sort.c                                         |    5 +-
 src/sound.c                                        |    2 +-
 src/sqlite.c                                       |    2 +-
 src/syntax.c                                       |    4 +-
 src/syntax.h                                       |    2 +-
 src/sysdep.c                                       |    3 +-
 src/sysselect.h                                    |    2 +-
 src/syssignal.h                                    |    2 +-
 src/sysstdio.h                                     |    2 +-
 src/systhread.c                                    |    2 +-
 src/systhread.h                                    |    2 +-
 src/systime.h                                      |    2 +-
 src/systty.h                                       |    2 +-
 src/syswait.h                                      |    2 +-
 src/term.c                                         |   36 +-
 src/termcap.c                                      |    2 +-
 src/termchar.h                                     |    2 +-
 src/termhooks.h                                    |    2 +-
 src/terminal.c                                     |    4 +-
 src/terminfo.c                                     |    2 +-
 src/termopts.h                                     |    2 +-
 src/textconv.c                                     |   36 +-
 src/textconv.h                                     |    2 +-
 src/textprop.c                                     |    2 +-
 src/thread.c                                       |    2 +-
 src/thread.h                                       |    2 +-
 src/timefns.c                                      |    2 +-
 src/tparam.c                                       |    4 +-
 src/tparam.h                                       |    2 +-
 src/treesit.c                                      |   29 +-
 src/treesit.h                                      |    6 +-
 src/undo.c                                         |    2 +-
 src/unexaix.c                                      |    2 +-
 src/unexcoff.c                                     |    2 +-
 src/unexcw.c                                       |    2 +-
 src/unexelf.c                                      |    2 +-
 src/unexmacosx.c                                   |    2 +-
 src/unexw32.c                                      |    2 +-
 src/verbose.mk.in                                  |    2 +-
 src/vm-limit.c                                     |    2 +-
 src/w16select.c                                    |    4 +-
 src/w32.c                                          |    4 +-
 src/w32.h                                          |    2 +-
 src/w32common.h                                    |    2 +-
 src/w32console.c                                   |    6 +-
 src/w32cygwinx.c                                   |    2 +-
 src/w32fns.c                                       |   38 +-
 src/w32font.c                                      |    6 +-
 src/w32font.h                                      |    2 +-
 src/w32gui.h                                       |    2 +-
 src/w32heap.c                                      |    2 +-
 src/w32heap.h                                      |    2 +-
 src/w32image.c                                     |    2 +-
 src/w32inevt.c                                     |    2 +-
 src/w32inevt.h                                     |    2 +-
 src/w32menu.c                                      |    2 +-
 src/w32notify.c                                    |    8 +-
 src/w32proc.c                                      |    2 +-
 src/w32reg.c                                       |    2 +-
 src/w32select.c                                    |    2 +-
 src/w32select.h                                    |    2 +-
 src/w32term.c                                      |    9 +-
 src/w32term.h                                      |    2 +-
 src/w32uniscribe.c                                 |    5 +-
 src/w32xfns.c                                      |    2 +-
 src/widget.c                                       |    2 +-
 src/widget.h                                       |    2 +-
 src/widgetprv.h                                    |    2 +-
 src/window.c                                       |   24 +-
 src/window.h                                       |   26 +-
 src/xdisp.c                                        |  438 +--
 src/xfaces.c                                       |   55 +-
 src/xfns.c                                         |    2 +-
 src/xfont.c                                        |    4 +-
 src/xftfont.c                                      |    2 +-
 src/xgselect.c                                     |    2 +-
 src/xgselect.h                                     |    2 +-
 src/xmenu.c                                        |    2 +-
 src/xml.c                                          |    2 +-
 src/xrdb.c                                         |    2 +-
 src/xselect.c                                      |   10 +-
 src/xsettings.c                                    |    2 +-
 src/xsettings.h                                    |    2 +-
 src/xsmfns.c                                       |    2 +-
 src/xterm.c                                        |   63 +-
 src/xterm.h                                        |    8 +-
 src/xwidget.c                                      |    2 +-
 src/xwidget.h                                      |    2 +-
 test/ChangeLog.1                                   |    2 +-
 test/Makefile.in                                   |    2 +-
 test/README                                        |    2 +-
 test/infra/Dockerfile.emba                         |    2 +-
 test/infra/Makefile.in                             |    2 +-
 test/infra/gitlab-ci.yml                           |    2 +-
 test/lib-src/emacsclient-tests.el                  |    2 +-
 test/lisp/abbrev-tests.el                          |    2 +-
 test/lisp/align-tests.el                           |    2 +-
 test/lisp/allout-tests.el                          |    2 +-
 test/lisp/allout-widgets-tests.el                  |    2 +-
 test/lisp/ansi-color-tests.el                      |    2 +-
 test/lisp/ansi-osc-tests.el                        |    2 +-
 test/lisp/apropos-tests.el                         |    2 +-
 test/lisp/arc-mode-tests.el                        |    2 +-
 test/lisp/auth-source-pass-tests.el                |    2 +-
 test/lisp/auth-source-tests.el                     |   36 +-
 test/lisp/autoinsert-tests.el                      |    2 +-
 test/lisp/autorevert-tests.el                      |    2 +-
 test/lisp/battery-tests.el                         |    2 +-
 test/lisp/bookmark-tests.el                        |    2 +-
 test/lisp/buff-menu-tests.el                       |    2 +-
 test/lisp/button-tests.el                          |    2 +-
 test/lisp/calc/calc-tests.el                       |   65 +-
 test/lisp/calculator-tests.el                      |    2 +-
 test/lisp/calendar/cal-french-tests.el             |    2 +-
 test/lisp/calendar/cal-julian-tests.el             |    2 +-
 test/lisp/calendar/icalendar-tests.el              |    2 +-
 test/lisp/calendar/iso8601-tests.el                |    2 +-
 test/lisp/calendar/lunar-tests.el                  |    2 +-
 test/lisp/calendar/parse-time-tests.el             |    2 +-
 test/lisp/calendar/solar-tests.el                  |    2 +-
 test/lisp/calendar/time-date-tests.el              |    2 +-
 test/lisp/calendar/todo-mode-tests.el              |    2 +-
 test/lisp/cedet/cedet-files-tests.el               |    2 +-
 test/lisp/cedet/semantic-utest-c.el                |    2 +-
 .../cedet/semantic-utest-ia-resources/test.srt     |    2 +-
 .../semantic-utest-ia-resources/testdoublens.cpp   |    2 +-
 .../semantic-utest-ia-resources/testdoublens.hpp   |    2 +-
 .../semantic-utest-ia-resources/testjavacomp.java  |    2 +-
 .../semantic-utest-ia-resources/testlocalvars.cpp  |    2 +-
 .../cedet/semantic-utest-ia-resources/testnsp.cpp  |    2 +-
 .../semantic-utest-ia-resources/testsppcomplete.c  |    2 +-
 .../semantic-utest-ia-resources/teststruct.cpp     |    2 +-
 .../semantic-utest-ia-resources/testsubclass.cpp   |    2 +-
 .../semantic-utest-ia-resources/testsubclass.hh    |    2 +-
 .../semantic-utest-ia-resources/testtemplates.cpp  |    2 +-
 .../semantic-utest-ia-resources/testtypedefs.cpp   |    2 +-
 .../semantic-utest-ia-resources/testusing.cpp      |    2 +-
 .../cedet/semantic-utest-ia-resources/testusing.hh |    2 +-
 .../semantic-utest-ia-resources/testvarnames.c     |    2 +-
 .../semantic-utest-ia-resources/testvarnames.java  |    2 +-
 .../semantic-utest-ia-resources/testwisent.wy      |    2 +-
 test/lisp/cedet/semantic-utest-ia.el               |    2 +-
 test/lisp/cedet/semantic-utest.el                  |    2 +-
 test/lisp/cedet/semantic/bovine/gcc-tests.el       |    2 +-
 .../cedet/semantic/format-resources/test-fmt.cpp   |    2 +-
 .../cedet/semantic/format-resources/test-fmt.el    |    2 +-
 test/lisp/cedet/semantic/format-tests.el           |    2 +-
 test/lisp/cedet/semantic/fw-tests.el               |    2 +-
 test/lisp/cedet/srecode-utest-getset.el            |    2 +-
 test/lisp/cedet/srecode-utest-template.el          |    2 +-
 test/lisp/cedet/srecode/document-tests.el          |    2 +-
 test/lisp/cedet/srecode/fields-tests.el            |    2 +-
 test/lisp/char-fold-tests.el                       |    2 +-
 test/lisp/color-tests.el                           |    2 +-
 test/lisp/comint-tests.el                          |    2 +-
 test/lisp/completion-preview-tests.el              |    2 +-
 test/lisp/completion-tests.el                      |    2 +-
 test/lisp/cus-edit-tests.el                        |    2 +-
 test/lisp/custom-tests.el                          |    2 +-
 test/lisp/dabbrev-tests.el                         |    2 +-
 test/lisp/delim-col-tests.el                       |    2 +-
 test/lisp/descr-text-tests.el                      |    2 +-
 test/lisp/desktop-tests.el                         |    2 +-
 test/lisp/dired-aux-tests.el                       |    2 +-
 test/lisp/dired-tests.el                           |    6 +-
 test/lisp/dired-x-tests.el                         |    2 +-
 test/lisp/dnd-tests.el                             |    2 +-
 test/lisp/dom-tests.el                             |   12 +-
 test/lisp/edmacro-tests.el                         |    2 +-
 test/lisp/electric-tests.el                        |    2 +-
 test/lisp/elide-head-tests.el                      |    2 +-
 test/lisp/emacs-lisp/backquote-tests.el            |    2 +-
 test/lisp/emacs-lisp/backtrace-tests.el            |    2 +-
 test/lisp/emacs-lisp/benchmark-tests.el            |    2 +-
 test/lisp/emacs-lisp/bindat-tests.el               |    2 +-
 test/lisp/emacs-lisp/byte-run-tests.el             |    2 +-
 test/lisp/emacs-lisp/bytecomp-tests.el             |   28 +-
 test/lisp/emacs-lisp/cconv-tests.el                |    2 +-
 test/lisp/emacs-lisp/check-declare-tests.el        |    2 +-
 test/lisp/emacs-lisp/checkdoc-tests.el             |   11 +-
 test/lisp/emacs-lisp/cl-extra-tests.el             |    2 +-
 test/lisp/emacs-lisp/cl-generic-tests.el           |    2 +-
 test/lisp/emacs-lisp/cl-lib-tests.el               |    2 +-
 test/lisp/emacs-lisp/cl-macs-tests.el              |    2 +-
 test/lisp/emacs-lisp/cl-preloaded-tests.el         |    2 +-
 test/lisp/emacs-lisp/cl-print-tests.el             |    2 +-
 test/lisp/emacs-lisp/cl-seq-tests.el               |    2 +-
 test/lisp/emacs-lisp/comp-cstr-tests.el            |  414 ++-
 test/lisp/emacs-lisp/comp-tests.el                 |    2 +-
 test/lisp/emacs-lisp/copyright-tests.el            |    2 +-
 test/lisp/emacs-lisp/derived-tests.el              |    2 +-
 test/lisp/emacs-lisp/easy-mmode-tests.el           |    2 +-
 .../edebug-resources/edebug-test-code.el           |    2 +-
 test/lisp/emacs-lisp/edebug-tests.el               |    2 +-
 .../eieio-tests/eieio-test-methodinvoke.el         |    2 +-
 .../emacs-lisp/eieio-tests/eieio-test-persist.el   |    2 +-
 test/lisp/emacs-lisp/eieio-tests/eieio-tests.el    |    2 +-
 test/lisp/emacs-lisp/ert-font-lock-tests.el        |    2 +-
 test/lisp/emacs-lisp/ert-tests.el                  |   41 +-
 test/lisp/emacs-lisp/ert-x-tests.el                |    2 +-
 .../faceup-resources/faceup-test-mode.el           |    2 +-
 .../faceup-test-this-file-directory.el             |    2 +-
 .../emacs-lisp/faceup-tests/faceup-test-basics.el  |    2 +-
 .../emacs-lisp/faceup-tests/faceup-test-files.el   |    2 +-
 test/lisp/emacs-lisp/find-func-tests.el            |    2 +-
 test/lisp/emacs-lisp/float-sup-tests.el            |    2 +-
 test/lisp/emacs-lisp/generator-tests.el            |    2 +-
 test/lisp/emacs-lisp/gv-tests.el                   |    2 +-
 test/lisp/emacs-lisp/hierarchy-tests.el            |    5 +-
 test/lisp/emacs-lisp/icons-tests.el                |    2 +-
 test/lisp/emacs-lisp/let-alist-tests.el            |    2 +-
 test/lisp/emacs-lisp/lisp-mnt-tests.el             |   22 +-
 test/lisp/emacs-lisp/lisp-mode-tests.el            |    2 +-
 test/lisp/emacs-lisp/lisp-tests.el                 |    2 +-
 test/lisp/emacs-lisp/macroexp-resources/m1.el      |    2 +-
 test/lisp/emacs-lisp/macroexp-resources/m2.el      |    2 +-
 test/lisp/emacs-lisp/macroexp-resources/vk.el      |    2 +-
 test/lisp/emacs-lisp/macroexp-tests.el             |    2 +-
 test/lisp/emacs-lisp/map-tests.el                  |    2 +-
 test/lisp/emacs-lisp/memory-report-tests.el        |    2 +-
 test/lisp/emacs-lisp/multisession-tests.el         |    2 +-
 test/lisp/emacs-lisp/nadvice-tests.el              |    2 +-
 test/lisp/emacs-lisp/oclosure-tests.el             |    2 +-
 .../package-resources/signed/update-signatures.sh  |    2 +-
 test/lisp/emacs-lisp/package-tests.el              |    2 +-
 test/lisp/emacs-lisp/pcase-tests.el                |    2 +-
 test/lisp/emacs-lisp/pp-tests.el                   |    2 +-
 test/lisp/emacs-lisp/range-tests.el                |    2 +-
 test/lisp/emacs-lisp/regexp-opt-tests.el           |    2 +-
 test/lisp/emacs-lisp/ring-tests.el                 |    2 +-
 test/lisp/emacs-lisp/rmc-tests.el                  |    2 +-
 test/lisp/emacs-lisp/rx-tests.el                   |    2 +-
 test/lisp/emacs-lisp/seq-tests.el                  |    2 +-
 test/lisp/emacs-lisp/shadow-tests.el               |    2 +-
 test/lisp/emacs-lisp/shortdoc-tests.el             |    2 +-
 test/lisp/emacs-lisp/subr-x-tests.el               |    2 +-
 test/lisp/emacs-lisp/syntax-tests.el               |    2 +-
 test/lisp/emacs-lisp/tabulated-list-tests.el       |    2 +-
 .../emacs-lisp/testcover-resources/testcases.el    |    2 +-
 test/lisp/emacs-lisp/testcover-tests.el            |    2 +-
 test/lisp/emacs-lisp/text-property-search-tests.el |    2 +-
 test/lisp/emacs-lisp/thunk-tests.el                |    2 +-
 test/lisp/emacs-lisp/timer-tests.el                |    2 +-
 test/lisp/emacs-lisp/unsafep-tests.el              |    2 +-
 test/lisp/emacs-lisp/vtable-tests.el               |    2 +-
 test/lisp/emacs-lisp/warnings-tests.el             |    2 +-
 test/lisp/emulation/viper-tests.el                 |    2 +-
 test/lisp/env-tests.el                             |    2 +-
 test/lisp/epg-config-tests.el                      |    2 +-
 test/lisp/epg-tests.el                             |    2 +-
 test/lisp/erc/erc-button-tests.el                  |   27 +-
 test/lisp/erc/erc-dcc-tests.el                     |    2 +-
 test/lisp/erc/erc-fill-tests.el                    |  122 +-
 test/lisp/erc/erc-goodies-tests.el                 |   41 +-
 test/lisp/erc/erc-join-tests.el                    |    2 +-
 test/lisp/erc/erc-match-tests.el                   |    2 +-
 test/lisp/erc/erc-networks-tests.el                |   68 +-
 test/lisp/erc/erc-nicks-tests.el                   |    4 +-
 test/lisp/erc/erc-sasl-tests.el                    |    2 +-
 test/lisp/erc/erc-scenarios-auth-source.el         |    2 +-
 .../erc/erc-scenarios-base-association-nick.el     |    2 +-
 .../erc/erc-scenarios-base-association-query.el    |    2 +-
 .../erc/erc-scenarios-base-association-samenet.el  |    2 +-
 test/lisp/erc/erc-scenarios-base-association.el    |    2 +-
 test/lisp/erc/erc-scenarios-base-attach.el         |    6 +-
 test/lisp/erc/erc-scenarios-base-auto-recon.el     |    2 +-
 test/lisp/erc/erc-scenarios-base-buffer-display.el |    2 +-
 test/lisp/erc/erc-scenarios-base-chan-modes.el     |   60 +-
 .../erc-scenarios-base-compat-rename-bouncer.el    |    2 +-
 .../erc/erc-scenarios-base-local-module-modes.el   |    2 +-
 test/lisp/erc/erc-scenarios-base-local-modules.el  |    2 +-
 .../erc/erc-scenarios-base-misc-regressions.el     |    2 +-
 .../erc/erc-scenarios-base-netid-bouncer-id.el     |    2 +-
 .../erc-scenarios-base-netid-bouncer-recon-base.el |    2 +-
 .../erc-scenarios-base-netid-bouncer-recon-both.el |    2 +-
 .../erc-scenarios-base-netid-bouncer-recon-id.el   |    2 +-
 test/lisp/erc/erc-scenarios-base-netid-bouncer.el  |    2 +-
 test/lisp/erc/erc-scenarios-base-netid-samenet.el  |    2 +-
 test/lisp/erc/erc-scenarios-base-reconnect.el      |    4 +-
 test/lisp/erc/erc-scenarios-base-renick.el         |    4 +-
 test/lisp/erc/erc-scenarios-base-reuse-buffers.el  |    2 +-
 test/lisp/erc/erc-scenarios-base-send-message.el   |    2 +-
 test/lisp/erc/erc-scenarios-base-split-line.el     |    2 +-
 test/lisp/erc/erc-scenarios-base-statusmsg.el      |  103 +
 test/lisp/erc/erc-scenarios-base-unstable.el       |    2 +-
 .../erc/erc-scenarios-base-upstream-recon-soju.el  |    2 +-
 .../erc/erc-scenarios-base-upstream-recon-znc.el   |   48 +-
 test/lisp/erc/erc-scenarios-display-message.el     |    6 +-
 test/lisp/erc/erc-scenarios-internal.el            |   37 +-
 test/lisp/erc/erc-scenarios-join-auth-source.el    |    2 +-
 .../lisp/erc/erc-scenarios-join-display-context.el |    2 +-
 .../lisp/erc/erc-scenarios-join-netid-newcmd-id.el |    2 +-
 test/lisp/erc/erc-scenarios-join-netid-newcmd.el   |    2 +-
 test/lisp/erc/erc-scenarios-join-netid-recon-id.el |    2 +-
 test/lisp/erc/erc-scenarios-join-netid-recon.el    |    2 +-
 .../lisp/erc/erc-scenarios-keep-place-indicator.el |  141 +
 test/lisp/erc/erc-scenarios-log.el                 |   57 +-
 test/lisp/erc/erc-scenarios-match.el               |   18 +-
 test/lisp/erc/erc-scenarios-misc-commands.el       |   34 +-
 test/lisp/erc/erc-scenarios-misc.el                |    4 +-
 test/lisp/erc/erc-scenarios-prompt-format.el       |    2 +-
 test/lisp/erc/erc-scenarios-sasl.el                |   37 +-
 .../erc/erc-scenarios-scrolltobottom-relaxed.el    |    5 +-
 test/lisp/erc/erc-scenarios-scrolltobottom.el      |    8 +-
 test/lisp/erc/erc-scenarios-services-misc.el       |    2 +-
 test/lisp/erc/erc-scenarios-stamp.el               |   22 +-
 test/lisp/erc/erc-scenarios-status-sidebar.el      |    8 +-
 test/lisp/erc/erc-services-tests.el                |    2 +-
 test/lisp/erc/erc-stamp-tests.el                   |   60 +-
 test/lisp/erc/erc-tests.el                         | 1017 +++++--
 test/lisp/erc/erc-track-tests.el                   |  168 +-
 .../resources/base/display-message/statusmsg.eld   |   47 +
 .../erc/resources/base/local-modules/first.eld     |    6 +-
 .../erc/resources/base/modes/speaker-status.eld    |   69 +
 .../base/upstream-reconnect/znc-severed.eld        |   87 +
 test/lisp/erc/resources/commands/vhost.eld         |   40 +
 test/lisp/erc/resources/erc-d/erc-d-i.el           |    2 +-
 test/lisp/erc/resources/erc-d/erc-d-t.el           |    2 +-
 test/lisp/erc/resources/erc-d/erc-d-tests.el       |    2 +-
 test/lisp/erc/resources/erc-d/erc-d-u.el           |    2 +-
 test/lisp/erc/resources/erc-d/erc-d.el             |    2 +-
 test/lisp/erc/resources/erc-d/resources/basic.eld  |    5 +-
 .../resources/erc-d/resources/dynamic-barnet.eld   |    2 +-
 .../resources/erc-d/resources/dynamic-foonet.eld   |    2 +-
 .../lisp/erc/resources/erc-d/resources/dynamic.eld |    5 +-
 test/lisp/erc/resources/erc-d/resources/eof.eld    |    5 +-
 test/lisp/erc/resources/erc-d/resources/fuzzy.eld  |    4 +-
 .../erc/resources/erc-d/resources/incremental.eld  |    5 +-
 test/lisp/erc/resources/erc-d/resources/linger.eld |    5 +-
 .../erc/resources/erc-d/resources/no-block.eld     |    7 +-
 .../erc/resources/erc-d/resources/no-match.eld     |    5 +-
 .../resources/erc-d/resources/proxy-subprocess.el  |    2 +-
 .../erc/resources/erc-d/resources/unexpected.eld   |    5 +-
 test/lisp/erc/resources/erc-scenarios-common.el    |   51 +-
 test/lisp/erc/resources/erc-tests-common.el        |  301 ++
 .../resources/fill/snapshots/merge-01-start.eld    |    2 +-
 .../resources/fill/snapshots/merge-02-right.eld    |    2 +-
 .../erc/resources/fill/snapshots/merge-wrap-01.eld |    2 +-
 .../snapshots/merge-wrap-indicator-post-01.eld     |    2 +-
 .../fill/snapshots/merge-wrap-indicator-pre-01.eld |    2 +-
 .../fill/snapshots/monospace-01-start.eld          |    2 +-
 .../fill/snapshots/monospace-02-right.eld          |    2 +-
 .../resources/fill/snapshots/monospace-03-left.eld |    2 +-
 .../fill/snapshots/monospace-04-reset.eld          |    2 +-
 .../resources/fill/snapshots/spacing-01-mono.eld   |    2 +-
 .../resources/fill/snapshots/stamps-left-01.eld    |    2 +-
 test/lisp/erc/resources/join/network-id/barnet.eld |    2 +-
 .../erc/resources/join/network-id/foonet-again.eld |    2 +-
 test/lisp/erc/resources/keep-place/follow.eld      |   78 +
 test/lisp/erc/resources/sasl/plain-failed.eld      |   10 +-
 test/lisp/eshell/em-alias-tests.el                 |    2 +-
 test/lisp/eshell/em-basic-tests.el                 |   36 +-
 test/lisp/eshell/em-cmpl-tests.el                  |   14 +-
 test/lisp/eshell/em-dirs-tests.el                  |   24 +-
 test/lisp/eshell/em-extpipe-tests.el               |    2 +-
 test/lisp/eshell/em-glob-tests.el                  |    2 +-
 test/lisp/eshell/em-hist-tests.el                  |    4 +-
 test/lisp/eshell/em-ls-tests.el                    |    2 +-
 test/lisp/eshell/em-pred-tests.el                  |    2 +-
 test/lisp/eshell/em-prompt-tests.el                |    2 +-
 test/lisp/eshell/em-script-tests.el                |    2 +-
 test/lisp/eshell/em-tramp-tests.el                 |   91 +-
 test/lisp/eshell/em-unix-tests.el                  |    2 +-
 test/lisp/eshell/esh-arg-tests.el                  |   16 +-
 test/lisp/eshell/esh-cmd-tests.el                  |   24 +-
 test/lisp/eshell/esh-ext-tests.el                  |    2 +-
 test/lisp/eshell/esh-io-tests.el                   |    4 +-
 test/lisp/eshell/esh-opt-tests.el                  |    2 +-
 test/lisp/eshell/esh-proc-tests.el                 |    2 +-
 test/lisp/eshell/esh-util-tests.el                 |    2 +-
 test/lisp/eshell/esh-var-tests.el                  |   17 +-
 test/lisp/eshell/eshell-tests-helpers.el           |    2 +-
 test/lisp/eshell/eshell-tests-unload.el            |    2 +-
 test/lisp/eshell/eshell-tests.el                   |    2 +-
 test/lisp/faces-resources/faces-test-dark-theme.el |    2 +-
 .../lisp/faces-resources/faces-test-light-theme.el |    2 +-
 test/lisp/faces-tests.el                           |    2 +-
 test/lisp/ffap-tests.el                            |    2 +-
 test/lisp/filenotify-tests.el                      |    2 +-
 test/lisp/files-tests.el                           |    6 +-
 test/lisp/files-x-tests.el                         |  121 +-
 test/lisp/find-cmd-tests.el                        |    2 +-
 test/lisp/font-lock-tests.el                       |    2 +-
 test/lisp/format-spec-tests.el                     |    2 +-
 test/lisp/gnus/gnus-group-tests.el                 |    2 +-
 test/lisp/gnus/gnus-icalendar-tests.el             |    2 +-
 test/lisp/gnus/gnus-search-tests.el                |    2 +-
 test/lisp/gnus/gnus-test-headers.el                |    2 +-
 test/lisp/gnus/gnus-tests.el                       |    2 +-
 test/lisp/gnus/gnus-util-tests.el                  |    2 +-
 test/lisp/gnus/message-tests.el                    |    2 +-
 test/lisp/gnus/mm-decode-tests.el                  |    2 +-
 test/lisp/gnus/mml-sec-tests.el                    |    2 +-
 test/lisp/gnus/nnrss-tests.el                      |    2 +-
 test/lisp/help-fns-tests.el                        |    2 +-
 test/lisp/help-mode-tests.el                       |    2 +-
 test/lisp/help-tests.el                            |    2 +-
 test/lisp/hfy-cmap-tests.el                        |    2 +-
 test/lisp/hi-lock-tests.el                         |    2 +-
 test/lisp/hl-line-tests.el                         |    2 +-
 test/lisp/htmlfontify-tests.el                     |    2 +-
 test/lisp/ibuffer-tests.el                         |    2 +-
 test/lisp/ido-tests.el                             |    2 +-
 test/lisp/image-file-tests.el                      |    2 +-
 test/lisp/image-tests.el                           |    2 +-
 test/lisp/image/exif-tests.el                      |    2 +-
 test/lisp/image/gravatar-tests.el                  |    2 +-
 test/lisp/image/image-dired-tests.el               |    2 +-
 test/lisp/image/image-dired-util-tests.el          |    2 +-
 test/lisp/image/wallpaper-tests.el                 |    2 +-
 test/lisp/imenu-tests.el                           |    2 +-
 test/lisp/info-tests.el                            |   16 +-
 test/lisp/info-xref-tests.el                       |   12 +-
 test/lisp/international/ccl-tests.el               |    2 +-
 test/lisp/international/mule-tests.el              |    4 +-
 test/lisp/international/mule-util-tests.el         |    2 +-
 test/lisp/international/textsec-tests.el           |    2 +-
 test/lisp/international/ucs-normalize-tests.el     |    2 +-
 test/lisp/isearch-tests.el                         |    2 +-
 test/lisp/jit-lock-tests.el                        |    2 +-
 test/lisp/json-tests.el                            |    2 +-
 test/lisp/jsonrpc-tests.el                         |   11 +-
 test/lisp/kmacro-tests.el                          |    2 +-
 test/lisp/loadhist-resources/loadhist--bar.el      |    2 +-
 test/lisp/loadhist-resources/loadhist--foo.el      |    2 +-
 test/lisp/loadhist-tests.el                        |    2 +-
 test/lisp/lpr-tests.el                             |    2 +-
 test/lisp/ls-lisp-tests.el                         |    9 +-
 test/lisp/mail/flow-fill-tests.el                  |    2 +-
 test/lisp/mail/footnote-tests.el                   |    2 +-
 test/lisp/mail/ietf-drums-date-tests.el            |    2 +-
 test/lisp/mail/ietf-drums-tests.el                 |    2 +-
 test/lisp/mail/mail-extr-tests.el                  |    2 +-
 test/lisp/mail/mail-parse-tests.el                 |    2 +-
 test/lisp/mail/mail-utils-tests.el                 |    2 +-
 test/lisp/mail/qp-tests.el                         |    2 +-
 test/lisp/mail/rfc2045-tests.el                    |    2 +-
 test/lisp/mail/rfc2047-tests.el                    |    2 +-
 test/lisp/mail/rfc6068-tests.el                    |    2 +-
 test/lisp/mail/rfc822-tests.el                     |    2 +-
 test/lisp/mail/rmail-tests.el                      |    2 +-
 test/lisp/mail/rmailmm-tests.el                    |    2 +-
 test/lisp/mail/undigest-tests.el                   |    2 +-
 test/lisp/mail/uudecode-tests.el                   |    2 +-
 test/lisp/man-tests.el                             |   20 +-
 test/lisp/md4-tests.el                             |    2 +-
 test/lisp/mh-e/mh-limit-tests.el                   |    2 +-
 test/lisp/mh-e/mh-thread-tests.el                  |    2 +-
 test/lisp/mh-e/mh-utils-tests.el                   |    2 +-
 test/lisp/mh-e/mh-xface-tests.el                   |    2 +-
 test/lisp/mh-e/test-all-mh-variants.sh             |    2 +-
 test/lisp/minibuffer-tests.el                      |   90 +-
 test/lisp/misc-tests.el                            |    2 +-
 test/lisp/mouse-tests.el                           |    2 +-
 test/lisp/mwheel-tests.el                          |    2 +-
 test/lisp/net/browse-url-tests.el                  |    2 +-
 test/lisp/net/dbus-tests.el                        |    2 +-
 test/lisp/net/dig-tests.el                         |    2 +-
 test/lisp/net/eudc-tests.el                        |    2 +-
 test/lisp/net/gnutls-tests.el                      |    2 +-
 test/lisp/net/hmac-md5-tests.el                    |    2 +-
 test/lisp/net/mailcap-tests.el                     |    2 +-
 test/lisp/net/network-stream-tests.el              |    2 +-
 test/lisp/net/newsticker-tests.el                  |    2 +-
 test/lisp/net/nsm-tests.el                         |    2 +-
 test/lisp/net/ntlm-tests.el                        |    2 +-
 test/lisp/net/puny-tests.el                        |    2 +-
 test/lisp/net/rcirc-tests.el                       |    2 +-
 test/lisp/net/rfc2104-tests.el                     |    2 +-
 test/lisp/net/sasl-cram-tests.el                   |    2 +-
 test/lisp/net/sasl-scram-rfc-tests.el              |    2 +-
 test/lisp/net/sasl-tests.el                        |    2 +-
 test/lisp/net/secrets-tests.el                     |    2 +-
 test/lisp/net/shr-tests.el                         |    2 +-
 test/lisp/net/socks-tests.el                       |    2 +-
 test/lisp/net/tramp-archive-tests.el               |    2 +-
 test/lisp/net/tramp-tests.el                       |  116 +-
 test/lisp/net/webjump-tests.el                     |    2 +-
 test/lisp/newcomment-tests.el                      |    2 +-
 test/lisp/nxml/nxml-mode-tests.el                  |    2 +-
 test/lisp/nxml/xsd-regexp-tests.el                 |    2 +-
 test/lisp/obarray-tests.el                         |    2 +-
 test/lisp/obsolete/cl-tests.el                     |    2 +-
 test/lisp/obsolete/inversion-tests.el              |    2 +-
 test/lisp/obsolete/makesum-tests.el                |    2 +-
 test/lisp/obsolete/rfc2368-tests.el                |    2 +-
 test/lisp/obsolete/thumbs-tests.el                 |    2 +-
 test/lisp/org/org-tests.el                         |    2 +-
 test/lisp/paren-tests.el                           |    2 +-
 test/lisp/password-cache-tests.el                  |    2 +-
 test/lisp/pcmpl-linux-tests.el                     |    2 +-
 test/lisp/pcomplete-tests.el                       |    2 +-
 test/lisp/play/animate-tests.el                    |    2 +-
 test/lisp/play/cookie1-tests.el                    |    2 +-
 test/lisp/play/dissociate-tests.el                 |    2 +-
 test/lisp/play/fortune-tests.el                    |    2 +-
 test/lisp/play/life-tests.el                       |    2 +-
 test/lisp/play/morse-tests.el                      |    2 +-
 test/lisp/play/studly-tests.el                     |    2 +-
 test/lisp/proced-tests.el                          |    4 +-
 test/lisp/progmodes/asm-mode-tests.el              |    2 +-
 test/lisp/progmodes/autoconf-tests.el              |    2 +-
 test/lisp/progmodes/bat-mode-tests.el              |    2 +-
 test/lisp/progmodes/bug-reference-tests.el         |    2 +-
 .../progmodes/c-ts-mode-resources/indent-bsd.erts  |   34 +
 .../lisp/progmodes/c-ts-mode-resources/indent.erts |   50 +-
 test/lisp/progmodes/c-ts-mode-tests.el             |    2 +-
 test/lisp/progmodes/cc-mode-tests.el               |    2 +-
 test/lisp/progmodes/compile-tests.el               |   33 +-
 test/lisp/progmodes/cperl-mode-tests.el            |   18 +-
 test/lisp/progmodes/eglot-tests.el                 |   75 +-
 test/lisp/progmodes/elisp-mode-tests.el            |    2 +-
 .../progmodes/elixir-ts-mode-resources/indent.erts |    2 +-
 test/lisp/progmodes/elixir-ts-mode-tests.el        |    2 +-
 test/lisp/progmodes/etags-tests.el                 |    2 +-
 test/lisp/progmodes/executable-tests.el            |    2 +-
 test/lisp/progmodes/f90-tests.el                   |    2 +-
 test/lisp/progmodes/flymake-tests.el               |    2 +-
 test/lisp/progmodes/gdb-mi-tests.el                |    2 +-
 test/lisp/progmodes/glasses-tests.el               |    2 +-
 test/lisp/progmodes/go-ts-mode-tests.el            |    2 +-
 test/lisp/progmodes/grep-tests.el                  |    2 +-
 test/lisp/progmodes/heex-ts-mode-tests.el          |    2 +-
 test/lisp/progmodes/hideshow-tests.el              |    2 +-
 test/lisp/progmodes/java-ts-mode-tests.el          |    2 +-
 .../lisp/progmodes/js-resources/js-ts-indents.erts |   44 +
 test/lisp/progmodes/js-tests.el                    |    8 +-
 .../progmodes/lua-ts-mode-resources/font-lock.lua  |  339 +++
 .../progmodes/lua-ts-mode-resources/indent.erts    |  106 +
 test/lisp/progmodes/lua-ts-mode-tests.el           |   12 +-
 test/lisp/progmodes/octave-tests.el                |    2 +-
 test/lisp/progmodes/opascal-tests.el               |    2 +-
 test/lisp/progmodes/pascal-tests.el                |    2 +-
 test/lisp/progmodes/perl-mode-tests.el             |    4 +-
 test/lisp/progmodes/project-tests.el               |    2 +-
 test/lisp/progmodes/ps-mode-tests.el               |    2 +-
 test/lisp/progmodes/python-tests.el                |  389 ++-
 test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb |    4 +
 test/lisp/progmodes/ruby-mode-resources/ruby.rb    |    6 +-
 test/lisp/progmodes/ruby-mode-tests.el             |   14 +-
 test/lisp/progmodes/ruby-ts-mode-tests.el          |    2 +-
 test/lisp/progmodes/scheme-tests.el                |    2 +-
 test/lisp/progmodes/sh-script-tests.el             |    2 +-
 test/lisp/progmodes/sql-tests.el                   |    2 +-
 test/lisp/progmodes/subword-tests.el               |    2 +-
 test/lisp/progmodes/tcl-tests.el                   |    2 +-
 test/lisp/progmodes/typescript-ts-mode-tests.el    |    5 +-
 test/lisp/progmodes/which-func-tests.el            |    2 +-
 test/lisp/progmodes/xref-tests.el                  |    2 +-
 test/lisp/ps-print-tests.el                        |    2 +-
 .../lisp/{buff-menu-tests.el => register-tests.el} |   41 +-
 test/lisp/repeat-tests.el                          |    2 +-
 test/lisp/replace-tests.el                         |    2 +-
 test/lisp/rot13-tests.el                           |    2 +-
 test/lisp/saveplace-tests.el                       |    2 +-
 test/lisp/scroll-lock-tests.el                     |    2 +-
 test/lisp/server-tests.el                          |    2 +-
 test/lisp/ses-tests.el                             |   26 +-
 test/lisp/shadowfile-tests.el                      |    2 +-
 test/lisp/shell-tests.el                           |    2 +-
 test/lisp/simple-tests.el                          |    2 +-
 .../so-long-tests/autoload-longlines-mode-tests.el |    2 +-
 .../so-long-tests/autoload-major-mode-tests.el     |    2 +-
 .../so-long-tests/autoload-minor-mode-tests.el     |    2 +-
 test/lisp/so-long-tests/so-long-tests-helpers.el   |    2 +-
 test/lisp/so-long-tests/so-long-tests.el           |    2 +-
 test/lisp/so-long-tests/spelling-tests.el          |    2 +-
 test/lisp/sort-tests.el                            |    2 +-
 test/lisp/soundex-tests.el                         |    2 +-
 test/lisp/startup-tests.el                         |    2 +-
 test/lisp/subr-tests.el                            |    2 +-
 test/lisp/tab-bar-tests.el                         |    2 +-
 test/lisp/tabify-tests.el                          |    2 +-
 test/lisp/tar-mode-tests.el                        |    2 +-
 test/lisp/tempo-tests.el                           |    2 +-
 test/lisp/term-tests.el                            |    2 +-
 test/lisp/term/tty-colors-tests.el                 |    2 +-
 test/lisp/textmodes/bibtex-tests.el                |    2 +-
 test/lisp/textmodes/conf-mode-tests.el             |    2 +-
 test/lisp/textmodes/css-mode-tests.el              |    2 +-
 test/lisp/textmodes/dns-mode-tests.el              |    2 +-
 test/lisp/textmodes/emacs-news-mode-tests.el       |    2 +-
 test/lisp/textmodes/fill-tests.el                  |    4 +-
 test/lisp/textmodes/mhtml-mode-tests.el            |    2 +-
 test/lisp/textmodes/page-tests.el                  |    8 +-
 test/lisp/textmodes/paragraphs-tests.el            |    2 +-
 test/lisp/textmodes/po-tests.el                    |    2 +-
 test/lisp/textmodes/reftex-tests.el                |    2 +-
 test/lisp/textmodes/sgml-mode-tests.el             |    2 +-
 test/lisp/textmodes/texinfo-tests.el               |    2 +-
 test/lisp/textmodes/tildify-tests.el               |    4 +-
 test/lisp/textmodes/underline-tests.el             |    2 +-
 test/lisp/thingatpt-tests.el                       |    8 +-
 test/lisp/thread-tests.el                          |    2 +-
 test/lisp/time-stamp-tests.el                      |    2 +-
 test/lisp/time-tests.el                            |    2 +-
 test/lisp/timezone-tests.el                        |    2 +-
 test/lisp/uniquify-tests.el                        |    2 +-
 test/lisp/url/url-auth-tests.el                    |    2 +-
 test/lisp/url/url-domsuf-tests.el                  |    2 +-
 test/lisp/url/url-expand-tests.el                  |    3 +-
 test/lisp/url/url-file-tests.el                    |    2 +-
 test/lisp/url/url-future-tests.el                  |    2 +-
 test/lisp/url/url-handlers-tests.el                |    2 +-
 test/lisp/url/url-misc-tests.el                    |    2 +-
 test/lisp/url/url-parse-tests.el                   |    3 +-
 test/lisp/url/url-tramp-tests.el                   |    2 +-
 test/lisp/url/url-util-tests.el                    |    2 +-
 test/lisp/use-package/use-package-tests.el         |    2 +-
 test/lisp/vc/add-log-tests.el                      |    2 +-
 test/lisp/vc/diff-mode-tests.el                    |    2 +-
 test/lisp/vc/ediff-diff-tests.el                   |    2 +-
 test/lisp/vc/ediff-ptch-tests.el                   |    2 +-
 test/lisp/vc/log-edit-tests.el                     |  212 +-
 test/lisp/vc/smerge-mode-tests.el                  |    2 +-
 test/lisp/vc/vc-bzr-tests.el                       |    2 +-
 test/lisp/vc/vc-cvs-tests.el                       |    2 +-
 test/lisp/vc/vc-git-tests.el                       |    2 +-
 test/lisp/vc/vc-hg-tests.el                        |    6 +-
 test/lisp/vc/vc-tests.el                           |    2 +-
 test/lisp/version-tests.el                         |    2 +-
 test/lisp/wdired-tests.el                          |    2 +-
 test/lisp/whitespace-tests.el                      |    2 +-
 test/lisp/wid-edit-tests.el                        |    2 +-
 test/lisp/x-dnd-tests.el                           |    2 +-
 test/lisp/xdg-tests.el                             |    2 +-
 test/lisp/xml-tests.el                             |    2 +-
 test/lisp/xt-mouse-tests.el                        |    2 +-
 test/lisp/yank-media-tests.el                      |    2 +-
 test/manual/biditest.el                            |    2 +-
 test/manual/cedet/cedet-utests.el                  |    2 +-
 test/manual/cedet/ede-tests.el                     |    2 +-
 test/manual/cedet/semantic-tests.el                |    2 +-
 test/manual/cedet/tests/test.c                     |    2 +-
 test/manual/cedet/tests/test.el                    |    2 +-
 test/manual/cedet/tests/test.make                  |    2 +-
 test/manual/cedet/tests/testpolymorph.cpp          |    2 +-
 test/manual/cedet/tests/testspp.c                  |    2 +-
 test/manual/cedet/tests/testsppreplace.c           |    2 +-
 test/manual/cedet/tests/testsppreplaced.c          |    2 +-
 test/manual/etags/c-src/abbrev.c                   |    2 +-
 test/manual/etags/c-src/emacs/src/gmalloc.c        |    2 +-
 test/manual/etags/c-src/emacs/src/keyboard.c       |    2 +-
 test/manual/etags/c-src/emacs/src/lisp.h           |    2 +-
 test/manual/etags/c-src/emacs/src/regex.h          |    2 +-
 test/manual/etags/c-src/etags.c                    |    2 +-
 test/manual/etags/c-src/exit.c                     |    2 +-
 test/manual/etags/c-src/exit.strange_suffix        |    2 +-
 test/manual/etags/c-src/getopt.h                   |    2 +-
 test/manual/etags/c-src/sysdep.h                   |    2 +-
 .../etags/el-src/emacs/lisp/progmodes/etags.el     |    2 +-
 test/manual/etags/tex-src/texinfo.tex              |    2 +-
 test/manual/etags/y-src/cccp.c                     |    2 +-
 test/manual/etags/y-src/parse.c                    |    2 +-
 test/manual/etags/y-src/parse.y                    |    2 +-
 test/manual/image-circular-tests.el                |    2 +-
 test/manual/image-size-tests.el                    |    2 +-
 test/manual/image-tests.el                         |    2 +-
 test/manual/image-transforms-tests.el              |    2 +-
 test/manual/indent/pascal.pas                      |    2 +-
 test/manual/indent/shell.sh                        |    7 +
 test/manual/noverlay/Makefile.in                   |    2 +-
 test/manual/noverlay/check-sanitize.sh             |    2 +-
 test/manual/noverlay/emacs-compat.h                |    2 +-
 test/manual/noverlay/itree-tests.c                 |    2 +-
 test/manual/noverlay/overlay-perf.el               |    2 +-
 test/manual/process-callout-tests.el               |    2 +-
 test/manual/redisplay-testsuite.el                 |    2 +-
 test/manual/scroll-tests.el                        |    2 +-
 test/misc/test-custom-deps.el                      |    2 +-
 test/misc/test-custom-libs.el                      |    2 +-
 test/misc/test-custom-noloads.el                   |    2 +-
 test/misc/test-custom-opts.el                      |    2 +-
 test/src/alloc-tests.el                            |    2 +-
 test/src/buffer-tests.el                           |    2 +-
 test/src/callint-tests.el                          |    2 +-
 test/src/callproc-tests.el                         |    2 +-
 test/src/casefiddle-tests.el                       |    2 +-
 test/src/character-tests.el                        |    2 +-
 test/src/charset-tests.el                          |    2 +-
 test/src/chartab-tests.el                          |    2 +-
 test/src/cmds-tests.el                             |    2 +-
 test/src/coding-tests.el                           |    2 +-
 test/src/comp-resources/comp-test-funcs-dyn.el     |    2 +-
 test/src/comp-resources/comp-test-funcs-dyn2.el    |    2 +-
 test/src/comp-resources/comp-test-funcs.el         |   18 +-
 test/src/comp-resources/comp-test-pure.el          |    2 +-
 test/src/comp-tests.el                             |   30 +-
 test/src/data-tests.el                             |    2 +-
 test/src/decompress-tests.el                       |    2 +-
 test/src/doc-tests.el                              |    2 +-
 test/src/editfns-tests.el                          |    2 +-
 test/src/emacs-module-resources/mod-test.c         |    6 +-
 test/src/emacs-module-tests.el                     |   15 +-
 test/src/emacs-tests.el                            |    2 +-
 test/src/eval-tests.el                             |   70 +-
 test/src/fileio-tests.el                           |    2 +-
 test/src/filelock-tests.el                         |    2 +-
 test/src/floatfns-tests.el                         |    2 +-
 test/src/fns-tests.el                              |   12 +-
 test/src/font-tests.el                             |    2 +-
 test/src/image-tests.el                            |    2 +-
 test/src/indent-tests.el                           |    2 +-
 test/src/inotify-tests.el                          |    2 +-
 test/src/json-tests.el                             |    2 +-
 test/src/keyboard-tests.el                         |    2 +-
 test/src/keymap-tests.el                           |   19 +-
 test/src/lcms-tests.el                             |    2 +-
 test/src/lread-tests.el                            |    2 +-
 test/src/marker-tests.el                           |    2 +-
 test/src/minibuf-tests.el                          |    2 +-
 test/src/print-tests.el                            |    9 +-
 test/src/process-tests.el                          |    2 +-
 test/src/regex-emacs-tests.el                      |    4 +-
 test/src/search-tests.el                           |    2 +-
 test/src/sqlite-tests.el                           |    2 +-
 test/src/syntax-tests.el                           |    2 +-
 test/src/textprop-tests.el                         |    2 +-
 test/src/thread-tests.el                           |    2 +-
 test/src/timefns-tests.el                          |    2 +-
 test/src/treesit-tests.el                          |   38 +-
 test/src/undo-tests.el                             |    2 +-
 test/src/xdisp-tests.el                            |    2 +-
 test/src/xfaces-tests.el                           |    2 +-
 test/src/xml-tests.el                              |    2 +-
 3521 files changed, 36145 insertions(+), 21165 deletions(-)

diff --git a/.dir-locals.el b/.dir-locals.el
index e087aa89cd1..1f08c882e0b 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -3,11 +3,17 @@
 
 ((nil . ((tab-width . 8)
          (sentence-end-double-space . t)
-         (fill-column . 70)
-        (emacs-lisp-docstring-fill-column . 65)
+         (fill-column . 72)
+        (emacs-lisp-docstring-fill-column . 72)
          (vc-git-annotate-switches . "-w")
          (bug-reference-url-format . "https://debbugs.gnu.org/%s";)
         (diff-add-log-use-relative-names . t)
+         (etags-regen-regexp-alist
+          .
+          ((("c" "objc") .
+            ("/[ \t]*DEFVAR_[A-Z_ \t(]+\"\\([^\"]+\\)\"/\\1/"
+             "/[ \t]*DEFVAR_[A-Z_ \t(]+\"[^\"]+\",[ 
\t]\\([A-Za-z0-9_]+\\)/\\1/"))))
+         (etags-regen-ignores . ("test/manual/etags/"))
          (vc-prepare-patches-separately . nil)))
  (c-mode . ((c-file-style . "GNU")
             (c-noise-macro-names . ("INLINE" "NO_INLINE" 
"ATTRIBUTE_NO_SANITIZE_UNDEFINED"
diff --git a/.gitattributes b/.gitattributes
index 39a82cc0efc..38cc45f3ee3 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,6 +1,6 @@
 # Attributes of Emacs files in the Git repository.
 
-# Copyright 2015-2023 Free Software Foundation, Inc.
+# Copyright 2015-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/.gitignore b/.gitignore
index 81abc4c90ff..29c571a3dcb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
 # Files that Git should ignore in the Emacs source directory.
 
-# Copyright 2009-2023 Free Software Foundation, Inc.
+# Copyright 2009-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
@@ -376,7 +376,10 @@ _gdb_history
 
 # Files ignored in exec/.
 exec/aclocal.m4
+exec/config.guess
+exec/config.sub
 exec/config.status
+exec/install-sh
 exec/loader
 exec/test
 exec/exec1
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8462fdddc3a..a9cf69ac195 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-# Copyright (C) 2021-2023 Free Software Foundation, Inc.
+# Copyright (C) 2021-2024 Free Software Foundation, Inc.
 #
 #  This file is part of GNU Emacs.
 #
diff --git a/.mailmap b/.mailmap
index 5d80e4aa082..18e55b0d1e7 100644
--- a/.mailmap
+++ b/.mailmap
@@ -28,6 +28,7 @@ Arash Esbati <arash@gnu.org> <arash.esbati@gmail.com>
 Arash Esbati <arash@gnu.org> <esbati@gmx.de>
 Artur Malabarba <bruce.connor.am@gmail.com> <am12548@it055607.users.bris.ac.uk>
 Artur Malabarba <bruce.connor.am@gmail.com> Artur Malabarba <address@hidden>
+Basil L. Contovounesios <basil@contovou.net> <contovob@tcd.ie>
 Bastien Guerry <bzg@gnu.org>
 Bastien Guerry <bzg@gnu.org> <bastien1@free.fr>
 Bastien Guerry <bzg@gnu.org> <bzg@altern.org>
@@ -163,8 +164,8 @@ Ronnie Schnell <ronnie@driver-aces.com>
 Ryan C. Thompson <rct@thompsonclan.org>
 Sam Steingold <sds@gnu.org> <sdsg@amazon.com>
 Simen Heggestøyl <simenheg@runbox.com>
-Simen Heggestøyl <simenheg@runbox.com> <simenheg@ifi.uio.no>
 Simen Heggestøyl <simenheg@runbox.com> <simenheg@gmail.com>
+Simen Heggestøyl <simenheg@runbox.com> <simenheg@ifi.uio.no>
 Simon Josefsson <simon@josefsson.org> <jas@extundo.com>
 Stefan Kangas <stefankangas@gmail.com> <stefan@marxist.se>
 Stefan Monnier <monnier@iro.umontreal.ca> <monnier@IRO.UMontreal.CA>
diff --git a/CONTRIBUTE b/CONTRIBUTE
index 68c41638942..70b9760bb99 100644
--- a/CONTRIBUTE
+++ b/CONTRIBUTE
@@ -1,4 +1,4 @@
-Copyright (C) 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 2006-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 * How developers contribute to GNU Emacs
diff --git a/ChangeLog.1 b/ChangeLog.1
index 597b320dff4..b592cc0bcab 100644
--- a/ChangeLog.1
+++ b/ChangeLog.1
@@ -14700,7 +14700,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1993-1999, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1993-1999, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/ChangeLog.2 b/ChangeLog.2
index d40401093c5..7c1267e66b9 100644
--- a/ChangeLog.2
+++ b/ChangeLog.2
@@ -8956,10 +8956,10 @@
 
 2016-02-04  Carlos Pita  <carlosjosepita@gmail.com>  (tiny change)
 
-       Make complection in erc use consistent casing
+       Make completion in erc use consistent casing
 
        * lisp/erc/erc-pcomplete.el (pcomplete-erc-all-nicks): Make
-       case in the complection consistent (bug#18509).
+       case in the completion consistent (bug#18509).
 
 2016-02-04  Francis Litterio  <flitterio@gmail.com>
 
@@ -17094,11 +17094,11 @@
        * lisp/json.el (json-encoding-object-sort-predicate): New variable
        for specifying a sorting predicate for JSON objects during encoding.
        (json--plist-to-alist): New utility function.
-       (json-encode-hash-table): Re-use `json-encode-alist' when object keys
+       (json-encode-hash-table): Reuse `json-encode-alist' when object keys
        are to be sorted.
        (json-encode-alist): Sort output by
        `json-encoding-object-sort-predicate, when set.
-       (json-encode-plist): Re-use `json-encode-alist' when object keys are
+       (json-encode-plist): Reuse `json-encode-alist' when object keys are
        to be sorted.
        (json-pretty-print-buffer-ordered): New command to pretty print the
        buffer with object keys sorted alphabetically.
@@ -19542,7 +19542,7 @@
        calling low-level functions.
 
        * test/automated/file-notify-tests.el (file-notify--test-timeout):
-       Decrase to 6 seconds for remote directories.
+       Decrease to 6 seconds for remote directories.
        (file-notify-test02-events): Expect different number of
        `attribute-changed' events for the local and remote cases.  Apply
        short delays between the operations, in order to receive all
@@ -32624,7 +32624,7 @@
        (verilog-set-auto-endcomments): Fix end comments for functions of
        type void, etc.  Reported by Alex Reed.
        (verilog-do-indent): Fix electric tab deleting form-feeds.  Note
-       caused by indent-line-to deleting tabls pre 24.5.
+       caused by indent-line-to deleting tables pre 24.5.
        (verilog-nameable-item-re): Fix nameable items that can have an
        end-identifier to include endchecker, endgroup, endprogram,
        endproperty, and endsequence.  Reported by Alex Reed.
@@ -35788,7 +35788,7 @@ See ChangeLog.1 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2015-2023 Free Software Foundation, Inc.
+  Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/ChangeLog.3 b/ChangeLog.3
index d831b14178c..dc712df43ad 100644
--- a/ChangeLog.3
+++ b/ChangeLog.3
@@ -146,7 +146,7 @@
 
 2022-10-04  Andreas Schwab  <schwab@linux-m68k.org>
 
-       * src/emacs.c (load_pdump): Propery handle case when executable
+       * src/emacs.c (load_pdump): Properly handle case when executable
        wasn't found.
 
 2022-10-04  Eli Zaretskii  <eliz@gnu.org>
@@ -6570,7 +6570,7 @@
 
 2021-10-04  Lars Ingebrigtsen  <larsi@gnus.org>
 
-       Mention ffap-file-name-with-spaces in the ffap doc strin
+       Mention ffap-file-name-with-spaces in the ffap doc string
 
        * lisp/ffap.el (find-file-at-point): Mention
        ffap-file-name-with-spaces in the doc string.
@@ -7174,7 +7174,7 @@
 
        (ess-eval-visibly-p): Declare.
        (org-babel-julia-assign-elisp): Remove unused vars `header` and
-       `row-names` and corespondingly remove now unused args `colnames-p` and
+       `row-names` and correspondingly remove now unused args `colnames-p` and
        `rownames-p`.
        (org-babel-variable-assignments:julia): Adjust call to
        `org-babel-julia-assign-elisp` accordingly.
@@ -10203,7 +10203,7 @@
 
 2021-09-17  Lars Ingebrigtsen  <larsi@gnus.org>
 
-       Mention that the garbage collection is convervative
+       Mention that the garbage collection is conservative
 
        * doc/lispref/internals.texi (Garbage Collection): Mention that
        we're using a conservative gc (bug#42013).
@@ -21832,7 +21832,7 @@
        * src/doprnt.c (exprintf, evxprintf):
        * src/lisp.h (exprintf, evxprintf): Don't use a pointer-to-const type
        for the `nonheapbuf` argument: although it is never dereferenced, GCC
-       will warn when passing a pointer to uninitialised memory otherwise.
+       will warn when passing a pointer to uninitialized memory otherwise.
        * src/fns.c (sort_vector_copy, realize_face, realize_gui_face)
        (realize_tty_face): Use the same signatures in the prototypes as in
        the actual function definitions.
@@ -23755,7 +23755,7 @@
 
 2021-05-29  Lars Ingebrigtsen  <larsi@gnus.org>
 
-       Improve the file-accessible-directory-p doc strin
+       Improve the file-accessible-directory-p doc string
 
        * src/fileio.c (Ffile_accessible_directory_p): Don't use the
        phrase "directory name spec", which isn't defined (bug#18201).
@@ -44752,7 +44752,7 @@
        (nxml-prefer-utf-16-little-to-big-endian-flag)
        (nxml-default-buffer-file-coding-system)
        (nxml-auto-insert-xml-declaration-flag): Add :safe to allow easier
-       cusomization (bug#45969).
+       customization (bug#45969).
 
 2021-01-19  Lars Ingebrigtsen  <larsi@gnus.org>
 
@@ -47582,10 +47582,10 @@
 
 2020-12-30  Andrea Corallo  <akrl@sdf.org>
 
-       Order function types in aphabetical order
+       Order function types in alphabetical order
 
        * lisp/emacs-lisp/comp.el (comp-known-type-specifiers): Reorder in
-       aphabetical order and comment.
+       alphabetical order and comment.
 
 2020-12-30  Andrea Corallo  <akrl@sdf.org>
 
@@ -55395,7 +55395,7 @@
 
 2020-11-18  Andrea Corallo  <akrl@sdf.org>
 
-       Fix eln file hasing for symlink paths (bug#44701)
+       Fix eln file hashing for symlink paths (bug#44701)
 
        * src/comp.c (Fcomp_el_to_eln_filename): Call `file-truename'
        in place of `expand-file-name' when available.
@@ -55928,7 +55928,7 @@
        Fix debug symbol emission
 
        * src/comp.c (Fcomp__compile_ctxt_to_file): Now that we do not
-       rely anymore on globlal variables move logic in from
+       rely anymore on global variables move logic in from
        'Fcomp__init_ctxt' so comp.debug is already set correctly.
 
 2020-11-14  Andrea Corallo  <akrl@sdf.org>
@@ -59251,7 +59251,7 @@
 
 2020-10-26  Andrea Corallo  <akrl@sdf.org>
 
-       Make native compiler tollerant to redefined primitives (bug#44221).
+       Make native compiler tolerant to redefined primitives (bug#44221).
 
        * lisp/emacs-lisp/comp.el (comp-emit-set-call-subr): Rework based
        on the fact that the subr can now be redefined.
@@ -59833,7 +59833,7 @@
        Fix error in tramp-sh-handle-make-process
 
        * lisp/net/tramp-sh.el (tramp-sh-handle-make-process): Don't use heredoc
-       script whent the argument contains a string.
+       script when the argument contains a string.
 
 2020-10-23  Stefan Kangas  <stefan@marxist.se>
 
@@ -64846,7 +64846,7 @@
 
 2020-09-24  Andrea Corallo  <akrl@sdf.org>
 
-       Add a test for primitive advicing effectiveness
+       Add a test for primitive advising effectiveness
 
        * test/src/comp-test-funcs.el (comp-test-primitive-advice-f): New
        function.
@@ -64903,7 +64903,7 @@
        install a subr trampoline into the function relocation table.
        Once this is done any call from native compiled Lisp to the
        related primitive will go through the `funcall' trampoline
-       making advicing effective.
+       making advising effective.
 
 2020-09-23  Andrea Corallo  <akrl@sdf.org>
 
@@ -70385,7 +70385,7 @@
        (MD5_BLOCKSIZE): New macro.
        (accumulate_and_process_md5, final_process_md5, md5_gz_stream)
        (comp_hash_source_file): New functions.
-       (Fcomp_el_to_eln_filename): Rework for hasing using also source
+       (Fcomp_el_to_eln_filename): Rework for hashing using also source
        file content.
 
        * src/lread.c (maybe_swap_for_eln): Rename el_name -> src_name as
@@ -73450,7 +73450,7 @@
 
 2020-08-11  Paul Eggert  <eggert@cs.ucla.edu>
 
-       pdumper speed tweeks for hash tables
+       pdumper speed tweaks for hash tables
 
        * src/pdumper.c (dump_queue_empty_p): Avoid unnecessary call
        to Fhash_table_count on a known hash table.
@@ -77752,7 +77752,7 @@
 
 2020-06-22  Andrea Corallo  <akrl@sdf.org>
 
-       Handle correctly pure delaration specifier.
+       Handle correctly pure declaration specifier.
 
        * lisp/emacs-lisp/comp.el (comp-func): New slot 'pure'.
        (comp-spill-decl-spec): New function.
@@ -81415,7 +81415,7 @@
 
 2020-05-14  Andrea Corallo  <akrl@sdf.org>
 
-       Dump log and intemediate GCC IRs only at comp-debug 3
+       Dump log and intermediate GCC IRs only at comp-debug 3
 
        * src/comp.c (Fcomp__init_ctxt): Increase threshold for dumping
        really everything to 'comp-debug' 3.
@@ -84459,7 +84459,7 @@
        either be encoding a string without NL, or decoding without CR.
 
        * src/coding.c (string_ascii_p): Revert to a pure predicate.
-       (code_convert_string): Fix logic.  Don't use uninitialised
+       (code_convert_string): Fix logic.  Don't use uninitialized
        ascii_p (removed).  Use memchr to detect CR or LF in string when needed.
        * test/src/coding-tests.el (coding-nocopy-ascii):
        Update tests to include encodings with explicit EOL conversions.
@@ -86579,7 +86579,7 @@
 
        Merge remote-tracking branch 'savannah/master' into HEAD
 
-       * Fix regexp instroduced by f055f52321
+       * Fix regexp introduced by f055f52321
 
 2020-03-09  Paul Eggert  <eggert@cs.ucla.edu>
 
@@ -86613,7 +86613,7 @@
 
        * lisp/term/rxvt.el: Enable backeted paste and window title
 
-       rxvt-unicode uses the same escape sequences as xterm so just re-use
+       rxvt-unicode uses the same escape sequences as xterm so just reuse
        the xterm functions to enable them.  The `xterm-rxvt-function-map`
        keymap already has
 
@@ -94009,7 +94009,7 @@
        Fix an error in tramp-sh-handle-make-process.  Don't merge with master
 
        * lisp/net/tramp-sh.el (tramp-sh-handle-make-process): Don't use heredoc
-       script whent the argument contains a string.
+       script when the argument contains a string.
 
 2021-02-03  Stefan Kangas  <stefan@marxist.se>
 
@@ -97511,7 +97511,7 @@
 
        * lisp/subr.el (cancel-change-group): Fix bug#39680
 
-       Don't re-use an existing `pending-undo-list` even if (eq last-command 
'undo)
+       Don't reuse an existing `pending-undo-list` even if (eq last-command 
'undo)
        since there might have been changes to the buffer since that `undo` 
command
        and the `pending-undo-list` can hence be invalid for the current
        buffer contents.
@@ -110510,7 +110510,7 @@
 
 2019-10-01  Lars Ingebrigtsen  <larsi@gnus.org>
 
-       Make the help page mention the customizeable global mode variable
+       Make the help page mention the customizable global mode variable
 
        * lisp/help-fns.el (help-fns--customize-variable): Factor out into
        own function for reuse.
@@ -117135,7 +117135,7 @@
        Use timer-convert with t rather than doing it by hand.
        * src/timefns.c (time_hz_ticks, time_form_stamp, lisp_time_form_stamp):
        Remove; no longer needed.
-       (decode_lisp_time): Rturn the form instead of having a *PFORM arg.
+       (decode_lisp_time): Return the form instead of having a *PFORM arg.
        All uses changed.
        (time_arith): Just return TICKS if HZ is 1.
        (Fencode_time): Remove argument FORM.  All callers changed.
@@ -131090,7 +131090,7 @@
        Make shr-rescale-image respect get-buffer-window again
 
        * lisp/net/shr.el (shr-rescale-image): Partially revert previous
-       change -- ressurrect the check for `get-buffer-window'.
+       change -- resurrect the check for `get-buffer-window'.
 
 2019-05-16  Ivan Shmakov  <ivan@siamics.net>
 
@@ -135103,7 +135103,7 @@
        (help-fns--var-ignored-local, help-fns--var-file-local)
        (help-fns--var-watchpoints, help-fns--var-obsolete)
        (help-fns--var-alias, help-fns--var-bufferlocal): New functions,
-       extacted from describe-variable.
+       extracted from describe-variable.
        (describe-variable): Run help-fns-describe-variable-functions instead.
 
 2019-04-12  Glenn Morris  <rgm@gnu.org>
@@ -163190,7 +163190,7 @@
        Quieten eshell compilation
 
        * lisp/eshell/em-tramp.el: Require esh-cmd.
-       * lisp/eshell/esh-ext.el: Requie esh-io at runtime too.
+       * lisp/eshell/esh-ext.el: Require esh-io at runtime too.
 
 2018-02-28  Glenn Morris  <rgm@gnu.org>
 
@@ -164098,7 +164098,7 @@
        (server-socket-dir): Compute socket dir from
        `get-external-sockname'.
        (server-start): Don't check for existing server when an
-       uninitialised external socket has been passed to Emacs.
+       uninitialized external socket has been passed to Emacs.
        * src/emacs.c: (main): Obtain socket name via getsockname and pass
        to `init_process_emacs'.
        * src/lisp.h: (init_process_emacs): Add second parameter.
@@ -165010,7 +165010,7 @@
 
        Merge from origin/emacs-26
 
-       6415b2d Allow read-passwd to hide characters inserted by C-y.  (Secur...
+       6415b2d Allow read-passwd to hide characters inserted by C-y.  
(Secure...
        8cb4ffb * etc/PROBLEMS: Document issues with double-buffering.  (Bug#...
        fd10070 * lisp/window.el (window-largest-empty-rectangle): Fix grammar.
        e1a4403 Minor changes in the Emacs manual
@@ -165500,7 +165500,7 @@
        1fc98ed073 ; Spelling fix
        bb396a369c Update Org to v9.1.6
        fa582153f7 Use text-pixels values only when saving framesets (Bug#30141)
-       6b01b9475d Minor improvement in section "Pages" of the usere manual
+       6b01b9475d Minor improvement in section "Pages" of the user manual
        e8c8bd3de2 Minor improvements in user manual
        26b8b92e63 Improve the "Mark" chapter of the user manual
        759569fe40 Improve the "Buffers" chapter of the user manual
@@ -167643,7 +167643,7 @@
 
 2017-12-12  Glenn Morris  <rgm@gnu.org>
 
-       Fix gitmerge handling of automatic conflict reslution
+       Fix gitmerge handling of automatic conflict resolution
 
        * admin/gitmerge.el (gitmerge-resolve): Reenable NEWS handling.
        (gitmerge-resolve-unmerged): Commit after successful resolution.
@@ -172441,11 +172441,11 @@
 
        * src/window.c (Fset_window_margins, Fset_window_fringes)
        (Fset_window_scroll_bars): In doc-strings tell that a window
-       must be large enough to accommodate fringes, sroll bars and
+       must be large enough to accommodate fringes, scroll bars and
        margins of the desired size.
        * doc/lispref/display.texi (Fringe Size/Pos, Scroll Bars)
        (Display Margins): Tell that windows must be large enough to
-       accommodate fringes, sroll bars and margins of the desired
+       accommodate fringes, scroll bars and margins of the desired
        size.
 
 2019-03-10  Eli Zaretskii  <eliz@gnu.org>
@@ -175963,7 +175963,7 @@
        Save the server alias on reconnect (Bug#29657)
 
        rcirc does not retain the server alias on reconnect.  As a result, rcirc
-       fails to re-use server and channel buffers when an alias is used.  
Further
+       fails to reuse server and channel buffers when an alias is used.  
Further
        problems may ensue when aliases are used to differentiate multiple
        connections to the same host, for example when using a single IRC 
bouncer
        or proxy to connect to multiple IRC networks.
@@ -180914,7 +180914,7 @@
 
 2018-01-21  Eli Zaretskii  <eliz@gnu.org>
 
-       Minor improvement in section "Pages" of the usere manual
+       Minor improvement in section "Pages" of the user manual
 
        * doc/emacs/text.texi (Pages): Improve wording.  Suggested by Will
        Korteland <emacs-devel@korte.land> in emacs-manual-bugs@gnu.org.
@@ -184512,7 +184512,7 @@
        * src/lisp.h (GCALIGNMENT): Change it back to a macro
        that expands to a literal integer constant, for older GCC.
        I had mistakenly thought that only MSVC had the problem.
-       Problem repored by Eli Zaretskii (Bug#29040#69).
+       Problem reported by Eli Zaretskii (Bug#29040#69).
 
 2017-11-03  Paul Eggert  <eggert@cs.ucla.edu>
 
@@ -186856,7 +186856,7 @@
        * doc/misc/flymake.texi (Overview of Flymake): Rewrite a bit.
        (Installing Flymake): Mostly scratch. Flymake comes with Emacs.
        (Running the syntax check): Simplify.
-       (Viewing error messages): Dekete,
+       (Viewing error messages): Delete.
        (Syntax check statuses): Rewrite.
        (Troubleshooting): Simplify.
        (Customizable variables): Rewrite.
@@ -188461,7 +188461,7 @@
        Loosen strict parsing requirement for desktop files
 
        There are other desktop-looking files, for instance those having to do
-       with MIME typess, that would benefit from being able to be read by this
+       with MIME types, that would benefit from being able to be read by this
        function.  It helps to have some flexibility.
        * lisp/xdg.el (xdg-desktop-read-file): Remove an error condition.
        * test/lisp/xdg-tests.el: Remove a test.
@@ -219622,7 +219622,7 @@
        for 0x80 ⪬ c < 0x100.  In other words, the loop never executes for
        c ≥ 0x80 and RE_CHAR_TO_MULTIBYTE call is unnecessary for c < 0x80.
 
-       * src/regex.c (regex_compile): Simplyfy a for loop by eliminating
+       * src/regex.c (regex_compile): Simplify a for loop by eliminating
        dead iterations and unnecessary macro calls.
 
 2016-09-08  Michal Nazarewicz  <mina86@mina86.com>
@@ -229115,7 +229115,7 @@
        6da3a6d Port to strict C99 offsetof
        de7601f Port to GTK with strict C11 compiler
        658aa2d Port to GTK with strict C99 compiler
-       1df7173 Avoid screen artifacts with new OS X visible bell after scrol...
+       1df7173 Avoid screen artifacts with new OS X visible bell after 
scroll...
        7a2edd3 Merge branch 'emacs-25' of git.sv.gnu.org:/srv/git/emacs into...
        dca240a Suppress some Tramp tests for OSX, do not merge with master
        9094304 * lisp/progmodes/xref.el (xref-buffer-name, xref--window): Mo...
@@ -233746,7 +233746,7 @@
 
        ee73997 Make erc work better when encountering unknown prefix chars
        b99141d Make erc completion case-insensitive again
-       66c4620 Make complection in erc use consistent casing
+       66c4620 Make completion in erc use consistent casing
        8c562b2 Make /QUIT in erc more robust
        d93d2c5 Make tracking faces in Emacs work more reliably
        af6ab7e Make shr not bug out on images on non-graphical displays
@@ -234944,7 +234944,7 @@
        (rng-complete-attribute-value): Don't perform completion, but return
        completion data instead.
        (rng-complete-qname-function, rng-generate-qname-list): Add a few
-       arguments, previously passed via dynamic coping.
+       arguments, previously passed via dynamic copying.
        (rng-strings-to-completion-table): Rename from
        rng-strings-to-completion-alist.  Don't return an alist.  Don't both
        sorting and uniquifying.
@@ -235280,7 +235280,7 @@
        d400753 * src/buffer.c: Stick with ASCII in doc string.
        221240c Reword transient-mark-mode doc string
        977d3ea Update doc string of 'selective-display'
-       229c3fa Make C++ buffers writeable when writing their initial text
+       229c3fa Make C++ buffers writable when writing their initial text
                properties.
        f5c762c Additional changes for "make check-expensive"
        1729cf3 ; * admin/MAINTAINERS: Remove myself.
@@ -237355,7 +237355,7 @@ See ChangeLog.2 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2015-2023 Free Software Foundation, Inc.
+  Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/ChangeLog.4 b/ChangeLog.4
index 24afabdbbb1..f0ae386f7fe 100644
--- a/ChangeLog.4
+++ b/ChangeLog.4
@@ -1,3 +1,1556 @@
+2024-01-18  Eli Zaretskii  <eliz@maintain0p.gnu.org>
+
+       * Version 29.2 released.
+
+       * ChangeLog.4:
+       * etc/HISTORY: Update for Emacs 29.2.
+       * README:
+       * configure.ac:
+       * nt/README.W32:
+       * msdos/sed2v2.inp: Bump Emacs version to 29.2.
+
+2024-01-17  Dmitry Gutov  <dmitry@gutov.dev>
+
+       diff-mode: Support committing diff with file deletions
+
+       * lisp/vc/diff-mode.el (diff-vc-deduce-fileset):
+       Remove nil elements from the result (bug#68443).
+
+2024-01-16  Juri Linkov  <juri@linkov.net>
+
+       * lisp/net/eww.el (eww-retrieve): Fix args of eww-render for sync 
(bug#68336).
+
+       Suggested by Phil Sainty <psainty@orcon.net.nz>.
+
+2024-01-16  Mike Kupfer  <kupfer@rawbw.com>
+
+       Fix folder creation error (Bug#67361)
+
+       * lisp/mh-e/mh-funcs.el (mh-kill-folder)
+       * lisp/mh-e/mh-search.el (mh-index-new-folder)
+       * lisp/mh-e/mh-utils.el (mh-prompt-for-folder):
+       Check for existence of 'speedbar-buffer' rather than
+       'mh-speed-folder-map'.  The latter can exist if
+       'mh-speed' has only been loaded but not displayed.
+
+       (cherry picked from commit e6a2901b1be6b4aa01f8bf0d3c6e06344ce8d366)
+
+2024-01-15  Gregory Heytings  <gregory@heytings.org>
+
+       Simplify 'without-restriction'
+
+       This simplification is symmetrical to 01fb898420.
+
+       * src/editfns.c: (Finternal__labeled_widen): Add a call to
+       'Fwiden', and rename from 'internal--unlabel-restriction'.
+       (unwind_labeled_narrow_to_region): Use the renamed function, and
+       remove the call to 'Fwiden'.
+       (syms_of_editfns): Rename the symbol.
+
+       * lisp/subr.el (internal--without-restriction): Use the renamed
+       function.
+
+       (cherry picked from commit 9e9e11648d3d5514de85edfb69f0949a062f4716)
+
+2024-01-14  Gregory Heytings  <gregory@heytings.org>
+
+       Fix blunder in labeled_narrow_to_region
+
+       * src/editfns.c (labeled_narrow_to_region): Record point before,
+       instead of after, calling narrow-to-region; otherwise point may
+       already have been changed.  Fixes bug#66764.
+
+2024-01-14  Daniel Martín  <mardani29@yahoo.es>
+
+       Fix documentation of icon-elements
+
+       * lisp/emacs-lisp/icons.el (icon-elements): The plist key it returns
+       is `image', not `display'.  (Bug#68451)
+
+2024-01-14  Stefan Kangas  <stefankangas@gmail.com>
+
+       Improve two docstrings in ox-latex
+
+       * lisp/org/ox-latex.el (org-latex-src-block-backend)
+       (org-latex-engraved-theme): Improve docstring; mention that
+       engrave-faces is a GNU ELPA package.
+
+2024-01-14  Stefan Kangas  <stefankangas@gmail.com>
+
+       Doc fix in auth-source-read-char-choice
+
+       * lisp/auth-source.el (auth-source-read-char-choice): Don't
+       document 'dropdown-list', which was removed in 2011.
+
+2024-01-13  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix info-xref-tests
+
+       * doc/lispintro/emacs-lisp-intro.texi (How let Binds Variables):
+       Fix cross-reference.  (Bug#68428)
+
+       * test/lisp/info-xref-tests.el (info-xref-test-write-file): Fix
+       test on MS-Windows when run from MSYS Bash.
+
+2024-01-13  Juri Linkov  <juri@linkov.net>
+
+       Add @kindex in manuals for existing keybindings on 'C-x x/w' (bug#13167)
+
+       * doc/emacs/buffers.texi (Misc Buffer): Add @kindex for 'C-x x r',
+       'C-x x u', 'C-x x i'.
+
+       * doc/emacs/display.texi (Line Truncation): Add @kindex for 'C-x x t'.
+
+       * doc/emacs/files.texi (Reverting): Add @kindex for 'C-x x g'.
+
+       * doc/emacs/windows.texi (Change Window): Use new keybinding 'C-x w 0'
+       instead of 'M-x delete-windows-on'.
+
+       * doc/misc/info.texi (Create Info buffer): Add @kindex for 'C-x x n'.
+
+2024-01-13  Eli Zaretskii  <eliz@gnu.org>
+
+       Improve documentation of 'emacs_function' in modules
+
+       * doc/lispref/internals.texi (Module Functions): Warn about
+       accessing the ARGS array in module functions.
+
+2024-01-12  Eli Zaretskii  <eliz@gnu.org>
+
+       Improve documentation of Ispell commands
+
+       * doc/emacs/fixit.texi (Spelling): Document "C-u M-$" and warn
+       against modifications in recursive-edit.  (Bug#14192)
+
+2024-01-11  Stefan Kangas  <stefankangas@gmail.com>
+
+       Don't recommend inverse-video for debugging
+
+       * etc/DEBUG: Don't recommend 'inverse-video', which has been broken
+       for 20 years, give or take.  (Bug#11430)
+
+2024-01-11  Xiyue Deng  <manphiz@gmail.com>
+
+       Fix typo in lispref "Creating Strings" section
+
+       * doc/lispref/strings.texi (String Basics): Fix typo (bug#68375).
+
+2024-01-11  Xiyue Deng  <manphiz@gmail.com>  (tiny change)
+
+       Fix count of no-op functions (bug#68375)
+
+       It looks like there are actually three kinds of no-op functions.
+
+       * doc/lispref/functions.texi (Calling Functions): Fix count and
+       plural of no-op functions.
+
+2024-01-11  Xiyue Deng  <manphiz@gmail.com>  (tiny change)
+
+       Wrap @pxref of Abbrevs in parentheses (bug#68375)
+
+       * doc/lispref/symbols.texi (Shorthands): Wrap `@pxref{Abbrevs}' in
+       parentheses.
+
+2024-01-10  Mauro Aranda  <maurooaranda@gmail.com>
+
+       Add examples to the Widget manual
+
+       * doc/misc/widget.texi (Widget Gallery, Defining New Widgets): Add
+       examples.  (Bug#66229)
+
+2024-01-10  Mauro Aranda  <maurooaranda@gmail.com>
+
+       Implement missing functions for custom-icon widget
+
+       * lisp/cus-edit.el (custom-icon-reset-saved, custom-icon-mark-to-save)
+       (custom-icon-state-set-and-redraw, custom-icon-reset-standard)
+       (custom-icon-mark-to-reset-standard): New functions.
+       (custom-icon, custom-icon-extended-menu): Register and add them to the
+       menu.  (Bug#66947)
+
+2024-01-10  Stephen Berman  <stephen.berman@gmx.net>
+
+       Fix fontification of cgroup2 in fstab (bug#68367)
+
+       * lisp/generic-x.el (etc-fstab-generic-mode): Add cgroup2.
+
+2024-01-10  Philip Kaludercic  <philipk@posteo.net>
+
+       Handle package versions that are not version strings
+
+       * lisp/emacs-lisp/package.el (package-menu--version-predicate): Ignore
+       any errors raised by 'version-to-list', thus falling back to the
+       default version list.  (Bug#68317)
+
+       (cherry picked from commit eb913c7501489e1eae475cae843fccdf14cc24d8)
+
+2024-01-09  Jim Porter  <jporterbugs@gmail.com>
+
+       Introduce 'let' using lexical binding in the Lisp Introduction
+
+       * doc/lispintro/emacs-lisp-intro.texi (Prevent confusion): Rework the
+       explanation to discuss how things work under lexical binding.
+       (How let Binds Variables): Describe the differences between lexical
+       and dynamic binding (including how to configure it).
+       (defvar): Mention that 'defvar' declares variables as always
+       dynamically-bound (bug#66756).
+
+2024-01-06  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix 'rmail-summary-by-thread'
+
+       * lisp/mail/rmailsum.el (rmail-summary-by-thread): Call
+       'rmail-new-summary' from the original buffer, not from
+       'rmail-buffer' to avoid failing the logic in 'rmail-new-summary'
+       that decides whether to pop up a new window.  Reported by Andrea
+       Monaco <andrea.monaco@autistici.org>.
+
+2024-01-06  Jean-Christophe Helary  
<jean.christophe.helary@traductaire-libre.org>
+
+       * doc/emacs/back.texi: Fix a typo.
+
+2024-01-06  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix icons.el when icon does not exist as a file
+
+       * lisp/emacs-lisp/icons.el (icons--create): Handle the case when
+       ICON is a file that doesn't exists or is unreadable.  Suggested by
+       David Ponce <da_vid@orange.fr>.  (Bug#66846)
+
+2024-01-05  Juri Linkov  <juri@linkov.net>
+
+       * lisp/isearch.el (isearch-search-and-update): Let-bind 'isearch-cmds'.
+
+       When 'isearch-wrap-pause' is 'no' or 'no-ding', let-bind 'isearch-cmds'
+       to avoid changing it by 'isearch-push-state' in 'isearch-repeat',
+       so that a later DEL (isearch-delete-char) doesn't stop at the
+       intermediate failing state (bug#68158).
+
+2024-01-04  Andrea Corallo  <acorallo@gnu.org>
+
+       * src/comp.c (Fcomp__compile_ctxt_to_file): Fix hash table Qunbound use.
+
+2024-01-04  Eli Zaretskii  <eliz@gnu.org>
+
+       Provide decent documentation for 'help-quick'
+
+       * lisp/help.el (help-quick, help-quick-toggle): Doc fix.
+
+       * doc/emacs/help.texi (Help Summary, Misc Help): Document
+       'help-quick-toggle'.
+
+2024-01-02  Dmitry Gutov  <dmitry@gutov.dev>
+
+       treesit--pre-syntax-ppss: Fix args-out-of-range in 
internal--syntax-propertize
+
+       * lisp/treesit.el (treesit--pre-syntax-ppss): Make sure the lower
+       bound is still within the current restriction (bug#67977).
+
+2024-01-01  Mike Kupfer  <kupfer@rawbw.com>
+
+       Fix mangled Subject header field when forwarding (Bug#67360)
+
+       * lisp/mh-e/mh-comp.el (mh-forward): Overwrite subject when
+       forwarding.
+
+2024-01-01  Kyle Meyer  <kyle@kyleam.com>
+
+       Update to Org 9.6.15
+
+2023-12-31  Eli Zaretskii  <eliz@gnu.org>
+
+       * doc/emacs/custom.texi (Modifier Keys): Fix markup (bug#68164).
+
+       Suggested by Jens Quade <jq@qdevelop.de>.
+
+2023-12-30  Stefan Kangas  <stefankangas@gmail.com>
+
+       org-protocol: Minor copy-edits to Commentary
+
+       * lisp/org/org-protocol.el: Minor copy-edits to Commentary.
+
+2023-12-30  Denis Zubarev  <dvzubarev@yandex.ru>
+
+       Improve syntax highlighting for python-ts-mode
+
+       Fix fontification of strings inside of f-strings interpolation, e.g. for
+       f"beg {'nested'}" - 'nested' was not fontified as string.  Do not
+       override the face of builtin functions (all, bytes etc.) with the
+       function call face.  Add missing assignment expressions (:= *=).
+       Fontify built-ins (dict,list,etc.) as types when they are used in type
+       hints.  Highlight union types (type1|type2).  Highlight base class names
+       in the class definition.  Fontify class patterns in case statements.
+       Highlight the second argument as a type in isinstance/issubclass call.
+       Highlight dotted decorator names.
+
+       * lisp/progmodes/python.el (python--treesit-keywords): Add compound
+       keyword "is not".
+       (python--treesit-builtin-types): New variable that stores all python
+       built-in types.
+       (python--treesit-type-regex): New variable.  Regex matches if text is
+       either built-in type or text starts with capital letter.
+       (python--treesit-builtins): Extract built-in types to other variable.
+       (python--treesit-fontify-string): fix f-string interpolation.  Enable
+       interpolation highlighting only if string-interpolation is presented
+       on the enabled levels of treesit-font-lock-feature-list.
+       (python--treesit-fontify-string-interpolation): Remove function.
+       (python--treesit-fontify-union-types): Fontify nested union types.
+       (python--treesit-fontify-union-types-strict): Fontify nested union
+       types, only if type identifier matches against
+       python--treesit-type-regex.
+       (python--treesit-fontify-dotted-decorator): Fontify all parts of
+       dotted decorator name.
+       (python--treesit-settings): Change/add rules.  (Bug#67061)
+
+       * test/lisp/progmodes/python-tests.el
+       (python-ts-tests-with-temp-buffer): Function for setting up test
+       buffer.
+       (python-ts-mode-compound-keywords-face)
+       (python-ts-mode-named-assignement-face-1)
+       (python-ts-mode-assignement-face-2)
+       (python-ts-mode-nested-types-face-1)
+       (python-ts-mode-union-types-face-1)
+       (python-ts-mode-union-types-face-2)
+       (python-ts-mode-types-face-1)
+       (python-ts-mode-types-face-2)
+       (python-ts-mode-types-face-3)
+       (python-ts-mode-isinstance-type-face-1)
+       (python-ts-mode-isinstance-type-face-2)
+       (python-ts-mode-isinstance-type-face-3)
+       (python-ts-mode-superclass-type-face)
+       (python-ts-mode-class-patterns-face)
+       (python-ts-mode-dotted-decorator-face-1)
+       (python-ts-mode-dotted-decorator-face-2)
+       (python-ts-mode-builtin-call-face)
+       (python-ts-mode-interpolation-nested-string)
+       (python-ts-mode-disabled-string-interpolation)
+       (python-ts-mode-interpolation-doc-string): Add tests.
+
+2023-12-29  Yuan Fu  <casouri@gmail.com>
+
+       Revert "Fix treesit-node-field-name and friends (bug#66674)"
+
+       This reverts commit 9874561f39e62c1c9fada6c2e013f93d9ea65729.
+
+       See bug#67990.  Basically our original code is correct, the error is
+       in libtree-sitter, which only manifests in certain cases.
+
+       https://github.com/tree-sitter/tree-sitter/pull/2104
+
+2023-12-25  Stefan Kangas  <stefankangas@gmail.com>
+
+       Explain status "r" in `epa-list-keys`
+
+       * lisp/epa.el (epa-list-keys): Add revoked status to description.
+       Suggested by CHENG Gao <chenggao@icloud.com>.
+
+2023-12-25  Jared Finder  <jared@finder.org>
+
+       Fix mouse clicks on directory line in Dired
+
+       The option 'dired-kill-when-opening-new-dired-buffer' should be
+       also honored when clicking the mouse to kill prev buffer.
+       * lisp/dired.el (dired--make-directory-clickable): Call
+       'dired--find-possibly-alternative-file' instead of 'dired', in
+       the click callback.  (Bug#67856)
+
+2023-12-25  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix 'split-root-window-right' and 'split-root-window-below'
+
+       * lisp/window.el (split-root-window-right)
+       (split-root-window-below): Fix the 'interactive' spec to avoid
+       misbehaving when invoked with no prefix argument.  (Bug#67452)
+
+2023-12-24  Stefan Kangas  <stefankangas@gmail.com>
+
+       Mark icalendar.el as maintained by emacs-devel
+
+       * lisp/calendar/icalendar.el: Mark emacs-devel as the maintainer.
+       Ref: https://debbugs.gnu.org/34315#152
+
+2023-12-24  Xiyue Deng  <manphiz@gmail.com>
+
+       Fix usage of `setq-default' and offer more suggestions
+
+       cd61af0 changed from default-major-mode to major-mode in the first
+       code sample but didn't change the rest.  This patch fixes this and add
+       some explanations of why use `setq-default' instead of `setq'.  In
+       addition, it gives background on suggesting using text-mode as default
+       mode and suggest other alternatives.
+
+       * doc/lispintro/emacs-lisp-intro.texi (Text and Auto-fill): Fix usage
+       of `setq-default' and offer more suggestions.  (Bug#67848)
+
+2023-12-23  Yuan Fu  <casouri@gmail.com>
+
+       Fix python-ts-mode triple quote syntax (bug#67262)
+
+       * lisp/progmodes/python.el (python--treesit-syntax-propertize): New 
function.
+       (python-ts-mode): Activate python--treesit-syntax-propertize.
+
+2023-12-23  Yuan Fu  <casouri@gmail.com>
+
+       Increment parser timestamp when narrowing changes (bug#67977)
+
+       When narrowing changes, parse reparses, so the timestamp should
+       definitely increment, just like in ts_record_changes.
+
+       Failing to increment this timestamp, outdated nodes would think they
+       are still up-to-date, and try to print their type name.  Printing
+       their type name involves accessing the old parse tree, which is
+       already freed during the last reparse.
+
+       I also found that we don't increment timestamp when changing parser
+       ranges and fixed that as well.
+
+       * src/treesit.c (treesit_sync_visible_region):
+       (Ftreesit_parser_set_included_ranges): Increment timestamp.
+       * src/treesit.h (Lisp_TS_Parser): Add some comments.
+
+2023-12-23  Dmitry Gutov  <dmitry@gutov.dev>
+
+       ruby-ts-mode: Fix indentation for string_array closer
+
+       * lisp/progmodes/ruby-ts-mode.el (ruby-ts--indent-rules):
+       Fix indentation for string_array closer.
+
+2023-12-23  Dmitry Gutov  <dmitry@gutov.dev>
+
+       treesit-major-mode-setup: Use 'treesit--syntax-propertize-notifier'
+
+       * lisp/treesit.el (treesit-major-mode-setup): Make sure
+       'treesit--syntax-propertize-notifier' is used (bug#66732)
+
+2023-12-23  Dmitry Gutov  <dmitry@gutov.dev>
+
+       ruby-ts-mode: Fix an out-of-bounds error with heredoc at eob
+
+       * lisp/progmodes/ruby-ts-mode.el (ruby-ts--syntax-propertize):
+       Fix an out-of-bounds error with heredoc at eob.
+
+2023-12-23  Yuan Fu  <casouri@gmail.com>
+
+       Correctly refontify changed region in tree-sitter modes (bug#66732)
+
+       We already have treesit--font-lock-notifier that should mark changed
+       regions to be refontified, but it's called too late in the redsiplay &
+       fontification pipeline.  Here we add treesit--pre-redisplay that
+       forces reparse and calls notifier functions in
+       pre-redisplay-functions, which is early enough for the marking to take
+       effect.
+
+       Similarly, we force reparse in
+       syntax-propertize-extend-region-functions so syntax-ppss will have the
+       up-to-date syntax information when it scans the buffer text.  We also
+       record the lowest start position of the affected regions, and make
+       sure next syntex-propertize starts from that position.
+
+       * lisp/treesit.el (treesit--pre-redisplay-tick):
+       (treesit--syntax-propertize-start): New variable.
+       (treesit--syntax-propertize-notifier):
+       (treesit--pre-redisplay):
+       (treesit--pre-syntax-ppss): New functions.
+       (treesit-major-mode-setup): Add hooks.
+
+       * lisp/progmodes/ruby-ts-mode.el (ruby-ts-mode): Remove notifier.
+       (ruby-ts--parser-after-change): Remove notifier function.
+
+2023-12-23  Michael Albinus  <michael.albinus@gmx.de>
+
+       * doc/man/emacsclient.1: Fix --tramp option.
+
+2023-12-23  Peter Oliver  <git@mavit.org.uk>  (tiny change)
+
+       * doc/man/emacsclient.1: Add missing sections (bug#66598)
+
+2023-12-23  Xiyue Deng  <manphiz@gmail.com>
+
+       Add explanation for extra parentheses in ELisp Introduction
+
+       * doc/lispintro/emacs-lisp-intro.texi (fwd-para while): Add
+       a note to explain the extra parentheses.  (Bug#67820)
+
+2023-12-23  Xiyue Deng  <manphiz@gmail.com>
+
+       Add sample code to the "let*" section in "forward-paragraph"
+
+       * doc/lispintro/emacs-lisp-intro.texi (fwd-para let): Add code
+       sample.  (Bug#67817)
+
+2023-12-23  Denis Zubarev  <dvzubarev@yandex.ru>
+
+       Fix treesit test (bug#67117)
+
+       * test/src/treesit-tests.el (treesit-search-subtree-forward-1):
+       (treesit-search-subtree-backward-1): Replace treesit--thing-at with
+       treesit-query-capture (treesit--thing-at isn't available in Emacs 29).
+
+2023-12-23  Yuan Fu  <casouri@gmail.com>
+
+       Fix c++-ts-mode indentation (bug#67975)
+
+       * lisp/progmodes/c-ts-mode.el (c-ts-mode--indent-styles): Make indent
+       rule match precise so it doesn't match declaration_list.
+
+2023-12-22  Stefan Kangas  <stefankangas@gmail.com>
+
+       Recommend customizing eglot for python-base-mode
+
+       * doc/misc/eglot.texi (Project-specific configuration): Recommend
+       setting directory local variables for 'python-base-mode' instead of
+       'python-mode'.  This makes any customizations effective also for
+       'python-ts-mode'.
+
+2023-12-22  Eli Zaretskii  <eliz@gnu.org>
+
+       Improve documentation of new native-compilation commands
+
+       * lisp/progmodes/elisp-mode.el (emacs-lisp-mode-menu)
+       (emacs-lisp-native-compile, emacs-lisp-native-compile-and-load):
+       Doc fixes.
+
+       * doc/lispref/compile.texi (Native-Compilation Functions):
+       Document 'emacs-lisp-native-compile' and
+       'emacs-lisp-native-compile-and-load'.
+
+2023-12-21  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       doc/lispintro: Don't mention `set` (bug#67734)
+
+       * doc/lispintro/emacs-lisp-intro.texi (Using set): Delete.
+       (Using setq): Adjust accordingly.
+       (setq): Rename from "set & setq" and don't refer to `set` any more.
+       (Review): Don't mention `set` any more.
+
+2023-12-20  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix script for some characters
+
+       * lisp/international/characters.el (char-script-table): Fix script
+       for 2 characters.
+
+       * admin/unidata/blocks.awk: Fix script for Yijing Hexagram
+       Symbols.  (Bug#67924)
+
+2023-12-18  Denis Zubarev  <dvzubarev@yandex.ru>
+
+       Fix an issue when searching subtree backward (bug#67117)
+
+       * src/treesit.c (treesit_traverse_child_helper):
+       Do not call treesit_traverse_sibling_helper when the named node is
+       required and the last child is the named node.
+       Otherwise treesit_traverse_sibling_helper will move cursor to the
+       previous sibling and last node will be skipped.
+       * test/src/treesit-tests.el (treesit-search-subtree-forward-1):
+       (treesit-search-subtree-backward-1):
+       Add tests.
+
+2023-12-18  Christophe Deleuze  <christophe.deleuze@free.fr>  (tiny change)
+
+       Fix passive mode for tnftp client in ange-ftp.el.
+
+       * lisp/net/ange-ftp.el (ange-ftp-passive-mode): Fix passive mode
+       result string for tnftp client.  (Bug#67865)
+
+2023-12-16  Stefan Kangas  <stefankangas@gmail.com>
+
+       Fix using disabled command without a docstring
+
+       * lisp/novice.el (disabled-command-function): Fix error when the
+       disable command has no docstring.  (Bug#67835)
+
+2023-12-16  Eli Zaretskii  <eliz@gnu.org>
+
+       Improve documentation of text properties handling when yanking
+
+       * doc/lispref/text.texi (Text Properties): Mention special
+       handling of text properties while yanking.
+
+2023-12-16  skykanin  <3789764+skykanin@users.noreply.github.com>  (tiny 
change)
+
+       Eglot: Add Uiua language server
+
+       * lisp/progmodes/eglot.el (eglot-server-programs): Add Uiua language
+       server.  (Bug#67850)
+
+2023-12-16  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix shaping of Sinhala text
+
+       * lisp/language/sinhala.el (composition-function-table): Allow
+       U+200D U+0DCA as well as U+0DCA U+200D between consonants.
+       Suggested by Richard Wordingham <richard.wordingham@ntlworld.com>.
+       (Bug#67828)
+
+2023-12-16  Jeremy Bryant  <jb@jeremybryant.net>
+           Eli Zaretskii  <eliz@gnu.org>
+
+       Add use cases of (fn) documentation facility.
+
+       * doc/lispref/functions.texi (Function Documentation):  Add examples.
+       (Bug#67499)
+
+2023-12-16  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix pasting into terminal-mode on term.el
+
+       * lisp/term.el (term--xterm-paste): Read pasted text from the
+       input event.  Suggested by Jared Finder <jared@finder.org>.
+       (Bug#49253)
+
+2023-12-16  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix opening directory trees from Filesets menu
+
+       In bug#976, the code was fixed, but the cautious condition in
+       the original author's code, which catered to invoking
+       'filelists-open' from the menu-bar menu, was omitted, which made
+       that invocation, which did work before, broken.
+       * lisp/filesets.el (filesets-get-filelist): Fix opening directory
+       trees from the Filesets menu-bar menu.  (Bug#67658)
+
+2023-12-16  Niall Dooley  <dooleyn@gmail.com>  (tiny change)
+
+       Eglot: Add ruff-lsp as an alternative Python server
+
+       ruff-lsp [1] is an LSP server for Ruff [2], [3], a fast Python linter
+       and code formatter.
+
+       It supports surfacing Ruff diagnostics and providing Code Actions to
+       fix them, but is intended to be used alongside another Python LSP in
+       order to support features like navigation and autocompletion.
+
+       [1]: https://github.com/astral-sh/ruff-lsp
+       [2]: https://github.com/astral-sh/ruff
+       [3]: https://docs.astral.sh/ruff/
+
+       * lisp/progmodes/eglot.el (eglot-server-programs): Add ruff-lsp.
+
+2023-12-14  Adam Porter  <adam@alphapapa.net>
+
+       Fix symbol name in Multisession Variables examples
+
+       * doc/lispref/variables.texi (Multisession Variables): Fix symbol
+       name.  (Bug#67823)
+
+2023-12-12  Dmitry Gutov  <dmitry@gutov.dev>
+
+       js-ts-mode: Fix font-lock rules conflict
+
+       * lisp/progmodes/js.el (js--treesit-font-lock-settings): Move
+       'property' to after 'jsx'.  Stop using predicate (bug#67684).
+       (js--treesit-property-not-function-p): Delete.
+
+2023-12-11  Noah Peart  <noah.v.peart@gmail.com>
+
+       Add indentation rules for bracketless statements in js-ts-mode
+
+       * lisp/progmodes/js.el (js--treesit-indent-rules): Add indentation
+       rules to handle bracketless statements (bug#67758).
+       * test/lisp/progmodes/js-tests.el (js-ts-mode-test-indentation):
+       New test for js-ts-mode indentation.
+       * test/lisp/progmodes/js-resources/js-ts-indents.erts: New file
+       with indentation tests for js-ts-mode.
+
+2023-12-10  Yuan Fu  <casouri@gmail.com>
+
+       Fix c-ts-mode bracketless indentation for BSD style (bug#66152)
+
+       * lisp/progmodes/c-ts-mode.el:
+       (c-ts-mode--indent-styles): Make sure the BSD rules only apply to
+       opening bracket (compound_statement), then bracketless statements will
+       fallback to common rules.
+       * test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts: Copy the
+       bracketless test from indent.erts to here.
+
+2023-12-10  Augustin Chéneau  <btuin@mailo.com>
+
+       Add missing indent rules in c-ts-mode (bug#66152)
+
+       Example:
+
+           static myttype *
+           variable_name;
+
+       * lisp/progmodes/c-ts-mode.el (c-ts-mode--indent-styles): Add rules.
+
+2023-12-10  Yuan Fu  <casouri@gmail.com>
+
+       Fix treesit-default-defun-skipper (bug#66711)
+
+       * lisp/treesit.el:
+       (treesit-default-defun-skipper): Add bol to the rx pattern.
+
+2023-12-10  Yuan Fu  <casouri@gmail.com>
+
+       Fix treesit-node-field-name and friends (bug#66674)
+
+       So turns out ts_node_field_name_for_child takes a named node index,
+       but we were passing it normal index that counts both named and
+       anonymous nodes.  That's what makes the field name all wrong in
+       treesit explorer.
+
+       * doc/lispref/parsing.texi:
+       (Accessing Node Information): Update docstring.
+       * lisp/treesit.el (treesit-node-index): Add some unrelated comment.
+       (treesit-node-field-name): Get named node index rather than all node
+       index.
+       * src/treesit.c (Ftreesit_node_field_name_for_child): Update
+       docstring, use ts_node_named_child_count.
+
+2023-12-10  Maciej Kalandyk  <m.kalandyk@outlook.com>
+
+       python-ts-mode: Highlight default parameters
+
+       * lisp/progmodes/python.el (python--treesit-settings):
+       Highlight default parameters (bug#67703).
+
+2023-12-10  Kyle Meyer  <kyle@kyleam.com>
+
+       Update to Org 9.6.13
+
+2023-12-10  Yuan Fu  <casouri@gmail.com>
+
+       Fix c-ts-mode indent heuristic (bug#67417)
+
+       This is a continuation of the first two patches for bug#67417.  The
+       c-ts-mode--prev-line-match heuristic we added is too broad, so for now
+       we are just adding a very specific heuristic for the else case.
+
+       * lisp/progmodes/c-ts-mode.el:
+       (c-ts-mode--prev-line-match): Remove function.
+       (c-ts-mode--else-heuristic): New function.
+       (c-ts-mode--indent-styles): Use c-ts-mode--else-heuristic.
+
+2023-12-10  nverno  <noah.v.peart@gmail.com>
+
+       Fix c-ts-mode indentation (bug#67357)
+
+       1. In a compund_statement, we indent the first sibling against the
+       parent, and the rest siblings against their previous sibling.  But
+       this strategy falls apart when the first sibling is not on its own
+       line.  We should regard the first sibling that is on its own line as
+       the "first sibling"", and indent it against the parent.
+
+       2. In linux style, in a do-while statement, if the do-body is
+       bracket-less, the "while" keyword is indented to the same level as the
+       do-body.  It should be indented to align with the "do" keyword
+       instead.
+
+       * lisp/progmodes/c-ts-mode.el:
+       (c-ts-mode--no-prev-standalone-sibling): New function.
+       (c-ts-mode--indent-styles): Use
+       c-ts-mode--no-prev-standalone-sibling. Add while keyword indent rule.
+       * test/lisp/progmodes/c-ts-mode-resources/indent.erts: New tests.
+
+2023-12-09  nverno  <noah.v.peart@gmail.com>
+
+       Add font-locking for hash-bang lines in typescript-ts-mode.
+
+       * lisp/progmodes/typescript-ts-mode.el
+       (typescript-ts-mode--font-lock-settings):
+       Add font-lock for hash bang line.
+
+2023-12-09  nverno  <noah.v.peart@gmail.com>
+
+       Add font-locking for hash-bang lines in js-ts-mode
+
+       * lisp/progmodes/js.el (js--treesit-font-lock-settings):
+       Add font-lock for hash bang line.
+
+2023-12-09  Dmitry Gutov  <dmitry@gutov.dev>
+
+       ruby-mode: Better detect regexp vs division (bug#67569)
+
+       * lisp/progmodes/ruby-mode.el (ruby-syntax-before-regexp-re):
+       Add grouping around methods from the whitelist.
+       (ruby-syntax-propertize): Also look for spaces around the slash.
+
+2023-12-09  Jared Finder  <jared@finder.org>
+
+       Fix dragging mode line on text terminals with a mouse (bug#67457)
+
+       * lisp/xt-mouse.el (xterm-mouse-translate-1): Fix the 'event-kind'
+       property of mouse-movement symbols emitted by xt-mouse.
+       * lisp/term/linux.el (terminal-init-linux): Call 'gpm-mouse-mode'
+       to set up the terminal for the mouse, if needed.
+
+2023-12-08  Christophe TROESTLER  <Christophe.TROESTLER@umons.ac.be>
+
+       (rust-ts-mode): Set electric-indent-chars
+
+       * lisp/progmodes/rust-ts-mode.el (rust-ts-mode):
+       Set electric-indent-chars (bug#67701).
+
+2023-12-07  Dmitry Gutov  <dmitry@gutov.dev>
+
+       js-ts-mode: Highlight function parameters inside destructuring
+
+       * lisp/progmodes/js.el (js--treesit-font-lock-settings):
+       Highlight function parameters declared using destructuring syntax.
+
+2023-12-07  Dmitry Gutov  <dmitry@gutov.dev>
+
+       js-ts-mode: Highlight property shorthands in assignments
+
+       * lisp/progmodes/js.el (js--treesit-lhs-identifier-query): Match
+       property shorthands (which turn into variable reference).
+       (js--treesit-fontify-assignment-lhs): Use the matches.
+
+2023-12-07  Dmitry Gutov  <dmitry@gutov.dev>
+
+       (js--treesit-font-lock-settings): Highlight parameters in function 
expression
+
+       * lisp/progmodes/js.el (js--treesit-font-lock-settings):
+       Highlight parameters in a function expression (the node type
+       'function').  Make the matcher for 'formal_parameters' independent
+       of the parent, that just created duplication.
+
+2023-12-07  Dmitry Gutov  <dmitry@gutov.dev>
+
+       (js--treesit-font-lock-settings): Remove some duplicates
+
+       * lisp/progmodes/js.el (js--treesit-font-lock-settings):
+       Remove queries from 'function' that duplicate entries in
+       'definition' (one of them with a typo).
+
+2023-12-04  Philipp Stephani  <p.stephani2@gmail.com>
+
+       Don't claim to signal an error when deleting a nonexisting file.
+
+       The behavior has changed in commit
+       1a65afb7ecc2a52127d6164bad19313440237f9d to no longer signal an error
+       on ENOENT.
+
+       * doc/lispref/files.texi (Changing Files): Fix documentation about
+       error reporting.
+
+2023-12-04  Eli Zaretskii  <eliz@gnu.org>
+
+       * lisp/indent.el (indent-rigidly): Improve prompt (bug#67620).
+
+2023-12-03  Christophe Troestler  <Christophe.Troestler@umons.ac.be>
+
+       rust-ts-mode--comment-docstring: Handle block doc comments
+
+       * lisp/progmodes/rust-ts-mode.el
+       (rust-ts-mode--comment-docstring): Handle block doc comments.
+       Inhibit match-data modification.
+
+2023-12-02  Christophe TROESTLER  <Christophe.TROESTLER@umons.ac.be>
+
+       rust-ts-mode--comment-docstring: Fix/improve the previous change
+
+       * lisp/progmodes/rust-ts-mode.el
+       (rust-ts-mode--comment-docstring): Match also "inner" line docs.
+       Stop rebinding 'end' and use the argument's value in the
+       'treesit-fontify-with-override' call.
+
+2023-12-02  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix 'Info-goto-node-web' when NODE is given in various forms
+
+       * lisp/info.el (Info-goto-node-web): Support all forms of node
+       input, per 'Info-read-node-name's documentation, and extract
+       FILENAME from NODE if given there.  Default NODE to "Top" if not
+       provided by the user.  (Bug#67531)
+       (Info-url-for-node): Support browsing the "Top" node.
+
+2023-12-02  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix setting cursor when the window's op line has 'line-prefix'
+
+       * src/xdisp.c (set_cursor_from_row): Skip glyphs that come from a
+       string if their 'avoid_cursor_p' flag is set.  (Bug#67486)
+
+2023-12-02  Xiyue Deng  <manphiz@gmail.com>  (tiny change)
+
+       Drop extra parenthesis in example code in Emacs Lisp Introduction
+
+       * doc/lispintro/emacs-lisp-intro.texi (Small buffer case): Drop
+       trailing unmatched parenthesis.  (Bug#67576)
+
+2023-12-01  Christophe Troestler  <Christophe.Troestler@umons.ac.be>
+
+       rust-ts-mode: appropriately fontify doc strings
+
+       * lisp/progmodes/rust-ts-mode.el
+       (rust-ts-mode--comment-docstring): New function.
+       (rust-ts-mode--font-lock-settings): Use it
+       (https://lists.gnu.org/archive/html/emacs-devel/2023-12/msg00019.html).
+
+2023-12-01  Xiyue Deng  <manphiz@gmail.com>  (tiny change)
+
+       Fix example code in Emacs Lisp Introduction manual
+
+       * doc/lispintro/emacs-lisp-intro.texi (Optional Arguments): Fix
+       indentation in an example.  (Bug#67559)
+
+2023-12-01  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix example in Emacs Lisp Intro manual
+
+       * doc/lispintro/emacs-lisp-intro.texi (beginning-of-buffer opt
+       arg): Fix indentation in example.  Reported by Xiyue Deng
+       <manphiz@gmail.com>.  (Bug#67560)
+
+2023-12-01  Jeremy Bryant  <jb@jeremybryant.net>
+
+       Elisp manual: Mention 'write-region' for saving the buffer
+
+       * doc/emacs/files.texi (Save Commands):  Mention
+       'write-region'.  (Bug#67313)
+
+2023-11-30  Michael Albinus  <michael.albinus@gmx.de>
+
+       Document, that PROCESS of signal-process can be a string
+
+       * doc/lispref/processes.texi (Signals to Processes) [signal-process]:
+       * src/process.c (Fsignal_process): Document, that PROCESS can be a
+       string.
+
+2023-11-29  nverno  <noah.v.peart@gmail.com>
+
+       Fix typescript-ts-mode indentation for switch statements
+
+       * lisp/progmodes/typescript-ts-mode.el (typescript-ts-mode): Add
+       indentation rule for switch case and default keywords.  (Bug#67488)
+
+2023-11-29  Aymeric Agon-Rambosson  <aymeric.agon@yandex.com>  (tiny change)
+
+       Repair `tab-first-completion` (bug#67158)
+
+
+       * lisp/indent.el (indent-for-tab-command): Use `syntax-class` to fix
+       longstanding thinko introduced back in 2020 in commit 64c851166442.
+       Rework the check for `syn` because TAB always completed when
+       `tab-first-completion` had value `word-or-paren` or 
`word-or-paren-or-punct`.
+
+       (cherry picked from commit c20226a1ef5fbdfd3e71e2ef8654ee19994c0f2f)
+
+2023-11-29  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix behavior of 'split-root-window-*' with 'C-u'
+
+       * lisp/window.el (split-root-window-below)
+       (split-root-window-right): Fix the 'interactive' form to work with
+       raw 'C-u' as well.  (Bug#67459)
+       (split-window-below, split-window-right, split-root-window-below)
+       (split-root-window-right): Doc fix.
+
+2023-11-29  Xiyue Deng  <manphiz@gmail.com>  (tiny change)
+
+       Add more text to clarify the behavior of 'with-current-buffer'
+
+       * doc/lispintro/emacs-lisp-intro.texi (copy-to-buffer): Expand
+       description of 'with-current-buffer'.  (Bug#67521)
+
+2023-11-27  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix example in Emacs user manual
+
+       * doc/emacs/custom.texi (Init Rebinding): Fix syntax of example.
+       Reported by silarakta <silarakta@protonmail.com>.  (Bug#67474)
+
+2023-11-27  Michael Albinus  <michael.albinus@gmx.de>
+
+       Mention Titankey in Tramp, which has passed the tests
+
+       * doc/misc/tramp.texi (Frequently Asked Questions):
+       * lisp/net/tramp.el (tramp-security-key-confirm-regexp):
+       Mention also Titankey.
+
+2023-11-26  Yuan Fu  <casouri@gmail.com>
+
+       Fix c-ts-mode indentation after if/else (bug#67417)
+
+       * lisp/progmodes/c-ts-mode.el:
+       (c-ts-mode--prev-line-match): New function.
+       (c-ts-mode--indent-styles): Add a rule for the empty line after
+       if/else/for/etc.
+
+2023-11-26  Yuan Fu  <casouri@gmail.com>
+
+       Fix indentation for else clause in c-ts-mode (bug#67417)
+
+       * lisp/progmodes/c-ts-mode.el:
+       (c-ts-mode--indent-styles): Add indentation for children of
+       else_clause.
+       * test/lisp/progmodes/c-ts-mode-resources/indent.erts:
+       (Name): Add test for else-break.  Also make the test such that it
+       needs to indent correctly from scratch (rather than maintaining the
+       already correct indentation.)
+
+2023-11-26  Joseph Turner  <joseph@breatheoutbreathe.in>
+
+       Ensure that directory is expanded in package-vc-checkout
+
+       * lisp/emacs-lisp/package-vc.el (package-vc-checkout): Expand
+       DIRECTORY.  (Bug#66115)
+
+2023-11-25  Ulrich Müller  <ulm@gentoo.org>
+
+       * etc/PROBLEMS: Add entry about pinentry with gpgsm.  (Bug#67012)
+
+2023-11-24  nverno  <noah.v.peart@gmail.com>
+
+       typescript-ts-mode: Add missing 'operator' to treesit-font-lock-features
+
+       * lisp/progmodes/typescript-ts-mode.el (typescript-ts-mode):
+       Add operator to treesit-font-lock-feature-list (bug#67433).
+
+2023-11-24  Michael Albinus  <michael.albinus@gmx.de>
+
+       Extend D-Bus doc and test
+
+       * doc/misc/dbus.texi (Register Objects): Adapt doc of
+       dbus-unregister-service.
+
+       * test/lisp/net/dbus-tests.el (dbus--test-register-service):
+       Extend test.
+
+2023-11-24  Michael Albinus  <michael.albinus@gmx.de>
+
+       Do not unregister a D-Bus service which is a unique name
+
+       * lisp/net/dbus.el (dbus-unregister-service): Check, whether
+       SERVICE is a known name.  (Bug#67386)
+
+2023-11-24  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix byte-compilation warnings about 'sqlite-rollback'
+
+       * lisp/sqlite.el (sqlite-transaction, sqlite-commit)
+       (sqlite-rollback): Declare.
+       * lisp/emacs-lisp/multisession.el (sqlite-commit)
+       (sqlite-transaction): Remove declaration.
+
+2023-11-23  Dmitry Gutov  <dmitry@gutov.dev>
+
+       Make python-ts-mode's syntax-highlighting more standardized
+
+       This was brought up in a Reddit discussion.
+
+       * lisp/progmodes/python.el (python--treesit-fontify-variable):
+       Use font-lock-variable-use-face (since it applies to references).
+       (python-ts-mode): Move 'property' from 3rd to 4th
+       treesit-font-lock-level.
+
+2023-11-23  George Kuzler  <gkuzler@gmail.com>  (tiny change)
+
+       Fix "Text is read-only" on backspacing initial Calc input
+
+       Immediately after `calc-mode' opens the minibuffer for input
+       (because you typed a digit, "e", etc), pressing backspace
+       should clear the minibuffer and return you to the *Calculator*
+       buffer.  Instead, it leaves the minibuffer as-is and prints the
+       message "Text is read-only"; this is because the function used,
+       `erase-buffer', tries to erase the read-only minibuffer prompt.
+       Using `delete-minibuffer-contents' fixes this, since it doesn't
+       attempt to delete the prompt.
+       * lisp/calc/calc.el (calcDigit-backspace): Use
+       `delete-minibuffer-contents' instead of `erase-buffer'.  (Bug#67395)
+
+2023-11-23  Jeremy Bryant  <jb@jeremybryant.net>
+
+       Add a doc string to simple.el (bug#67355)
+
+       * lisp/simple.el (kill-buffer--possibly-save): Add doc string.
+
+2023-11-23  Eli Zaretskii  <eliz@gnu.org>
+
+       Mention "visual line" in user manual
+
+       * doc/emacs/display.texi (Visual Line Mode):
+       * doc/emacs/basic.texi (Continuation Lines, Moving Point): Mention
+       "visual line".  (Bug#67382)
+
+2023-11-23  Eli Zaretskii  <eliz@gnu.org>
+
+       Allow listing Emoji from a read-only buffer
+
+       * lisp/international/emoji.el (emoji-list): Don't barf here if the
+       original buffer is read-inly...
+       (emoji-list-select): ...barf here instead.  (Bug#67400)
+       (emoji-list): Doc fix.
+
+2023-11-22  Michael Albinus  <michael.albinus@gmx.de>
+
+       Fix CRLF handling in Tramp (don't merge)
+
+       * lisp/net/tramp-sh.el (tramp-send-command-and-read): Use 'space'
+       instead of 'blank' in rx expression, in order to handle also CR
+       and alike.  Reported by Dominique Quatravaux
+       <dominique@quatravaux.org>.
+
+2023-11-21  Dmitry Gutov  <dmitry@gutov.dev>
+
+       Annotate java-ts-mode-test-movement with expected result
+
+       Do not merge to master.
+
+2023-11-21  Theodor Thornhill  <theo@thornhill.no>
+
+       Backport: Add more java indentation tests
+
+       * test/lisp/progmodes/java-ts-mode-resources/indent.erts: Use default
+       indent offset, and tweak the indentation examples.
+
+       (cherry picked from commit dbe7803aa1e8249bd70f67f25f19aedabeb9cc22)
+
+2023-11-21  Theodor Thornhill  <theo@thornhill.no>
+
+       Backport: Add test for java indentation (bug#61115)
+
+       * test/lisp/progmodes/java-ts-mode-resources/indent.erts: Add new test
+       case.
+
+       (cherry picked from commit 229d0772e235f51812ed8020a31f9a8de366c7ba)
+
+2023-11-21  Noah Peart  <noah.v.peart@gmail.com>
+
+       typescript-ts-mode: Support indentation for conditionals without braces
+
+       * lisp/progmodes/typescript-ts-mode.el
+       (typescript-ts-mode--indent-rules): Support indentation for
+       conditionals without braces (bug#67031).
+
+       * test/lisp/progmodes/typescript-ts-mode-resources/indent.erts
+       (Statement indentation without braces): New test.
+
+2023-11-21  Theodor Thornhill  <theo@thornhill.no>
+
+       Backport: Add some basic tests for java-ts-mode and typescript-ts-mode
+
+       * test/lisp/progmodes/java-ts-mode-resources/indent.erts: New file
+       with tests for indentation.
+       * test/lisp/progmodes/java-ts-mode-resources/movement.erts: New file
+       with tests for movement.
+       * test/lisp/progmodes/java-ts-mode-tests.el: New tests.
+       * test/lisp/progmodes/typescript-ts-mode-resources/indent.erts: New
+       file with tests for indentation.
+       * test/lisp/progmodes/typescript-ts-mode-tests.el: New tests.
+
+       (cherry picked from commit c8dd37b16c574beda900d4ee48ac7b4ab4a2ee56)
+
+2023-11-21  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix 'with-sqlite-transaction' when BODY fails
+
+       * lisp/sqlite.el (with-sqlite-transaction): Don't commit changes
+       if BODY errors out.  Roll back the transaction if committing
+       fails.  (Bug#67142)
+
+       * etc/NEWS:
+       * doc/lispref/text.texi (Database): Document the error handling in
+       'with-sqlite-transaction'.
+
+2023-11-19  Richard Stallman  <rms@gnu.org>
+
+       Fix wording in ELisp Intro manual
+
+       * doc/lispintro/emacs-lisp-intro.texi (Lisp macro): Improve
+       wording in description of 'unless'.  (Bug#67185)
+
+2023-11-18  Yuan Fu  <casouri@gmail.com>
+
+       Add missing python-ts-mode keyword (bug#67015)
+
+       * lisp/progmodes/python.el (python--treesit-keywords): Add "not in".
+
+2023-11-18  Dmitry Gutov  <dmitry@gutov.dev>
+
+       Fix string-pixel-width with global setting of display-line-numbers
+
+       * lisp/emacs-lisp/subr-x.el (string-pixel-width):
+       Instead of checking for display-line-numbers-mode, set the
+       display-line-numbers variable to nil (bug#67248).
+
+2023-11-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Document changes in 'edmacro-parse-keys'
+
+       * lisp/edmacro.el (edmacro-parse-keys): Add a comment for forcing
+       output to be a vector.
+       (read-kbd-macro): Adjust the doc string to changes in
+       'edmacro-parse-keys'.  (Bug#67182)
+
+2023-11-18  Eli Zaretskii  <eliz@gnu.org>
+
+       Add 2 SQLite extensions to allow-list.
+
+       * src/sqlite.c (Fsqlite_load_extension): Add 2 Free Software
+       extensions to the allow-list.  For the details, see
+       https://lists.gnu.org/archive/html/emacs-devel/2023-11/msg00234.html.
+
+2023-11-17  Michael Albinus  <michael.albinus@gmx.de>
+
+       * test/lisp/net/tramp-tests.el (tramp--test-timeout-handler): Be more 
verbose.
+
+2023-11-17  Michael Albinus  <michael.albinus@gmx.de>
+
+       Make Tramp aware of completion-regexp-list (don't merge)
+
+       * lisp/net/tramp.el (tramp-skeleton-file-name-all-completions):
+       New defmacro.
+       (tramp-completion-handle-file-name-all-completions):
+       * lisp/net/tramp-adb.el (tramp-adb-handle-file-name-all-completions):
+       * lisp/net/tramp-crypt.el 
(tramp-crypt-handle-file-name-all-completions):
+       * lisp/net/tramp-fuse.el (tramp-fuse-handle-file-name-all-completions):
+       * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-name-all-completions):
+       * lisp/net/tramp-sh.el (tramp-sh-handle-file-name-all-completions):
+       * lisp/net/tramp-smb.el (tramp-smb-handle-file-name-all-completions):
+       * lisp/net/tramp-sudoedit.el
+       (tramp-sudoedit-handle-file-name-all-completions): Use it.
+
+2023-11-17  Jeremy Bryant  <jb@jeremybryant.net>
+
+       Add 5 docstrings to abbrev.el (bug#67153)
+
+       * lisp/abbrev.el (prepare-abbrev-list-buffer, add-abbrev)
+       (inverse-add-abbrev, abbrev--describe)
+       (abbrev--possibly-save): Add doc strings.
+
+2023-11-15  Morgan Smith  <Morgan.J.Smith@outlook.com>
+
+       Fix CBZ file detection in doc-view-mode
+
+       * lisp/doc-view.el (doc-view-set-doc-type): Fix CBZ file
+       detection.  (Bug#67133)
+
+       This fix is almost identical to the previous fix for ODF file
+       detection in bug#54947 which resulted in commit
+       b3ff4905388834994ff26d9d033d6bc62b094c1c
+
+2023-11-15  João Távora  <joaotavora@gmail.com>
+
+       * lisp/progmodes/eglot.el (eglot-server-programs): Fix previous commit.
+
+       (cherry picked from commit 58d9e735e721ecf0187a5e15eefc7641112ace0b)
+
+2023-11-14  João Távora  <joaotavora@gmail.com>
+
+       Eglot: Send standard :language-id for typescript-language-server
+
+       bug#67150
+
+       * lisp/progmodes/eglot.el (eglot-server-programs): Update
+       language-id for languages handled by typescript-language-server.
+
+       (cherry picked from commit 1fe949888057b0275da041288709bd5690501974)
+
+2023-11-14  Zajcev Evgeny  <zevlg@yandex.ru>
+
+       Typofix in the doc/lispref/modes.texi
+
+2023-11-14  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix spell-checking email message with citations
+
+       This became broken 7 years ago, when the 'boundp condition was
+       removed, and with it an important unrelated part of the code.
+       * lisp/textmodes/ispell.el (ispell-message): Fix cite-regexp.
+
+2023-11-12  Xiaoyue Chen  <xchen@vvvu.org>  (tiny change)
+
+       Pass only the local parts of Eshell's $PATH to 'tramp-remote-path'
+
+       * lisp/eshell/esh-proc.el (eshell-gather-process-output): Get the
+       local part of the $PATH (bug#67126).
+
+       Do not merge to master.
+
+2023-11-12  Jeremy Bryant  <jb@jeremybryant.net>
+
+       Add two doc strings to cl-extra.el
+
+       * lisp/emacs-lisp/cl-extra.el (cl--random-time)
+       (cl-find-class): Add docstrings.  (Bug#66949)
+
+2023-11-11  Eli Zaretskii  <eliz@gnu.org>
+
+       Improve documentation of read syntax and printed representation
+
+       * doc/lispref/objects.texi (Syntax for Strings): Describe in more
+       detail how to specify special characters in string literals.
+       (Printed Representation, Character Type, Nonprinting Characters):
+       Improve information and add cross-references about printed
+       representation and read syntax.  (Bug#67033)
+
+2023-11-09  Eli Zaretskii  <eliz@gnu.org>
+
+       Improve documentation of signaling errors in batch mode
+
+       * doc/lispref/control.texi (Signaling Errors)
+       (Processing of Errors):
+       * doc/lispref/os.texi (Batch Mode):
+       * doc/lispref/debugging.texi (Invoking the Debugger):
+       * lisp/emacs-lisp/debug.el (debug):
+       * src/eval.c (Fsignal):
+       * lisp/subr.el (error): Document more prominently that signaling
+       an unhandled error in batch mode kills Emacs.  Better
+       documentation of backtrace in batch mode.
+
+2023-11-09  Yuan Fu  <casouri@gmail.com>
+
+       Fix treesit-simple-indent-presets docstring (bug#67007)
+
+       * lisp/treesit.el (treesit-simple-indent-presets): Fix docstring.
+       * doc/lispref/modes.texi (Parser-based Indentation): Fix example.
+
+2023-11-08  Stephen Berman  <stephen.berman@gmx.net>
+
+       Prevent an infinite loop in todo-mode (bug#66994)
+
+       * lisp/calendar/todo-mode.el (todo-item-start): Moving an item to
+       a todo file (with `C-u m') that had not yet been read into a
+       buffer puts point at the beginning of the file, from where it is
+       impossible to reach todo-item-start by this function, so don't try
+       in that case.
+
+2023-11-08  Randy Taylor  <dev@rjt.dev>
+
+       Fix cmake-ts-mode indentation (Bug#66845)
+
+       * lisp/progmodes/cmake-ts-mode.el (cmake-ts-mode--indent-rules):
+       Support versions v0.3.0 and v0.4.0 of the grammar.
+       (cmake-ts-mode--font-lock-compatibility-fe9b5e0): Fix docstring.
+
+2023-11-05  Kyle Meyer  <kyle@kyleam.com>
+
+       Update to Org 9.6.11
+
+2023-11-04  Mattias Engdegård  <mattiase@acm.org>
+
+       Suggest alternative reason for ERT test duplication error
+
+       * lisp/emacs-lisp/ert.el (ert-set-test): Amend error message;
+       maybe the redefinition was caused by a file loaded twice.
+       (Bug#66782)
+
+       Suggested by Xiyue Deng.
+
+       (cherry picked from commit 425d23fbeaede81ab4f50b4073949cc1c8a3fbd0)
+
+2023-11-04  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix description of 'Package-Requires' library header
+
+       * doc/lispref/tips.texi (Library Headers): Update the description
+       of the 'Package-Requires' header.  (Bug#66677)
+
+2023-10-30  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       * lisp/emacs-lisp/cl-lib.el (cl--defalias): Improve&fix docstring
+
+2023-10-30  Jeremy Bryant  <jb@jeremybryant.net>
+
+       Add two docstrings in cl-lib.el
+
+       * lisp/emacs-lisp/cl-lib.el (cl--set-buffer-substring)
+       (cl--defalias): Add docstrings.  (Bug#66828)
+
+2023-10-27  Michael Albinus  <michael.albinus@gmx.de>
+
+       Fix Tramp (don't merge)
+
+       * lisp/net/tramp.el (tramp-read-id-output): Identifiers can contain "-".
+
+2023-10-26  Michael Albinus  <michael.albinus@gmx.de>
+
+       * doc/misc/tramp.texi (Traces and Profiles): Fix indentation.  (don't 
merge)
+
+2023-10-25  Michael Albinus  <michael.albinus@gmx.de>
+
+       * doc/misc/tramp.texi (Traces and Profiles): Fix indentation.  (Don't 
merge)
+
+2023-10-25  Eli Zaretskii  <eliz@gnu.org>
+
+       Fix guessing commands for zstandard archives in Dired
+
+       * lisp/dired-aux.el (dired-guess-shell-alist-default): Fix
+       zstdandard commands.  (Bug#66532)
+
+2023-10-25  Matthew Woodcraft  <matthew@woodcraft.me.uk>  (tiny change)
+
+       Fix eglot.texi (JSONRPC objects in Elisp) example
+
+       * doc/misc/eglot.texi (JSONRPC objects in Elisp): Correct the
+       example.  (Bug#66569)
+
+2023-10-25  Michael Albinus  <michael.albinus@gmx.de>
+
+       * doc/man/emacsclient.1: Fix --tramp option.
+
+2023-10-24  Stefan Kangas  <stefankangas@gmail.com>
+
+       Improve `nsm-protocol-check--3des-cipher` docstring
+
+       * lisp/net/nsm.el (nsm-protocol-check--3des-cipher): Update
+       docstring to reflect current NIST policy.
+
+2023-10-24  Lassi Kortela  <lassi@lassi.io>
+
+       Recognize backslash in `dns-mode` quoted values
+
+       * lisp/textmodes/dns-mode.el (dns-mode-syntax-table): Recognize
+       backslash as an escape character.  (Bug#66660)
+
+       (cherry picked from commit e6f05e189db73a0f0b29f987381ffef61a409232)
+
+2023-10-24  Stefan Kangas  <stefankangas@gmail.com>
+
+       Make `dns-mode` fontify quoted values correctly
+
+       * lisp/textmodes/dns-mode.el (dns-mode-syntax-table): Fontify
+       quoted values correctly.  (Bug#62214)
+       Suggested by Trent W. Buck <trentbuck@gmail.com>.
+
+       (cherry picked from commit c586d984f279aa61de4f5dfc4f6df660188dd0f6)
+
+2023-10-23  Stefan Kangas  <stefankangas@gmail.com>
+
+       Change news.gmane.org to news.gmane.io
+
+       * admin/notes/emba:
+       * doc/misc/gnus.texi (Group Parameters)
+       (Non-ASCII Group Names, Filling In Threads)
+       (Selection Groups, Spam Package Configuration Examples)
+       (Terminology):
+       * lisp/gnus/gnus-group.el (gnus-useful-groups):
+       * lisp/gnus/gnus-sum.el (gnus-fetch-old-headers):
+       * lisp/gnus/spam-report.el (spam-report-gmane-use-article-number)
+       (spam-report-gmane-internal):
+       * test/lisp/gnus/gnus-group-tests.el (gnus-short-group-name):
+       Change news.gmane.org to news.gmane.io.
+       Ref: https://news.gmane.io/
+
+2023-10-23  Mauro Aranda  <maurooaranda@gmail.com>
+
+       Fix minor defcustom issues in Gnus (Bug#66715)
+
+       * lisp/gnus/gnus-art.el (gnus-button-prefer-mid-or-mail): Allow
+       function and add :tag to const values.
+       * lisp/gnus/gnus-bookmark.el (gnus-bookmark-bookmark-inline-details):
+       Fix docstring.
+       * lisp/gnus/gnus-sum.el (gnus-simplify-subject-fuzzy-regexp): Allow a
+       single regexp as value.
+       * lisp/gnus/message.el (message-indent-citation-function): Allow a
+       single function as value.
+       (message-mail-alias-type): Allow for a list of options as value.
+       (message-dont-reply-to-names): Allow a function as value.
+       * lisp/gnus/spam-report.el (spam-report-url-ping-function): Fix
+       default value for the function widget.
+
+2023-10-23  Michael Albinus  <michael.albinus@gmx.de>
+
+       Minor connection-local variables fixes
+
+       * doc/emacs/custom.texi (Connection Variables): Warn about
+       specifying the same variable twice.
+
+       * lisp/files-x.el (connection-local-get-profiles): Normalize criteria.
+
+2023-10-23  Stefan Kangas  <stefankangas@gmail.com>
+
+       Make Dired honor `insert-directory-program´ with globs
+
+       Starting with commit 6f6639d6ed6c6314b2643f6c22498fc2e23d34c7
+       (Bug#27631), Dired stopped respecting the value of
+       'insert-directory-program' when using directory wildcards/globs.
+
+       * lisp/dired.el (dired-insert-directory): Honor the value of
+       'insert-directory-program' when using directory wildcards.
+
+2023-10-22  Morgan J. Smith  <Morgan.J.Smith@outlook.com>
+
+       Fix typo in url-privacy-level :type
+
+       * lisp/url/url-vars.el (url-privacy-level): Fix typo in
+       :type.  (Bug#66613)
+
+2023-10-22  Juri Linkov  <juri@linkov.net>
+
+       * lisp/vc/log-view.el (log-view-mode-menu): Quote derived modes 
(bug#66686).
+
+2023-10-22  Petteri Hintsanen  <petterih@iki.fi>
+
+       * lisp/tab-bar.el: Fix the close button with auto-width (bug#66678).
+
+       (tab-bar-auto-width): Take into account the length of 
tab-bar-close-button
+       more than one character: " x".
+       Don't merge to master.
+
+2023-10-22  Mauro Aranda  <maurooaranda@gmail.com>
+
+       Fix State button for customize-icon (Bug#66635)
+
+       * lisp/cus-edit.el (custom-icon-action): New function.
+       (custom-icon): Use it as the :action.  Otherwise, clicking the State
+       button is a noop.  Remove irrelevant stuff from the docstring and
+       comment out some copy-pasta.
+       (custom-icon-extended-menu): New variable, the menu to show upon
+       :action.
+       (custom-icon-set): Really redraw the widget with the new settings.
+       Comment out strange call to custom-variable-backup-value.
+       (custom-icon-save): New function.
+
+       * lisp/emacs-lisp/icons.el (icons--merge-spec): Fix call to plist-get
+       and avoid infloop.
+
+2023-10-22  Yuan Fu  <casouri@gmail.com>
+
+       Fix the use of adaptive-fill-regexp in treesit indent preset
+
+       * lisp/treesit.el (treesit-simple-indent-presets):
+       adaptive-fill-regexp don't have a capture group (the group in the
+       default value is supposed to be a non-capture group), so don't use the
+       group. Also, in the second diff hunk, replace looking-at with
+       looking-at-p so it doesn't override match data that we use later.
+
+2023-10-21  nverno  <noah.v.peart@gmail.com>
+
+       Fix treesit-install-language-grammar (bug#66673)
+
+       * lisp/treesit.el (treesit-install-language-grammar): Take out the
+       language symbol when storing the recipe.
+
+2023-10-21  Yuan Fu  <casouri@gmail.com>
+
+       Fix treesit-explore-mode (bug#66431)
+
+       * lisp/treesit.el (treesit-explore-mode): Reset
+       treesit--explorer-last-node before calling treesit--explorer-refresh,
+       so that in the rare case described in the bug report, the explorer
+       buffer don't show the outdated node.
+
+2023-10-21  Dmitry Gutov  <dmitry@gutov.dev>
+
+       tsx-ts-mode--font-lock-compatibility-bb1f97b: Re-fix the previous fix
+
+       * lisp/progmodes/typescript-ts-mode.el
+       (tsx-ts-mode--font-lock-compatibility-bb1f97b): Make sure the
+       tested query is actually valid in the new grammar (bug#66646).
+
+2023-10-19  Michael Albinus  <michael.albinus@gmx.de>
+
+       Update Tramp version (don't merge with master)
+
+       * doc/misc/trampver.texi:
+       * lisp/net/trampver.el: Change version to "2.6.2.29.2".
+       (customize-package-emacs-version-alist):
+       Adapt Tramp version integrated in Emacs 29.2.
+
+2023-10-19  Eli Zaretskii  <eliz@gnu.org>
+
+       Bump Emacs version
+
+       * README:
+       * configure.ac:
+       * msdos/sed2v2.inp:
+       * nt/README.W32: Bump Emacs version to 29.1.90.
+
 2023-10-16  Po Lu  <luangruo@yahoo.com>
 
        Correctly register focus events concomitant with alpha changes
@@ -374,7 +1927,7 @@
        Ensure ucs-names is consistent with Unicode names
 
        * lisp/international/mule-cmds.el (ucs-names): Skip adding an old-name
-       if it conflicts with the offical name of a codepoint.  Adjust the
+       if it conflicts with the official name of a codepoint.  Adjust the
        ranges iterated over to account for new Unicode codepoints.
        * test/lisp/international/mule-tests.el
        (mule-cmds-tests--ucs-names-old-name-override,
@@ -1705,7 +3258,7 @@
        (tramp-archive-test47-auto-load): Adapt test.
 
        * test/lisp/net/tramp-tests.el (tramp-display-escape-sequence-regexp):
-       Dont't declare.
+       Don't declare.
        (tramp-action-yesno): Suppress run in tests.
        (tramp-test02-file-name-dissect):
        (tramp-test02-file-name-dissect-simplified)
@@ -2155,7 +3708,7 @@
        selection from hanging owner, we will proceed to take ownership of the
        selection as normal, resolving the problem.
 
-       (One example of a selction owner that might not be responding to
+       (One example of a selection owner that might not be responding to
        selection requests is another instance of Emacs itself; while Emacs is
        blocked in call-process or Lisp execution, it currently does not
        respond to selection requests.)
@@ -3050,7 +4603,7 @@
        Revert changes to the order in which package descs are loaded
 
        * lisp/emacs-lisp/package.el (package-load-all-descriptors):  Remove
-       NOSORT argument to 'directory-files', reverting back to the behaviour
+       NOSORT argument to 'directory-files', reverting back to the behavior
        as of Emacs 28.  (Bug#63757)
 
 2023-06-04  Spencer Baugh  <sbaugh@janestreet.com>
@@ -3233,7 +4786,7 @@
        (plstore-save, plstore--encode, plstore--decode)
        (plstore--write-contents-functions, plstore-mode-decoded)
        (plstore-mode): Brush up doc strings and documentation in general.
-       Fix terminology, in particular spurious occurences of all uppercase
+       Fix terminology, in particular spurious occurrences of all uppercase
        "PLSTORE".  (Bug#63627)
 
 2023-05-31  Jens Schmidt  <jschmidt4gnu@vodafonemail.de>
@@ -4198,7 +5751,7 @@
        Prevent generating empty autoload files
 
        * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate): Remove
-       optimisation that would mistakenly discard old loaddefs in case a file
+       optimization that would mistakenly discard old loaddefs in case a file
        was not modified by EXTRA-DATA is non-nil.  (Bug#62734)
 
 2023-04-30  Stefan Monnier  <monnier@iro.umontreal.ca>
@@ -5415,7 +6968,7 @@
 
 2023-03-29  Andrea Corallo  <akrl@sdf.org>
 
-       Comp fix calls to redefined primtives with op-bytecode (bug#61917)
+       Comp fix calls to redefined primitives with op-bytecode (bug#61917)
 
                * test/src/comp-tests.el (61917-1): New test.
                * src/comp.c (syms_of_comp): New variable.
@@ -5453,7 +7006,7 @@
 
 2023-03-28  Andrea Corallo  <akrl@sdf.org>
 
-       Revert "Comp fix calls to redefined primtives with op-bytecode 
(bug#61917)"
+       Revert "Comp fix calls to redefined primitives with op-bytecode 
(bug#61917)"
 
        This reverts commit 263d6c38539691c954f4c3057cbe8d5468499b91.
 
@@ -5791,10 +7344,10 @@
 
 2023-03-20  Andrea Corallo  <akrl@sdf.org>
 
-       Comp fix calls to redefined primtives with op-bytecode (bug#61917)
+       Comp fix calls to redefined primitives with op-bytecode (bug#61917)
 
        * lisp/emacs-lisp/comp.el (comp-emit-set-call-subr): Fix compilation
-       of calls to redefined primtives with dedicated op-bytecode.
+       of calls to redefined primitives with dedicated op-bytecode.
        * test/src/comp-tests.el (61917-1): New test.
 
 2023-03-20  Robert Pluim  <rpluim@gmail.com>
@@ -5914,7 +7467,7 @@
        CC Mode: Eliminate duplicate function c-list-of-strings
 
        Replace it with the existing c-string-list-p.  Also put an autoload 
cookie in
-       front of c-string-list-p so that it will not be signalled as undefined 
by
+       front of c-string-list-p so that it will not be signaled as undefined by
        loaddefs.el.
 
        lisp/progmodes/cc-vars.el (c-string-list-p): Make this autoload.
@@ -5932,7 +7485,7 @@
        (c-font-lock-extra-types, c++-font-lock-extra-types)
        (objc-font-lock-extra-types, java-font-lock-extra-types)
        (idl-font-lock-extra-types, pike-font-lock-extra-types): Add a :safe 
entry
-       into each of thes defcustoms for c-list-of-string.
+       into each of these defcustoms for c-list-of-string.
        (Top level): Add an autoload entry for each of the above.
 
 2023-03-18  Robert Pluim  <rpluim@gmail.com>
@@ -5955,7 +7508,7 @@
 
        Enhance section about troubleshooting in Eglot manual.
 
-       * doc/misc/eglot.texi (Troubleshooting Eglot): Parially rewrite.
+       * doc/misc/eglot.texi (Troubleshooting Eglot): Partially rewrite.
 
 2023-03-17  João Távora  <joaotavora@gmail.com>
 
@@ -5965,8 +7518,8 @@
        Before this change, it would only work if the user happened to have
        manually activated it before with 'yas-global-mode' or somesuch.
 
-       This makes Eglot's Yasnippet-activating behaviour similar to its
-       Flymake-activating behaviour.
+       This makes Eglot's Yasnippet-activating behavior similar to its
+       Flymake-activating behavior.
 
        * lisp/progmodes/eglot.el (eglot-client-capabilities): Consult
        eglot--stay-out-of.
@@ -6405,7 +7958,7 @@
 
 2023-03-09  João Távora  <joaotavora@gmail.com>
 
-       Autoload Eglot helper funtion eglot--debbugs-or-github-bug-uri
+       Autoload Eglot helper function eglot--debbugs-or-github-bug-uri
 
        This isn't a typical autoload: the progn block is plced in the
        autoloads file, but the eglot.el file itself isn't loaded as a result
@@ -6619,7 +8172,7 @@
 
        For example, in the 'buffer' category, the default value has the
        styles list '(basic substring)'.  This means that if a pattern matches
-       accoring to the 'basic' style, 'substring' will not be tried.  And
+       according to the 'basic' style, 'substring' will not be tried.  And
        neither will 'completion-styles' which in Fido mode's case happens to
        be 'flex'.
 
@@ -6635,7 +8188,7 @@
        * Fix `emacs-lisp-native-compile-and-load' for (bug#61917)
 
        * lisp/progmodes/elisp-mode.el (emacs-lisp-native-compile-and-load):
-       Don't load if no compialtion happened.
+       Don't load if no compilation happened.
 
 2023-03-06  Andrea Corallo  <akrl@sdf.org>
 
@@ -6750,7 +8303,7 @@
        "unspoffing" HOME just for the invocations of LSP server but it
        stopped working a while back.  So make it more robust.
 
-       Eventually, we'll want to decide wether these local servers should be
+       Eventually, we'll want to decide whether these local servers should be
        considered in 'make check' runs at all, or whether there is a way to
        use them with a spoofed HOME.
 
@@ -6835,7 +8388,7 @@
        Fix go-ts-mode multi-line string indentation (bug#61923)
 
        * lisp/progmodes/go-ts-mode.el:
-       (go-ts-mode--indent-rules): Add indent rule for multi-line sting.
+       (go-ts-mode--indent-rules): Add indent rule for multi-line string.
 
 2023-03-03  João Távora  <joaotavora@gmail.com>
 
@@ -6935,7 +8488,7 @@
 
        Originally our c-ts-mode--anchor-prev-sibling only specially handled
        labeled_statements, now we add special case for preproc in the similar
-       fasion: instead of using the preproc directive as anchor, use the last
+       fashion: instead of using the preproc directive as anchor, use the last
        statement in that preproc as the anchor. Thus effectively ignore the
        preproc.
 
@@ -6988,7 +8541,7 @@
        ([XwWebView initWithFrame:configuration:xwidget:])
        (nsxwidget_init):  Fixed memory leaks: when sending an alloc
        message to an object, send an autorelease message to any objects
-       we won't explictly release.
+       we won't explicitly release.
        ([XwWebView webView:didFinishNavigation:]): Second string to
        store in 'store_xwidget_event_string' is "load finished" rather
        than empty string.
@@ -7658,7 +9211,7 @@
        Eglot doesn't always show the LSP :label property of a CompletionItem
        in the completion candidates.  That is because label is sometimes not
        what should be inserted in the buffer in the end, the :insertText
-       property supercedes it.
+       property supersedes it.
 
        But the label is usually more suitable for display nevertheless and if
        the LSP CompletionItem contains either a snippet or a textEdit, it's
@@ -7720,7 +9273,7 @@
        occurs.  This is a much simpler mode of operation which may avoid
        problems, but is also likely much slower in large buffers.
 
-       Also, because the inlay feature is probably visually suprising to
+       Also, because the inlay feature is probably visually surprising to
        some, it is turned OFF by default, which is not the usual practice of
        Eglot (at least not when the necessary infrastructure is present).
        This decision may be changed soon.  Here's a good one-liner for
@@ -7731,7 +9284,7 @@
        I haven't tested inlay hints extensively across many LSP servers, so I
        would appreciate any testing, both for functional edge cases and
        regarding performance.  There are possibly more optimization
-       oportunities in the "lazy" mode of operation, like more aggressively
+       opportunities in the "lazy" mode of operation, like more aggressively
        deleting buffer overlays that are not in visible parts of the buffer.
 
        Though I ended up writing this one from scratch, I want to thank
@@ -7803,9 +9356,9 @@
 
        In that commit, I did what many longstanding issues and users were
        suggesting and removed Eglot's override of two Eldoc user
-       configuration varibles.
+       configuration variables.
 
-       I verified that Eglot's behaviour would stay mostly unaltered but my
+       I verified that Eglot's behavior would stay mostly unaltered but my
        tests were very incomplete.  In short there is no way that Eglot can
        work acceptably with the default setting of
        'eldoc-documentation-strategy', which is
@@ -8208,7 +9761,7 @@
        Fix 'display-buffer-use-least-recent-window'
 
        * src/window.c (Fwindow_use_time): Doc fix.
-       (Fwindow_bump_use_time): Bump use time of the seleceted window as
+       (Fwindow_bump_use_time): Bump use time of the selected window as
        well.  Doc fix.
 
        * lisp/window.el (display-buffer-avoid-small-windows): Remove.
@@ -8478,7 +10031,7 @@
 
 2023-02-16  Philip Kaludercic  <philipk@posteo.net>
 
-       Attempt to recognise if a VC package has no Elisp files
+       Attempt to recognize if a VC package has no Elisp files
 
        * lisp/emacs-lisp/package-vc.el (package-vc-non-code-file-names): Add
        new variable used to avoid false-positives.
@@ -8792,7 +10345,7 @@
        package specifications have been having issues with package-vc, when
        toggle-on-error is enabled.  In their case, package-vc would raise an
        error in its first invocation, but it would go on working normally
-       afterwards.  As this behaviour is confusing and the user can't do much
+       afterwards.  As this behavior is confusing and the user can't do much
        about a missing elpa-packages.eld to begin with, we satisfy ourselves
        with printing out a message and continuing on.
 
@@ -10316,7 +11869,7 @@
        Fix typo in c-ts-mode (bug#60932)
 
        * lisp/progmodes/c-ts-mode.el (c-ts-mode-indent-block-type-regexp):
-       enumerator, not enumeratior.
+       enumerator, not enumerator.
 
 2023-01-20  Mike Kupfer  <kupfer@rawbw.com>
 
@@ -11160,7 +12713,7 @@
        (treesit_load_language):
        (Ftreesit_pattern_expand):
        (Ftreesit_query_expand):
-       (treesit_eval_predicates): Use new varaibles.
+       (treesit_eval_predicates): Use new variables.
 
        (treesit_check_buffer_size):
        (treesit_compose_query_signal_data):
@@ -11899,7 +13452,7 @@
 
        * lisp/progmodes/ruby-ts-mode.el
        (ruby-ts-add-log-current-function): Fix the case when point is
-       between two methods.  'treesit-node-at' returs the 'def' node of
+       between two methods.  'treesit-node-at' returns the 'def' node of
        the method after point in such case, so it behaved like point was
        inside the method below.
 
@@ -12575,7 +14128,7 @@
 
        * doc/lispref/modes.texi (Imenu): Add manual.
        * doc/lispref/parsing.texi (Tree-sitter major modes): Update manual.
-       * lisp/treesit.el (treesit-simple-imenu-settings): New varaible.
+       * lisp/treesit.el (treesit-simple-imenu-settings): New variable.
        (treesit--simple-imenu-1)
        (treesit-simple-imenu): New functions.
        (treesit-major-mode-setup): Setup Imenu.
@@ -12840,7 +14393,7 @@
        (treesit--top-level-defun): Generalize into treesit--top-level-thing.
        (treesit--navigate-defun): Generalize into treesit--navigate-thing.
        (treesit-thing-at-point): Generalized from treesit-defun-at-point.
-       (treesit-defun-at-point): Use treesit-thing-at-point to do tht work.
+       (treesit-defun-at-point): Use treesit-thing-at-point to do the work.
 
 2022-12-25  Philip Kaludercic  <philipk@posteo.net>
 
@@ -13035,7 +14588,7 @@
        One way to solve it is to go back up the tree if we are at a leaf node
        and still haven't matched the target node.  That's too ugly and
        finicky so I resorted to recursion.  Now one more functions will
-       return give up (treesit_node_parent) if we are in a werid parse tree
+       return give up (treesit_node_parent) if we are in a weird parse tree
        that is super deep.  But since we already kind of give up on this kind
        of parse trees (bug#59426), it doesn't really hurt.
 
@@ -13287,7 +14840,7 @@
 
 2022-12-21  Andrea Corallo  <akrl@sdf.org>
 
-       * Invoke spawed Emacs processes with '-Q' when native compiling 
(bug#60208)
+       * Invoke spawned Emacs processes with '-Q' when native compiling 
(bug#60208)
 
        * lisp/emacs-lisp/comp.el (comp-final): Invoke spawned Emacs with '-Q'.
        (comp-run-async-workers): Likewise.
@@ -13455,7 +15008,7 @@
        Repair setopt test after error demotion to warning
 
        * test/lisp/cus-edit-tests.el (test-setopt):
-       Check for a warrning instead of an error in attempt to call `setopt`
+       Check for a warning instead of an error in attempt to call `setopt`
        with a value that does not match the declared type (bug#60162).
 
 2022-12-18  Dmitry Gutov  <dgutov@yandex.ru>
@@ -13523,13 +15076,13 @@
 
 2022-12-18  Philip Kaludercic  <philipk@posteo.net>
 
-       * lisp/cus-edit.el (setopt--set): Warn instead of rasing an error
+       * lisp/cus-edit.el (setopt--set): Warn instead of raising an error
 
        (Bug#60162)
 
 2022-12-18  Philip Kaludercic  <philipk@posteo.net>
 
-       Allow customising windmove user options with an empty prefix
+       Allow customizing windmove user options with an empty prefix
 
        * lisp/windmove.el (windmove--default-keybindings-type): Handle nil
        as a prefix value.  (Bug#60161)
@@ -13676,7 +15229,7 @@
        Add treesit_assume_true and treesit_cursor_helper
 
        This is part 1 of the change to change node API to cursor API.  See
-       the second part for more detail.  (I splitted the change to make the
+       the second part for more detail.  (I split the change to make the
        diff more sane.)
 
        * src/treesit.c (treesit_assume_true)
@@ -13860,7 +15413,7 @@
 
 2022-12-16  Eli Zaretskii  <eliz@gnu.org>
 
-       Revert "Elide broken but unnecessary `if` optimisations"
+       Revert "Elide broken but unnecessary `if` optimizations"
 
        This reverts commit 13aa376e93564a8cf2ddbbcf0968c6666620db89.
 
@@ -13874,7 +15427,7 @@
        This reverts commit f4b430140f0866f98bbf18b7094348dc64032813.
 
        Please don't install anything on the release branch that is not
-       strictly necessary fro Emacs 29.
+       strictly necessary for Emacs 29.
 
 2022-12-16  Mattias Engdegård  <mattiase@acm.org>
 
@@ -13896,7 +15449,7 @@
 
 2022-12-16  Mattias Engdegård  <mattiase@acm.org>
 
-       Elide broken but unnecessary `if` optimisations
+       Elide broken but unnecessary `if` optimizations
 
        * lisp/emacs-lisp/byte-opt.el (byte-optimize-if):
        Remove explicit clauses purposing to simplify
@@ -14026,7 +15579,7 @@
        1. the client code invoked by its jsonrpc--connection-receive inside
           the process filter callee immediately sends follow-up input to
           process within the same Lisp stack.  This is a common scenario,
-          especially during LSP initialiation sequence used by Eglot, a
+          especially during LSP initialization sequence used by Eglot, a
           jsonrpc.el client.
 
        2. that follow-up message is large enough for process-send-string to
@@ -14442,7 +15995,7 @@
 
        * lisp/emacs-lisp/shortdoc.el (shortdoc--display-function):
        If the parameter of :eval is a string then read, evaluate and print
-       the result.  This was always the intention and is documented behaviour.
+       the result.  This was always the intention and is documented behavior.
 
 2022-12-14  Michael Albinus  <michael.albinus@gmx.de>
 
@@ -14560,7 +16113,7 @@
 
        This new set of functions (and tests) should eliminate
        defun-navigation bugs and limitations we currently have.  This commit
-       doesn't change any existing bahavior: treesit-beginning/end-of-defun
+       doesn't change any existing behavior: treesit-beginning/end-of-defun
        and friends are unchanged.  The plan is to later switch gear and
        replace the current functions with the new ones introduced in this
        change.
@@ -14777,7 +16330,7 @@
        Eglot: allow skipping compile-time warnings about LSP interfaces
 
        * lisp/progmodes/eglot.el (eglot-strict-mode): Add 
'no-unknown-interfaces'.
-       (eglot--check-object): Honour new eglot-strict-mode value.
+       (eglot--check-object): Honor new eglot-strict-mode value.
 
 2022-12-11  Yuan Fu  <casouri@gmail.com>
 
@@ -15023,7 +16576,7 @@
 
        Bring back the project--value-in-dir logic
 
-       Essentialy revert commit 2389158a31b4a12, restoring the changes
+       Essentially revert commit 2389158a31b4a12, restoring the changes
        and fixing the conflicts.  Motivated by the problem brought up in
        bug#59722 (behavior of project-find-files/regexp when switching
        projects).  We should find other ways to improve performance.
@@ -15400,10 +16953,10 @@
        table.
 
        When the 'external' is in use, the usual styles configured by the user
-       or other in 'completion-styles' are completely overriden.  This
+       or other in 'completion-styles' are completely overridden.  This
        relatively minor inconvenience is the price to pay for responsive
        completion where the full set of completion candidates doesn't need to
-       be transfered into Emacs's address space.
+       be transferred into Emacs's address space.
 
        * lisp/external-completion.el: New file.
 
@@ -15521,7 +17074,7 @@
 
 2022-12-06  Mattias Engdegård  <mattiase@acm.org>
 
-       Lisp reader undefined behaviour excision
+       Lisp reader undefined behavior excision
 
        * src/lread.c (read_bool_vector, skip_lazy_string):
        Replace `|` with `||` to explicitly introduce sequence points since
@@ -15668,7 +17221,7 @@
 
 2022-12-03  Mattias Engdegård  <mattiase@acm.org>
 
-       Speed up Unicode normalisation tests by a factor of 5
+       Speed up Unicode normalization tests by a factor of 5
 
        After this change, ucs-normalize-tests are still very slow but
        somewhat less disastrously so (from 100 to 20 min on this machine).
@@ -15828,10 +17381,10 @@
        be as correct as possible we enable using both.
 
        * lisp/progmodes/typescript-ts-mode.el
-       (typescript-ts-mode--indent-rules): Change to a function to accomodate
+       (typescript-ts-mode--indent-rules): Change to a function to accommodate
        the two languages.
        (typescript-ts-mode--font-lock-settings): Change to a function to
-       accomodate the two languages.
+       accommodate the two languages.
        (typescript-ts-base-mode): Parent mode for typescript-ts-mode
        and tsx-ts-mode.
        (typescript-ts-mode): Derive from typescript-ts-base-mode and
@@ -16842,7 +18395,7 @@
        reverting the current buffer.  It made working in remote buffers with
        enable-remote-dir-locals non-nil slower, which doesn't seem worth it
        for a minor improvement of an infrequent operation.  Also less
-       compexity overall.
+       complexity overall.
 
        * lisp/progmodes/project.el (project-try-vc, project-files)
        (project--vc-list-files, project-ignores, project-buffers):
@@ -16929,7 +18482,7 @@
 
        This fixes bug #59427.  We now handle correctly the case when a 
parenthesis
        follows the * which is ambiguously a multiplication or indirection 
operator.
-       Also, we don't recognise a type thus found as a found type - the 
evidence is
+       Also, we don't recognize a type thus found as a found type - the 
evidence is
        too weak.
 
        * lisp/progmodes/cc-engine.el (c-forward-decl-or-cast-1): Fix CASE 17.5 
as
@@ -17846,7 +19399,7 @@
        Previously applied heuristic 2 sometimes invalidates heuristic 1, add
        a guard so it doesn't.
 
-       The new function is just for clearity of the code and has nothing to
+       The new function is just for clarity of the code and has nothing to
        do with the change itself.
 
        * lisp/treesit.el (treesit--node-length): New function
@@ -18380,7 +19933,7 @@
 
        * test/lisp/simple-tests.el
        (simple-execute-extended-command--describe-binding-msg):
-       Bind text-quoting-style explicitly to ensure consistent behaviour
+       Bind text-quoting-style explicitly to ensure consistent behavior
        whether or not the test is run interactively.
 
 2022-11-18  Stefan Kangas  <stefankangas@gmail.com>
@@ -18531,7 +20084,7 @@
 
 2022-11-17  Philip Kaludercic  <philipk@posteo.net>
 
-       Fix the behaviour of 'byte-compile-ignore-files'
+       Fix the behavior of 'byte-compile-ignore-files'
 
        * lisp/emacs-lisp/bytecomp.el (byte-recompile-directory): Negate the
        'string-match-p' check.  (Bug#59139)
@@ -18694,7 +20247,7 @@
 
        * lisp/emacs-lisp/package-vc.el (package-vc-repository-store):
        Unmention 'package-vc--unpack'.
-       (package-vc-install): Unmention 'package-vc--guess-backend' in favour
+       (package-vc-install): Unmention 'package-vc--guess-backend' in favor
        of 'package-vc-heuristic-alist'.
 
 2022-11-17  Philip Kaludercic  <philipk@posteo.net>
@@ -18736,7 +20289,7 @@
        Mark 'package-vc-update' as interactive
 
        * lisp/emacs-lisp/package-vc.el (package-vc--sourced-packages-list):
-       Remove function in favour of 'package-vc--read-package-name'.
+       Remove function in favor of 'package-vc--read-package-name'.
        (package-vc--read-package-name):
        Extract out common functionality.
        (package-vc--read-package-desc): Add auxiliary function based on
@@ -18745,7 +20298,7 @@
        'package-vc--read-package-desc'.
        (package-vc-install): Use 'package-vc--read-package-desc'.
        (package-vc-checkout): Use 'package-vc--read-package-desc'.
-       (package-vc--read-pkg): Remove in favour of 
'package-vc--read-package-desc'.
+       (package-vc--read-pkg): Remove in favor of 
'package-vc--read-package-desc'.
        (package-vc-refresh): Use 'package-vc--read-package-desc'.
        (package-vc-prepare-patch): Use 'package-vc--read-package-desc'.
 
@@ -18779,7 +20332,7 @@
        Handle strings as keys in 'package-vc-ensure-packages'
 
        * lisp/emacs-lisp/package-vc.el (package-vc-ensure-packages): Inter
-       sting keys while processing 'package-vc-selected-packages'.
+       string keys while processing 'package-vc-selected-packages'.
 
        As requested by Rudolf Adamkovič.
 
@@ -20734,10 +22287,10 @@
 
        * doc/lispref/modes.texi (Parser-based Indentation): Update manual.
        * lisp/progmodes/js.el (js--treesit-indent-rules): Change all
-       occurance of ,js-indent-level to js-indent-level.
+       occurrence of ,js-indent-level to js-indent-level.
 
        * lisp/progmodes/ts-mode.el (ts-mode--indent-rules): Change all
-       occurance of ,ts-mode-indent-offset to ts-mode-indent-offset.
+       occurrence of ,ts-mode-indent-offset to ts-mode-indent-offset.
        * lisp/treesit.el (treesit-simple-indent-rules): Change docstring.
        (treesit-simple-indent): Allow offset to be a variable.
 
@@ -21031,7 +22584,7 @@
        Print "decrypted" rot13 text is buffer is read-only
 
        * lisp/rot13.el (rot13-region): Add fallback if buffer is read-only
-       * doc/emacs/rmail.texi (Rmail Rot13): Document new behaviour.
+       * doc/emacs/rmail.texi (Rmail Rot13): Document new behavior.
 
 2022-11-04  Philip Kaludercic  <philipk@posteo.net>
 
@@ -21315,7 +22868,7 @@
 
        * lisp/progmodes/js.el (js--treesit-font-lock-settings)
        * lisp/progmodes/ts-mode.el (ts-mode--font-lock-settings): Capture
-       commend and strings.  Add empty lines.
+       comment and strings.  Add empty lines.
 
 2022-11-03  Jim Porter  <jporterbugs@gmail.com>
 
@@ -21739,7 +23292,7 @@
 
 2022-11-01  Gerd Möllmann  <gerd@gnu.org>
 
-       Preven a buffer-overflow (bug#58850)
+       Prevent a buffer-overflow (bug#58850)
 
        * src/print.c (print_vectorlike): Don't use sprintf.
 
@@ -21831,7 +23384,7 @@
        * doc/lispref/modes.texi (Parser-based Font Lock): Reflect the change
        in manual.
        * lisp/font-lock.el (font-lock-fontify-syntactically-function): New
-       varaible.
+       variable.
        (font-lock-default-fontify-region): Call
        font-lock-fontify-syntactically-function rather.
        (font-lock-fontify-syntactically-region): Rename to
@@ -21984,7 +23537,7 @@
        Unmention :release-rev
        (package-vc-desc->spec): Fall back on other archives if a
        specification is missing.
-       (package-vc-main-file): Add new function, copying the behaviour of
+       (package-vc-main-file): Add new function, copying the behavior of
        elpa-admin.el.
        (package-vc-generate-description-file): Use 'package-vc-main-file'.
        (package-vc-unpack): Handle special value ':last-release'.
@@ -21996,7 +23549,7 @@
        * lisp/vc/vc.el (vc-default-last-change): Add default 'last-change'
        implementation.
 
-       This attempts to replicate the behaviour of elpa-admin.el's
+       This attempts to replicate the behavior of elpa-admin.el's
        "elpaa--get-last-release-commit".
 
 2022-10-30  Damien Cassou  <damien@cassou.me>
@@ -23428,10 +24981,10 @@
 
 2022-10-24  Mattias Engdegård  <mattiase@acm.org>
 
-       Fix regexp matching with atomic strings and optimised backtracking
+       Fix regexp matching with atomic strings and optimized backtracking
 
        This bug occurs when an atomic pattern is matched at the end of
-       a string and the on-failure-keep-string-jump optimisation is
+       a string and the on-failure-keep-string-jump optimization is
        in effect, as in:
 
          (string-match "\\'\\(?:ab\\)*\\'" "a")
@@ -23533,7 +25086,7 @@
 
 2022-10-23  Yuan Fu  <casouri@gmail.com>
 
-       Change function signiture of treesit search functions
+       Change function signature of treesit search functions
 
        Justification: We want to make the SIDE argument in
        treesit-search-forward-goto optional, so I changed it to START.
@@ -23549,7 +25102,7 @@
        will probably be used more frequently than ALL anyway.
 
        * doc/lispref/parsing.texi (Retrieving Node): Resolve FIXME and update
-       function signitures.
+       function signatures.
        * lisp/treesit.el (treesit-search-forward-goto): Change SIDE to
        START, swap BACKWARD and ALL.
        (treesit-beginning-of-defun)
@@ -23581,7 +25134,7 @@
 
 2022-10-23  Philip Kaludercic  <philipk@posteo.net>
 
-       ;Fix typo "pacakge" -> "package"
+       ; Fix typo for "package"
 
 2022-10-23  Philip Kaludercic  <philipk@posteo.net>
 
@@ -23595,7 +25148,7 @@
 
 2022-10-23  Philip Kaludercic  <philipk@posteo.net>
 
-       ;Fix typo "heusitic" -> "heuristic"
+       ; Fix typo for "heuristic"
 
 2022-10-23  Philip Kaludercic  <philipk@posteo.net>
 
@@ -24301,7 +25854,7 @@
        from an identifier before passing it to c-add-type.
        (c-forward-decl-or-cast-1): CASE 3: Do not recognize two consecutive
        identifiers as type + variable/function unless certain conditions are 
met.
-       CASE 10: Do not recognize the "type" as a found type unless certain 
condtions
+       CASE 10: Do not recognize the "type" as a found type unless certain 
conditions
        are met.  (Near end): Do not recognize the identifier in a cast as a 
type
        unless certain conditions are met.
 
@@ -24919,9 +26472,9 @@
 
        Delete the itree_null sentinel node, use NULL everywhere.
 
-       This effort caught a few (already commited) places that were
+       This effort caught a few (already committed) places that were
        dereferencing through ITREE_NULL in a confusing way.  It makes some
-       functions have to check for NULL in more places, but in my experinece
+       functions have to check for NULL in more places, but in my experience
        this is worth it from a code clarity point of view.
 
        In doing this I rewrote `interval_tree_remove` completely.  There
@@ -25979,7 +27532,7 @@
        * src/itree.c (itree_null): Statically initialize itree_null.parent to
        NULL.  It is never accessed.
        (null_is_sane): Assert parent == NULL.
-       (interval_tree_remove_fix): Remove unecessary assignments to parent
+       (interval_tree_remove_fix): Remove unnecessary assignments to parent
        from node->parent.  These were the last places itree_null.parent were
        read.
        (interval_tree_remove): Avoid an assignment to itree_null.parent
@@ -26142,7 +27695,7 @@
 
 2022-10-10  Yuan Fu  <casouri@gmail.com>
 
-       Improve treesit-search-forward-goto so it doens't stuck at EOF
+       Improve treesit-search-forward-goto so it doesn't stuck at EOF
 
        * lisp/treesit.el (treesit-search-forward-goto): Handle the edge case.
 
@@ -26198,7 +27751,7 @@
 
        Fix tree-sitter build script in admin/notes
 
-       * admin/notes/tree-sitter/build-module/README: Add explaination.
+       * admin/notes/tree-sitter/build-module/README: Add explanation.
        * admin/notes/tree-sitter/build-module/build.sh: change
        typescript to tsx.
 
@@ -26304,14 +27857,14 @@
        Remove redundant check of the `limit` value.
        (interval_node_init): Remove `begin` and `end` args.
        (interval_tree_insert): Mark it as static.
-       Assert that the new node's `otick` should already be uptodate and its
+       Assert that the new node's `otick` should already be up-to-date and its
        new parent as well.
        (itree_insert_node): New function.
        (interval_tree_insert_gap): Assert the otick of the removed+added nodes
-       were uptodate and mark them as uptodate again after adjusting
+       were up-to-date and mark them as up-to-date again after adjusting
        their positions.
        (interval_tree_inherit_offset): Check that the parent is at least as
-       uptodate as the child.
+       up-to-date as the child.
 
        * src/lisp.h (build_overlay): Move to `buffer.h`.
 
@@ -26336,7 +27889,7 @@
        * lisp/simple.el (execute-extended-command--shorter): Compute a
        complete list of `commandp' symbols once.  This significantly speeds
        up complicated cases while the slowdown of simple cases is still
-       accetable.
+       acceptable.
 
 2022-10-09  समीर सिंह Sameer Singh  <lumarzeli30@gmail.com>
 
@@ -26419,7 +27972,7 @@
 
 2022-10-08  Mattias Engdegård  <mattiase@acm.org>
 
-       Restrict string-lessp vectorisation to safe architectures
+       Restrict string-lessp vectorization to safe architectures
 
        * src/fns.c (HAVE_FAST_UNALIGNED_ACCESS): New.
        (Fstring_lessp): Only use word operations where safe, because string
@@ -27109,7 +28662,7 @@
        (interval_tree_propagate_limit): Use it.
        (null_is_sane): Remove `inline` annotation; it's not needed.
        (interval_tree_inherit_offset): Sanity check that `offset` is 0 when
-       `otick` is uptodate.  Skip the unneeded increments when the offset is 0.
+       `otick` is up-to-date.  Skip the unneeded increments when the offset is 
0.
        (interval_tree_insert_fix): Add sanity check that we indeed have 2 reds.
 
 2022-10-05  Po Lu  <luangruo@yahoo.com>
@@ -27258,7 +28811,7 @@
        Fix bug in "macintization" of x_draw_glyph_string
 
        * src/nsterm.m (ns_draw_stretch_glyph_string): Restore text decoration
-       drawing code ommitted during "macintization" to convert the X function
+       drawing code omitted during "macintization" to convert the X function
        into NS code.  Reported by Qiantan Hong <qthong@stanford.edu>.
 
 2022-10-04  Filipp Gunbin  <fgunbin@fastmail.fm>
@@ -27393,7 +28946,7 @@
 
        Merge from origin/emacs-28
 
-       a78af3018e * src/emacs.c (load_pdump): Propery handle case when execu...
+       a78af3018e * src/emacs.c (load_pdump): Properly handle case when 
execu...
 
        # Conflicts:
        #       src/emacs.c
@@ -27429,7 +28982,7 @@
 
 2022-10-04  Andreas Schwab  <schwab@linux-m68k.org>
 
-       * src/emacs.c (load_pdump): Propery handle case when executable
+       * src/emacs.c (load_pdump): Properly handle case when executable
        wasn't found.
 
 2022-10-04  Alan Mackenzie  <acm@muc.de>
@@ -27626,7 +29179,7 @@
 
        * src/xterm.c (x_handle_wm_state): New function.
        (handle_one_xevent): Handle window state changes in WM_STATE
-       messages, and use them for signalling deiconification.
+       messages, and use them for signaling deiconification.
        (bug#58164)
 
 2022-10-03  Stefan Kangas  <stefankangas@gmail.com>
@@ -28386,7 +29939,7 @@
        Rectify string= documentation
 
        * doc/lispref/strings.texi (Text Comparison): Describe the current
-       behaviour since about 20 years back.
+       behavior since about 20 years back.
 
 2022-09-30  Mattias Engdegård  <mattiase@acm.org>
 
@@ -28400,7 +29953,7 @@
        Speed up string-lessp further
 
        * src/fns.c (Fstring_lessp): Use the memcmp fast path for ASCII-only
-       multibyte strings as well.  Specialise loops on argument
+       multibyte strings as well.  Specialize loops on argument
        multibyteness.
 
 2022-09-30  Lars Ingebrigtsen  <larsi@gnus.org>
@@ -28470,7 +30023,7 @@
 
        Remove the per-tree null node
 
-       "make check" shows 0 unexpcted.
+       "make check" shows 0 unexpected.
 
        * src/itree.h (itree_null): Declare extern.
        (ITREE_NULL): New macro
@@ -29344,7 +30897,7 @@
        "c++-or-c-but-not-both-at-once" server, this commit now breaks that
        person's configuration.
 
-       After analysing the entries of this variable, an educated guess was
+       After analyzing the entries of this variable, an educated guess was
        made that this situation is rare.  If it's not rare, then some change
        to the syntax of eglot-server-programs will have to ensue.
 
@@ -29902,7 +31455,7 @@
        variable.
        (c-after-change-mark-abnormal-strings): Set c-open-string-opener when an
        unbalanced string is detected.
-       (c-before-change): Initilize c-open-string-opener to nil, each buffer 
change.
+       (c-before-change): Initialize c-open-string-opener to nil, each buffer 
change.
        (c-electric-pair-inhibit-predicate): Use the value of 
c-open-string-opener to
        flag an unbalaced string rather than trying to calculate it again.
 
@@ -30203,7 +31756,7 @@
        Make bounding box of 'image-crop' more noticeable
 
        * lisp/image/image-crop.el (image-crop--crop-image-1): Darken the
-       selected region to make the bounding-box more noticable in images
+       selected region to make the bounding-box more noticeable in images
        which are mostly white (bug#58004).
 
 2022-09-23  Lars Ingebrigtsen  <larsi@gnus.org>
@@ -30445,7 +31998,7 @@
        Work around rare crash when turning scroll wheel
 
        * src/xterm.c (handle_one_xevent): Don't allow devices to be
-       added twice handling hierarcy events.
+       added twice handling hierarchy events.
 
 2022-09-21  Sean Whitton  <spwhitton@spwhitton.name>
 
@@ -31133,7 +32686,7 @@
 
 2022-09-19  Po Lu  <luangruo@yahoo.com>
 
-       * Makefile.in: Readd warnings about "git clean -fdx"
+       * Makefile.in: Re-add warnings about "git clean -fdx"
 
 2022-09-19  Po Lu  <luangruo@yahoo.com>
 
@@ -34162,7 +35715,7 @@
 
        Fix (mostly multibyte) issues in sieve-manage.el (Bug#54154)
 
-       The managesieve protocol (s. RFC5804) requires support for (a sightly
+       The managesieve protocol (s. RFC5804) requires support for (a slightly
        restricted variant of) UTF-8 in script content and script names. This
        commit fixes/improves the handling of multibyte characters.
 
@@ -34210,7 +35763,7 @@
 
 2022-09-06  Kai Tetzlaff  <emacs@tetzco.de>
 
-       Improve robustnes of `sieve-manage-quit' in case of errors
+       Improve robustness of `sieve-manage-quit' in case of errors
 
        * lisp/net/sieve.el (sieve-manage-quit): Avoid killing buffers it's
        not supposed to touch (bug#54154).
@@ -34304,7 +35857,7 @@
        * lisp/ffap.el (find-file-at-point): Allow people to set
        ffap-file-finder again (bug#50279).
 
-       * lisp/ido.el (ido-everywhere): Add an interstitial to fulfil
+       * lisp/ido.el (ido-everywhere): Add an interstitial to fulfill
        ffap-file-handler semantics.
 
 2022-09-06  Stefan Kangas  <stefankangas@gmail.com>
@@ -35482,7 +37035,7 @@
        * lisp/t-mouse.el (gpm-mouse-tty-setup): New function.
        (gpm-mouse-mode): Use it as well as `tty-setup-hook`.
        * lisp/term/linux.el (terminal-init-linux): Remove gpm-specific code,
-       not neded any more.
+       not needed any more.
 
 2022-08-30  Gregory Heytings  <gregory@heytings.org>
 
@@ -36843,7 +38396,7 @@
 
 2022-08-21  Mattias Engdegård  <mattiase@acm.org>
 
-       Fix eshell-pipe-broken signalling
+       Fix eshell-pipe-broken signaling
 
        * lisp/eshell/esh-io.el (eshell-output-object-to-target):
        Second argument to `signal` should be a list.
@@ -36927,12 +38480,12 @@
 
 2022-08-21  Mattias Engdegård  <mattiase@acm.org>
 
-       Update function properties and optimisations
+       Update function properties and optimizations
 
        * lisp/emacs-lisp/byte-opt.el (byte-opt--bool-value-form):
-       Recognise boolean identity in aset, put, function-put and puthash.
+       Recognize boolean identity in aset, put, function-put and puthash.
        * lisp/emacs-lisp/byte-opt.el (byte-compile-trueconstp):
-       Mark more functins as non-nil-returning, including the new
+       Mark more functions as non-nil-returning, including the new
        pos-bol and pos-eol.
        * lisp/emacs-lisp/byte-opt.el (side-effect-free-fns):
        Mark pos-bol and pos-eol as side-effect-free.
@@ -37065,7 +38618,7 @@
 
 2022-08-19  Mattias Engdegård  <mattiase@acm.org>
 
-       Move `while` syntax check from optimiser to macroexpand
+       Move `while` syntax check from optimizer to macroexpand
 
        * lisp/emacs-lisp/byte-opt.el (byte-optimize-while): Move check...
        * lisp/emacs-lisp/macroexp.el (macroexp--expand-all): ...here.
@@ -37226,7 +38779,7 @@
        python.el: Adjustments to Flymake backend
 
        * lisp/progmodes/python.el (python-flymake-command): Advertise
-       possiblity to use pylint.
+       possibility to use pylint.
        (python-flymake-command-output-pattern): Make compatible with recent
        versions of pyflakes.  (Bug#53913)
 
@@ -37477,7 +39030,7 @@
 
 2022-08-18  Mattias Engdegård  <mattiase@acm.org>
 
-       More non-nil-returning functions in source optimisation
+       More non-nil-returning functions in source optimization
 
        This change was partially generated and mechanically cross-validated
        with function type information from comp-known-type-specifiers in
@@ -37785,7 +39338,7 @@
 
 2022-08-16  Mattias Engdegård  <mattiase@acm.org>
 
-       Improved `null` (alias `not`) optimisation
+       Improved `null` (alias `not`) optimization
 
        Take static boolean information of the argument into account.
 
@@ -37793,7 +39346,7 @@
 
 2022-08-16  Mattias Engdegård  <mattiase@acm.org>
 
-       Improved `and` and `or` optimisation
+       Improved `and` and `or` optimization
 
        * lisp/emacs-lisp/byte-opt.el (byte-optimize-and, byte-optimize-or):
        Rewrite.  Avoid branching on arguments statically known to be true or
@@ -37801,9 +39354,9 @@
 
 2022-08-16  Mattias Engdegård  <mattiase@acm.org>
 
-       Improved `if` and `while` optimisation
+       Improved `if` and `while` optimization
 
-       Recognise some more special cases:
+       Recognize some more special cases:
 
          (if X nil t)      -> (not X)
          (if X t)          -> (not (not X))
@@ -38519,7 +40072,7 @@
 
        Make htmlfontify-version variable obsolete
 
-       * lisp/htmlfontify.el (htmlfontify-version): Make obolete.
+       * lisp/htmlfontify.el (htmlfontify-version): Make obsolete.
        (hfy-meta-tags): Don't use above obsolete variable.
 
 2022-08-13  Stefan Kangas  <stefan@marxist.se>
@@ -38545,7 +40098,7 @@
 
 2022-08-13  Po Lu  <luangruo@yahoo.com>
 
-       Prevent selection converter from signalling if buffer is narrowed
+       Prevent selection converter from signaling if buffer is narrowed
 
        * lisp/select.el (xselect-convert-to-string): If positions are
        outside the accessible portion of the buffer, don't return
@@ -38980,7 +40533,7 @@
 
        Add "send patches" note to package-vc TODO section
 
-       * package.el (describe-package-1): Add news if avaliable
+       * package.el (describe-package-1): Add news if available
 
        * package.el (package--get-activatable-pkg): Prefer source packages
 
@@ -39101,14 +40654,14 @@
 
 2022-08-10  Mattias Engdegård  <mattiase@acm.org>
 
-       Extend LAP optimisations to more operations
+       Extend LAP optimizations to more operations
 
        Extend the set of eligible opcodes for certain peephole
-       transformations, which then provide further optimisation
+       transformations, which then provide further optimization
        opportunities.
 
        * lisp/emacs-lisp/byte-opt.el (byte-optimize-lapcode):
-       Optimise empty save-current-buffer in the same way as we already
+       Optimize empty save-current-buffer in the same way as we already
        do for save-excursion and save-restriction.  This is safe
        because (save-current-buffer) is a no-op.
        (byte-compile-side-effect-and-error-free-ops): Add list3, list4 and
@@ -40884,7 +42437,7 @@
 
        * lisp/auth-source.el (auth-source-netrc-parse-all): New function
        (bug#56976).
-       (auth-source-netrc-parse): Partially revert behaviour in previous
+       (auth-source-netrc-parse): Partially revert behavior in previous
        change -- require :allow-null to match.
 
 2022-08-04  Lars Ingebrigtsen  <larsi@gnus.org>
@@ -40900,7 +42453,7 @@
 
        * lisp/emacs-lisp/package.el
        (package-autoload-ensure-default-file): Don't warn about
-       soon-to-be obsolete functon.
+       soon-to-be obsolete function.
 
 2022-08-04  Lars Ingebrigtsen  <larsi@gnus.org>
 
@@ -41190,7 +42743,7 @@
 
        Adjust src/Makefile.in comments about make-docfile
 
-       * src/Makefile.in ($(etc)/DOC): Remove comment aboout make-docfile
+       * src/Makefile.in ($(etc)/DOC): Remove comment about make-docfile
        being run twice (because it no longer is).
 
 2022-08-04  Po Lu  <luangruo@yahoo.com>
@@ -41244,7 +42797,7 @@
        Avoid redundant calls to XFlush in x_make_frame_visible
 
        * src/xterm.c (x_make_frame_visible): Keep track of whether or
-       not the output buffer was implictly flushed before issuing
+       not the output buffer was implicitly flushed before issuing
        XFlush.
 
 2022-08-03  Stefan Monnier  <monnier@iro.umontreal.ca>
@@ -41787,7 +43340,7 @@
        same key is specified twice.  (Bug#56873)
 
        * doc/lispref/keymaps.texi (Creating Keymaps): Document error
-       signaling behaviour.
+       signaling behavior.
 
        * test/src/keymap-tests.el (keymap-test-duplicate-definitions): Test
        duplicate definition detection.
@@ -42498,7 +44051,7 @@
        Remove loaddefs debug code
 
        * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--rubric):
-       Remove code inadvertantly checked in.
+       Remove code inadvertently checked in.
 
 2022-07-31  Lars Ingebrigtsen  <larsi@gnus.org>
 
@@ -42829,7 +44382,7 @@
        Minor improvements to precision scroll interpolation
 
        * lisp/pixel-scroll.el (pixel-scroll-start-momentum): Bump GC
-       cons threshold temporarily.  This leads to a very noticable
+       cons threshold temporarily.  This leads to a very noticeable
        improvement to animation speed.
 
 2022-07-29  Po Lu  <luangruo@yahoo.com>
@@ -42954,7 +44507,7 @@
        (XTframe_up_to_date): Set FRAME_X_WAITING_FOR_DRAW if bumped.
        (handle_one_xevent): Handle frame drawn events.
 
-       * src/xterm.h (struct x_output): New fields for frame dirtyness
+       * src/xterm.h (struct x_output): New fields for frame dirtiness
        and vsync.
 
 2022-07-29  Gregory Heytings  <gregory@heytings.org>
@@ -43774,7 +45327,7 @@
 
 2022-07-25  Robert Pluim  <rpluim@gmail.com>
 
-       Make package-archives URL treatment slighty laxer
+       Make package-archives URL treatment slightly laxer
 
        'package-archives' URLs are expected to end in '/', but we can
        cater for people typoing that by using 'url-expand-file-name'.
@@ -44540,7 +46093,7 @@
 
        Merge from origin/emacs-28
 
-       ea44d7ddfc ; * lisp/mail/smtpmail.el (smtpmail-via-smtp): Explain wit...
+       ea44d7ddfc ; * lisp/mail/smtpmail.el (smtpmail-via-smtp): Explain 
with...
 
 2022-07-20  Po Lu  <luangruo@yahoo.com>
 
@@ -45294,7 +46847,7 @@
 
 2022-07-16  Mattias Engdegård  <mattiase@acm.org>
 
-       Optimise `append` calls
+       Optimize `append` calls
 
        Add the transforms
 
@@ -45317,7 +46870,7 @@
 
 2022-07-16  Mattias Engdegård  <mattiase@acm.org>
 
-       Improved cons optimisation
+       Improved cons optimization
 
        * lisp/emacs-lisp/byte-opt.el (byte-optimize-cons):
        Add the transform
@@ -45326,10 +46879,10 @@
 
 2022-07-16  Mattias Engdegård  <mattiase@acm.org>
 
-       Transform (list) -> nil in source optimiser
+       Transform (list) -> nil in source optimizer
 
-       This optimisation is already done in the code generator but performing
-       it at this earlier stage is a useful normalising step that uncovers
+       This optimization is already done in the code generator but performing
+       it at this earlier stage is a useful normalizing step that uncovers
        more opportunities.
 
        * lisp/emacs-lisp/byte-opt.el (byte-optimize-list): New.
@@ -45702,7 +47255,7 @@
        (xref-backend-definitions): Complicate.
        (completion-category-overrides): Register a category and a style here.
        (completion-styles-alist): Add eglot--lsp-backend-style style
-       (eglot--lsp-backend-style-call): New funtion.
+       (eglot--lsp-backend-style-call): New function.
        (eglot--lsp-backend-style-all-completions): New function.
        (eglot--lsp-backend-style-try-completion): New function.
 
@@ -46131,7 +47684,7 @@
 
 2022-07-12  Mattias Engdegård  <mattiase@acm.org>
 
-       Better gomoku X colour with bright background
+       Better gomoku X color with bright background
 
        * lisp/play/gomoku.el (gomoku-X): Use blue rather than green for
        crosses on bright background for better legibility.
@@ -46155,7 +47708,7 @@
        * src/pgtkmenu.c (set_frame_menubar)
        * src/xdisp.c (update_menu_bar)
        * src/xmenu.c (set_frame_menubar): Remove calls to 
Qrecompute_lucid_menubar
-       contitional on Vlucid_menu_bar_dirty_flag.
+       conditional on Vlucid_menu_bar_dirty_flag.
 
 2022-07-12  Po Lu  <luangruo@yahoo.com>
 
@@ -46929,7 +48482,7 @@
        * src/dispextern.h (WITH_NARROWED_BEGV): New macro.
 
        * src/xdisp.c (get_narrowed_begv): New function.
-       (init_iterator): Initilize the 'narrowed_begv' field.
+       (init_iterator): Initialize the 'narrowed_begv' field.
        (back_to_previous_line_start, get_visually_first_element,
        move_it_vertically_backward): Use the new macro.
 
@@ -47342,7 +48895,7 @@
        * src/fns.c (concat_strings): Rename to...
        (concat_to_string): ...this.
        (concat): Split into concat_to_list and concat_to_vector.
-       (concat_to_list, concat_to_vector): New, specialised and
+       (concat_to_list, concat_to_vector): New, specialized and
        streamlined from earlier combined code.
        (concat2, concat3, Fappend, Fconcat, Fvconcat): Adjust calls.
 
@@ -48036,7 +49589,7 @@
 
 2022-07-05  Lars Ingebrigtsen  <larsi@gnus.org>
 
-       Documnt left/right mwheel events
+       Document left/right mwheel events
 
        * doc/lispref/commands.texi (Misc Events): Document left/right
        mwheel events (bug#41722).
@@ -48727,7 +50280,7 @@
 
 2022-07-03  Eli Zaretskii  <eliz@gnu.org>
 
-       Implement pseudo-value 'reset' of face attrributes
+       Implement pseudo-value 'reset' of face attributes
 
        * doc/lispref/display.texi (Face Attributes):
        * etc/NEWS: Document the new pseudo-value 'reset'.
@@ -49171,7 +50724,7 @@
 
 2022-07-01  Lars Ingebrigtsen  <larsi@gnus.org>
 
-       Make time-stamp-tests.el work in a Norwegian language enviroment
+       Make time-stamp-tests.el work in a Norwegian language environment
 
        The short version of names for days/month is not necessary the same as
        limiting the string with a #n operator.  For instance:
@@ -50159,7 +51712,7 @@
 
 2022-06-30  Lars Ingebrigtsen  <larsi@gnus.org>
 
-       Restore temp-buffer-resize-mode behaviour wrt. [back] buttons
+       Restore temp-buffer-resize-mode behavior wrt. [back] buttons
 
        * lisp/help.el (help--window-setup): If temp-buffer-resize-mode, do
        the window setup after adding [back] buttons (bug#56306).
@@ -50962,7 +52515,7 @@
 
 2022-06-26  Mattias Engdegård  <mattiase@acm.org>
 
-       Optimise away functions in for-effect context
+       Optimize away functions in for-effect context
 
        * lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker):
        Turn functions into nil when compiled for-effect since they have no
@@ -50970,7 +52523,7 @@
        as the elimination of variable bindings.
        `unwind-protect` forms can be treated as plain function call at this
        point.  In particular, their unwind function argument should be
-       not optimised for effect since it's a function.
+       not optimized for effect since it's a function.
 
 2022-06-26  Stefan Monnier  <monnier@iro.umontreal.ca>
 
@@ -51141,7 +52694,7 @@
 
        * lisp/files.el (locate-user-emacs-file): Don't create HOME if it
        doesn't exist (bug#47298).  This returns us to Emacs 26.3
-       behaviour here.
+       behavior here.
 
 2022-06-26  Michael Albinus  <michael.albinus@gmx.de>
 
@@ -51524,7 +53077,7 @@
 
        Bytecode opcode comments update
 
-       This is a cosmetic change only; there is no change in behaviour.
+       This is a cosmetic change only; there is no change in behavior.
 
        * lisp/emacs-lisp/bytecomp.el:
        * src/bytecode.c (BYTE_CODES, exec_byte_code):
@@ -51999,7 +53552,7 @@
 
        A trivial optimization and a formatting fix
 
-       * lisp/subr.el (internal--compiler-macro-cXXr): Re-use `head' for `n'.
+       * lisp/subr.el (internal--compiler-macro-cXXr): Reuse `head' for `n'.
        Fix indentation and line length.
 
 2022-06-21  Tassilo Horn  <tsdh@gnu.org>
@@ -53548,7 +55101,7 @@
 
 2022-06-16  Mattias Engdegård  <mattiase@acm.org>
 
-       * src/fns.c (mapcar1): Test types in rough order of likelyhood.
+       * src/fns.c (mapcar1): Test types in rough order of likelihood.
 
 2022-06-16  Mattias Engdegård  <mattiase@acm.org>
 
@@ -53786,7 +55339,7 @@
 
        Improve drag atom computation
 
-       * src/xterm.c (xm_get_drag_window): Avoid leak if error occured
+       * src/xterm.c (xm_get_drag_window): Avoid leak if error occurred
        creating drag window.  Also use StructureNotifyMask instead of
        ButtonPressMask.
        (xm_get_drag_atom_1): Update.  Make EMACS_DRAG_ATOM a list of
@@ -54110,7 +55663,7 @@
        (Ftreesit_query_compile): New function.
        (Ftreesit_query_capture): Remove code that creates a query object and
        instead either use make_ts_query or use the give compiled query.  Free
-       the query object conditonally.
+       the query object conditionally.
        (syms_of_treesit): New symbol.
 
 2022-06-14  Yuan Fu  <casouri@gmail.com>
@@ -54121,7 +55674,7 @@
 
        Add new type treesit-compiled-query
 
-       No intergration/interaction with the new type, just adding it.
+       No integration/interaction with the new type, just adding it.
 
        * lisp/emacs-lisp/cl-preloaded.el (cl--typeof-types): Add new type.
        * src/alloc.c (cleanup_vector): Add gc for the new type.
@@ -54142,8 +55695,8 @@
        * lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker)
        (byte-optimize-let-form, byte-optimize-letX):
        * lisp/emacs-lisp/bytecomp.el (byte-compile-unwind-protect):
-       Simplify source optimisation and codegen code that can now rely on
-       normalised let/let* and unwind-protect forms.
+       Simplify source optimization and codegen code that can now rely on
+       normalized let/let* and unwind-protect forms.
 
 2022-06-14  Mattias Engdegård  <mattiase@acm.org>
 
@@ -54161,14 +55714,14 @@
 
 2022-06-14  Mattias Engdegård  <mattiase@acm.org>
 
-       Normalise setq during macro-expansion
+       Normalize setq during macro-expansion
 
-       Early normalisation of setq during macroexpand-all allows later
+       Early normalization of setq during macroexpand-all allows later
        stages, cconv, byte-opt and codegen, to be simplified and duplicated
        checks to be eliminated.
 
        * lisp/emacs-lisp/macroexp.el (macroexp--expand-all):
-       Normalise all setq forms to a sequence of (setq VAR EXPR).
+       Normalize all setq forms to a sequence of (setq VAR EXPR).
        Emit warnings if necessary.
        * lisp/emacs-lisp/cconv.el (cconv-convert, cconv-analyze-form):
        * lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker):
@@ -55015,7 +56568,7 @@
 
 2022-06-10  Po Lu  <luangruo@yahoo.com>
 
-       Fix cancelling DND upon a regular X error
+       Fix canceling DND upon a regular X error
 
        * src/xterm.c (x_connection_closed): The display isn't dead upon
        a non-IO error, so don't avoid sending messages to clean stuff
@@ -55553,7 +57106,7 @@
        Add more super and subscript characters to latin input methods
 
        * lisp/leim/quail/latin-post.el ("latin-postfix", "latin-prefix"): Add
-       mssing super and subscript characters.  (Bug#55722)
+       missing super and subscript characters.  (Bug#55722)
 
 2022-06-08  Robert Pluim  <rpluim@gmail.com>
 
@@ -55887,7 +57440,7 @@
        * src/xterm.c (x_defer_selection_requests)
        (x_release_selection_requests): New functions.
        (x_dnd_begin_drag_and_drop): Use those functions to defer
-       selections instead.  Fix error signalled when ownership of
+       selections instead.  Fix error signaled when ownership of
        XdndSelection is lost.
        (handle_one_xevent): Likewise.
 
@@ -56712,7 +58265,7 @@
        (dnd-remove-last-dragged-remote-file): Handle list values.
        (dnd-begin-file-drag): Fix file name expansion.
        (dnd-begin-drag-files): New function.
-       * lisp/select.el (xselect-convert-to-filename): Handle mutiple
+       * lisp/select.el (xselect-convert-to-filename): Handle multiple
        files
        (a vector of file names):.
 
@@ -56750,7 +58303,7 @@
        Use a space since that is clearly what was meant.
        ?\ at the end of a line (ie, ?\LF) never was well-defined and produced
        -1 most of the time, but will soon raise an error (bug#55738).
-       This doesn't matter much becaue this variable is unused.
+       This doesn't matter much because this variable is unused.
 
 2022-06-03  Po Lu  <luangruo@yahoo.com>
 
@@ -56813,7 +58366,7 @@
 
 2022-06-02  Po Lu  <luangruo@yahoo.com>
 
-       Don't call XSelectInput on a dying display when cancelling drag-and-drop
+       Don't call XSelectInput on a dying display when canceling drag-and-drop
 
        * src/xterm.c (x_dnd_free_toplevels): New argument
        `display_alive'.
@@ -56841,7 +58394,7 @@
 
        Make ?\LF generate 10, not -1 (bug#55738)
 
-       The old -1 value was an artefact of the reader implementation.
+       The old -1 value was an artifact of the reader implementation.
 
        * src/lread.c (read_escape): Remove the `stringp` argument; assume
        character literal syntax.  Never return -1.
@@ -56851,7 +58404,7 @@
 
 2022-06-02  Mattias Engdegård  <mattiase@acm.org>
 
-       * src/lread.c (skip_lazy_string): Fix uninitialised variable.
+       * src/lread.c (skip_lazy_string): Fix uninitialized variable.
 
 2022-06-02  Stefan Kangas  <stefan@marxist.se>
 
@@ -58114,7 +59667,7 @@
        This fixes bug#55684.  There, with a minibuffer-only frame at start up,
        Emacs tried to switch to this frame, whose selected window was the
        mini-window.  There is no other active window in this frame, so the
-       attempt to swith to another window failed.
+       attempt to switch to another window failed.
 
        * src/frame.c (do_switch_frame): On switching to a frame whose selected
        window is as above, before selecting the most recently used window, 
check
@@ -58617,7 +60170,7 @@
 
        * lisp/emacs-lisp/bytecomp.el (byte-compile--first-symbol-with-pos)
        (byte-compile--warning-source-offset):
-       Remove recursion for cdr-traversal of lists, and optimise (bug#55414).
+       Remove recursion for cdr-traversal of lists, and optimize (bug#55414).
 
 2022-05-26  Po Lu  <luangruo@yahoo.com>
 
@@ -59668,7 +61221,7 @@
 
        * src/haiku_support.cc (movement_locker, class EmacsWindow)
        (MouseMoved): Delete `movement_locker' and associated hack,
-       since it's superseeded by some code in haiku_read_socket.
+       since it's superseded by some code in haiku_read_socket.
        (key_map, key_chars, dpy_color_space, popup_track_message)
        (alert_popup_value, grab_view, grab_view_locker)
        (drag_and_drop_in_progress): Write comments and fix
@@ -60302,7 +61855,7 @@
 
        Also per https://github.com/joaotavora/eglot/issues/957.
 
-       Only actually and eagerly report LSP diagnotics if the user has
+       Only actually and eagerly report LSP diagnostics if the user has
        Flymake starting automatically on a timer (flymake-no-changes-timeout
        is a number).
 
@@ -60659,7 +62212,7 @@
        decorator dimensions.  Update prototypes.
 
        * src/haikufns.c (haiku_update_after_decoration_change): Ask for
-       a move frame event and don't do anything if configury is not yet
+       a move frame event and don't do anything if configurable is not yet
        complete.
 
        * src/haikuterm.c (haiku_read_socket): Adjust accordingly.
@@ -61050,7 +62603,7 @@
 
 2022-05-15  Lars Ingebrigtsen  <larsi@gnus.org>
 
-       Don't freeze Emacs on colour codes in sccs-mode
+       Don't freeze Emacs on color codes in sccs-mode
 
        * lisp/textmodes/css-mode.el (css--font-lock-keywords): Don't
        freeze Emacs on #ffffff #ffffff, and be more strict in parsing
@@ -62208,7 +63761,7 @@
 
 2022-05-11  Yoav Marco  <yoavm448@gmail.com>  (tiny change)
 
-       (sqlite-mode--column-names): Suppport nested parens
+       (sqlite-mode--column-names): Support nested parens
 
        * lisp/sqlite-mode.el (sqlite-mode--column-names): Make parsing
        more resilient (bug#55363).
@@ -62404,7 +63957,7 @@
 
 2022-05-10  Lars Ingebrigtsen  <larsi@gnus.org>
 
-       Use fields on log-edit headers (which changes `C-a' behaviour)
+       Use fields on log-edit headers (which changes `C-a' behavior)
 
        * lisp/vc/log-edit.el (log-edit-insert-message-template): Fieldify
        headers so that `C-a' takes us to the start of the string, not the
@@ -63316,7 +64869,7 @@
 
 2022-05-07  Lars Ingebrigtsen  <larsi@gnus.org>
 
-       Improve inferior-python-mode scroll behaviour
+       Improve inferior-python-mode scroll behavior
 
        * lisp/progmodes/python.el (inferior-python-mode): Use
        scroll-convervatively instead of trying to do this with a comint
@@ -63381,7 +64934,7 @@
 
 2022-05-07  Yuan Fu  <casouri@gmail.com>
 
-       Add tree-sitter intergration
+       Add tree-sitter integration
 
        * configure.ac (HAVE_TREE_SITTER, TREE_SITTER_OBJ): New variables.
        (DYNAMIC_LIB_SUFFIX): new variable, I copied code from MODULES_SUFFIX
@@ -66795,7 +68348,7 @@
 
        * doc/misc/info.texi (Search Index): Mention it.
 
-       * lisp/info.el (Info-find-node): Allow not signalling errors.
+       * lisp/info.el (Info-find-node): Allow not signaling errors.
        (Info-apropos-matches): Allow taking a regexp.
        (info-apropos): Prefix now means looking for a regexp.
 
@@ -66803,7 +68356,7 @@
 
        Fix indentation in copy-region-as-kill
 
-       * lisp/simple.el (copy-region-as-kill): Fix indendation.
+       * lisp/simple.el (copy-region-as-kill): Fix indentation.
 
 2022-04-21  Lars Ingebrigtsen  <larsi@gnus.org>
 
@@ -67303,11 +68856,11 @@
 
 2022-04-18  Nacho Barrientos  <nacho.barrientos@cern.ch>  (tiny change)
 
-       Unify local variable initialisation in url-http
+       Unify local variable initialization in url-http
 
        * lisp/url/url-http.el (url-http-chunked-last-crlf-missing): Treat
        url-http-chunked-last-crlf-missing as any other buffer variable by
-       declaring and initialising it the same way as the other related
+       declaring and initializing it the same way as the other related
        ones (bug#54989).
 
 2022-04-18  Lars Ingebrigtsen  <larsi@gnus.org>
@@ -67848,7 +69401,7 @@
        Make sure the ftcr font driver is used on Haiku when Cairo is enabled
 
        * src/haikufont.c (syms_of_haikufont): [USE_BE_CAIRO]: Make sure
-       `ftcr' superseeds `haiku'.
+       `ftcr' supersedes `haiku'.
 
 2022-04-16  Paul Eggert  <eggert@cs.ucla.edu>
 
@@ -68453,7 +70006,7 @@
 
 2022-04-15  Philip Kaludercic  <philipk@posteo.net>
 
-       Generalise buffer matching from project.el
+       Generalize buffer matching from project.el
 
        * subr.el (buffer-match): Add function to check if a buffer satisfies
        a condition.
@@ -68622,7 +70175,7 @@
        * lisp/net/ldap.el (ldap-ldapsearch-args): Change -LL to -LLL to
        suppress ldif version output.
        (ldap-search-internal): Remove skipping of version output.  Remove
-       redundand ws skipping.
+       redundant ws skipping.
 
 2022-04-14  Filipp Gunbin  <fgunbin@fastmail.fm>
 
@@ -68938,7 +70491,7 @@
        This reverts commit 78f76fe16e2737b40694f82af28d17a90a21ed7b.
 
        The commit made calls to cl-concatenate bug out, since
-       autoloading defalises doesn't work very well (bug#54901).
+       autoloading defaliases doesn't work very well (bug#54901).
 
 2022-04-12  Po Lu  <luangruo@yahoo.com>
 
@@ -69158,10 +70711,10 @@
 
 2022-04-12  Olaf Trygve Berglihn  <olafb@pvv.org>  (tiny change)
 
-       Add biblatex alias entry types for compability with bibtex
+       Add biblatex alias entry types for compatibility with bibtex
 
        * lisp/textmodes/bibtex.el (bibtex-biblatex-entry-alist): Add
-       biblatex alias entry types for compability with bibtex (bug#54877).
+       biblatex alias entry types for compatibility with bibtex (bug#54877).
 
 2022-04-12  Lars Ingebrigtsen  <larsi@gnus.org>
 
@@ -69178,7 +70731,7 @@
        * src/xterm.c (x_dnd_cleanup_drag_and_drop): Always free DND
        targets even if waiting for finish.
        (x_dnd_begin_drag_and_drop): Free targets correctly when
-       signalling error and prevent activating drag-and-drop inside a
+       signaling error and prevent activating drag-and-drop inside a
        menu or popup.  (It doesn't work.)
 
 2022-04-12  Michael Albinus  <michael.albinus@gmx.de>
@@ -69301,10 +70854,10 @@
 
 2022-04-11  Mattias Engdegård  <mattiase@acm.org>
 
-       Recognise hybrid IPv6/IPv4 addresses in textsec (bug#54624)
+       Recognize hybrid IPv6/IPv4 addresses in textsec (bug#54624)
 
        * lisp/international/textsec.el (textsec--ipvx-address-p):
-         Recognise hybrid addresses like "::ffff:129.55.2.201".
+         Recognize hybrid addresses like "::ffff:129.55.2.201".
          Combine to a single regexp and translate to rx.
          Remove some regexp ambiguity (relint complaint).
        * test/lisp/international/textsec-tests.el (test-suspiction-domain):
@@ -69628,7 +71181,7 @@
        Fix DND leave events not being sent to toplevel after returning frame
 
        * src/xterm.c (x_dnd_update_state, handle_one_xevent): Make sure
-       to send leave events to the previous toplevel when cancelling to
+       to send leave events to the previous toplevel when canceling to
        return a frame.
 
 2022-04-08  Po Lu  <luangruo@yahoo.com>
@@ -70147,7 +71700,7 @@
 
        * src/xterm.c (x_dnd_begin_drag_and_drop): Verify
        x_dnd_movement_x and x_dnd_movement_y are wholenums before
-       caling posn-at-x-y.
+       calling posn-at-x-y.
 
 2022-04-07  Po Lu  <luangruo@yahoo.com>
 
@@ -70240,7 +71793,7 @@
        like server latency), then Flymake sometimes doesn't request any
        diagnostics at all.
 
-       The reason for the Flymake behaviour wasn't investigated, but that
+       The reason for the Flymake behavior wasn't investigated, but that
        wasn't a very good solution either
 
        Rather this change makes it so that when such a Flymake request comes
@@ -70735,7 +72288,7 @@
 
        Reduce GC mark-phase recursion by using explicit stack (bug#54698)
 
-       An explict stack of objects to be traversed for marking replaces
+       An explicit stack of objects to be traversed for marking replaces
        recursion for most common object types: conses, vectors, records, hash
        tables, symbols, functions etc.  Recursion is still used for other
        types but those are less common and thus not as likely to cause a
@@ -70859,7 +72412,7 @@
        Rework eglot's mode-line
 
        Mimic flymake by replacing the old menus of the mode-line with
-       "context menus".  List all usefull commands under the main menu
+       "context menus".  List all useful commands under the main menu
        (eglot-menu-map), and commands related to LSP debugging under the
        project menu (eglot-debug-map).
 
@@ -70903,7 +72456,7 @@
 
        Since <, <=, > and >= have their own byte-ops, the corresponding
        functions are mostly used as arguments to higher-order functions.
-       This optimisation is particularly beneficial for sorting, where the
+       This optimization is particularly beneficial for sorting, where the
        comparison function is time-critical.
 
        * src/data.c (Flss, Fgtr, Fleq, Fgeq):
@@ -70926,7 +72479,7 @@
        Faster `string-lessp` for unibyte arguments
 
        Since this function is commonly used as a sorting predicate
-       where it is time-critical, this is a useful optimisation.
+       where it is time-critical, this is a useful optimization.
 
        * src/fns.c (Fstring_lessp): Add fast path for the common case
        when both arguments are unibyte.
@@ -71030,7 +72583,7 @@
          echo "\\"
 
        * lisp/eshell/esh-util.el (eshell-find-delimiter): Correct docstring
-       and treat '\' as an escapeable character when using backslash escapes.
+       and treat '\' as an escapable character when using backslash escapes.
 
        * test/lisp/eshell/eshell-tests.el
        (eshell-test/escape-special-quoted): Adapt test.
@@ -71158,7 +72711,7 @@
        Fix incorrect usage of XM_DRAG_SIDE_EFFECT
 
        * src/xterm.c (xm_send_top_level_leave_message)
-       (handle_one_xevent): Pass corret alt side effects and flags to
+       (handle_one_xevent): Pass correct alt side effects and flags to
        XM_DRAG_SIDE_EFFECT.
 
 2022-04-02  Lars Ingebrigtsen  <larsi@gnus.org>
@@ -71441,10 +72994,10 @@
 
        * etc/themes/modus-operandi-theme.el:
        * etc/themes/modus-vivendi-theme.el: Ensure that the theme is reified
-       as expected both at compiletime and runtime.
+       as expected both at compile time and runtime.
 
        * etc/themes/modus-themes.el (require): Require 'cl-lib' and 'subr-x'
-       at compiletime.
+       at compile time.
        (seq): Require the 'seq' library.
        (modus-themes-completion-standard-first-match)
        (modus-themes-completion-standard-selected)
@@ -71683,7 +73236,7 @@
 
        * src/pdumper.c (dump_get_max_page_size): Rename from 
'dump_get_page_size'.
 
-       * src/pdumper.c: Remove getpagesize.h dependecy.
+       * src/pdumper.c: Remove getpagesize.h dependency.
 
 2022-03-30  Michael Albinus  <michael.albinus@gmx.de>
 
@@ -72118,7 +73671,7 @@
 
        Make sure that the value added to the `read_objects_completed` set is
        the one we actually return; previously this wasn't the case for conses
-       because of an optimisation (bug#54501).
+       because of an optimization (bug#54501).
 
        Also add a check for vacuous self-references such as #1=#1# instead of
        returning a nonsense value from thin air.
@@ -72848,7 +74401,7 @@
        by RFC 5322.
 
        When eudc-inline-expansion-format remains set to a list as previously,
-       the old behaviour is fully retained.
+       the old behavior is fully retained.
 
 2022-03-22  Lars Ingebrigtsen  <larsi@gnus.org>
 
@@ -73369,7 +74922,7 @@
 
 2022-03-19  Po Lu  <luangruo@yahoo.com>
 
-       Improve behaviour of drag-n-drop during window manager operations
+       Improve behavior of drag-n-drop during window manager operations
 
        * src/xterm.c (x_dnd_begin_drag_and_drop): Select for some
        events on the root window.
@@ -74070,7 +75623,7 @@
        generation of random bignums without using Frem etc.
        * src/fns.c (get_random_fixnum): New function.
        (Frandom): Use it, and get_random_bignum.
-       Be consistent about signalling nonpositive integer arguments;
+       Be consistent about signaling nonpositive integer arguments;
        since zero is invalid, Qnatnump is not quite right here.
        * src/sysdep.c (get_random_ulong): New function.
 
@@ -74684,7 +76237,7 @@
        This results in better performance, and bytecode recursion is no
        longer limited by the size of the C stack.  The bytecode stack is
        currently of fixed size but overflow is handled gracefully by
-       signalling a Lisp error instead of the hard crash that we get now.
+       signaling a Lisp error instead of the hard crash that we get now.
 
        In addition, GC marking of the stack is now faster and more precise.
        Full precision could be attained if desired.
@@ -74911,7 +76464,7 @@
        Return the same file from locate-file in nativecomp and non
 
        * lisp/files.el (locate-file): Return the .elc file (if it exists)
-       in nativecomp, too, to mimic the behaviour from non-nativecomp
+       in nativecomp, too, to mimic the behavior from non-nativecomp
        builds (bug#51308).
 
 2022-03-12  Lars Ingebrigtsen  <larsi@gnus.org>
@@ -74931,7 +76484,7 @@
 
 2022-03-12  Alexander Adolf  <alexander.adolf@condition-alpha.com>
 
-       Facilitate Customisation of Message-Mode Header Completion Behaviour
+       Facilitate Customization of Message-Mode Header Completion Behavior
 
        * lisp/gnus/message.el (message-email-recipient-header-regexp):
        New user option.
@@ -74966,7 +76519,7 @@
 
        * src/bytecode.c (FETCH2):
        Use `|` instead of `+` to combine the bytes forming a 16-bit immediate
-       argument so that GCC (prior to version 12) recognises the idiom and
+       argument so that GCC (prior to version 12) recognizes the idiom and
        generates a 16-bit load.  This applies for little-endian machines with
        cheap unaligned accesses such as x86[-64], arm64 and power64le.
 
@@ -74974,7 +76527,7 @@
        kinds of Lisp code, as 16-bit immediates are used by all jump
        instructions.
 
-       Clang performs this optimisation for both `+` and `|` from version 10.
+       Clang performs this optimization for both `+` and `|` from version 10.
 
 2022-03-12  Mattias Engdegård  <mattiase@acm.org>
 
@@ -75284,7 +76837,7 @@
        Support remote home directories via connection property
 
        * doc/misc/tramp.texi (Home directories): New section.
-       (Top, Usage): Add it to the menue.
+       (Top, Usage): Add it to the menu.
        (Predefined connection information): Mention "~".
        (Multi-hops, File name syntax): Fix typos.
 
@@ -75704,7 +77257,7 @@
        Merge from origin/emacs-28
 
        73f28fbde8 Add a comment for previous browse-url-of-dired-file change
-       9b74e84857 Restore documented Emacs 27.2 behaviour of browse-url-of-d...
+       9b74e84857 Restore documented Emacs 27.2 behavior of browse-url-of-d...
        cd77fd3b85 Update to Org 9.5.2-24-g668205
 
 2022-03-07  Manuel Giraud  <manuel@ledu-giraud.fr>
@@ -75867,7 +77420,7 @@
 
 2022-03-06  Mattias Engdegård  <mattiase@acm.org>
 
-       Don't accept whitespace or hex floats in rgbi: colour specs
+       Don't accept whitespace or hex floats in rgbi: color specs
 
        `color-values-from-color-spec` (new in Emacs 28) erroneously accepted
        leading whitespace and hex floats in rgbi: components.
@@ -78381,7 +79934,7 @@
 
        Fix SIGFPE on some fonts when calculating their average width on Haiku
 
-       * src/haiku_font_support.cc (estimate_font_ascii): Avoid divison
+       * src/haiku_font_support.cc (estimate_font_ascii): Avoid division
        by zero.
 
 2022-02-16  Po Lu  <luangruo@yahoo.com>
@@ -78466,7 +80019,7 @@
 
        * src/character.c (count_size_as_multibyte): Move the overflow test
        outside the loop, which makes it much faster.  Standard compilers
-       will even vectorise it if asked to (-O2 in Clang, -O3 in GCC).
+       will even vectorize it if asked to (-O2 in Clang, -O3 in GCC).
 
 2022-02-16  Mattias Engdegård  <mattiase@acm.org>
 
@@ -78694,7 +80247,7 @@
        (vc-clone): Declare function for package-unpack.
        (package-unpack): Handle source packages.
        (package-generate-description-file): Handle source packages by
-       ommiting a version number.
+       omitting a version number.
        (package-install-from-archive): Check if a package is a source
        package.
        (package-fetch): Add new command
@@ -78791,7 +80344,7 @@
 
 2022-02-14  Po Lu  <luangruo@yahoo.com>
 
-       * etc/TODO: Update some entires related to macOS and NS.
+       * etc/TODO: Update some entries related to macOS and NS.
 
        Xwidgets have worked on NS for a long time, "smooth scrolling"
        is now available as `pixel-scroll-precision-mode' for all GUI
@@ -78821,7 +80374,7 @@
 
 2022-02-13  Po Lu  <luangruo@yahoo.com>
 
-       Improve efficency of handling DeviceChanged events
+       Improve efficiency of handling DeviceChanged events
 
        * src/xterm.c (handle_one_xevent): Just update the device that
        was changed on DeviceChanged and only do hierarchy recalculation
@@ -78974,7 +80527,7 @@
 
 2022-02-12  Po Lu  <luangruo@yahoo.com>
 
-       Stop quering for Xinerama inside x_get_monitor_attributes
+       Stop querying for Xinerama inside x_get_monitor_attributes
 
        * src/xfns.c (x_get_monitor_attributes): Remove Xinerama check
        and use xinerama_supported_p instead.
@@ -79096,7 +80649,7 @@
        specpdl refs has been converted.
 
        We only do this on 64-bit platforms, since those tend to have modern
-       ABIs where small structs are optimised as scalars.  In other words,
+       ABIs where small structs are optimized as scalars.  In other words,
        this change should not affect the compiled code.
 
        * src/lisp.h (specpdl_ref): Now a struct on 64-bit platforms.
@@ -79332,7 +80885,7 @@
 
 2022-02-11  Mattias Engdegård  <mattiase@acm.org>
 
-       Modernise byte-compilation chapters in manual
+       Modernize byte-compilation chapters in manual
 
        * doc/lispref/compile.texi (Speed of Byte-Code): More representative
        numbers for byte code; the difference is much greater today.
@@ -79484,7 +81037,7 @@
        Restore command-line--load-script messaging
 
        * lisp/startup.el (command-line--load-script): Restore previous
-       non-messaging behaviour.
+       non-messaging behavior.
 
 2022-02-10  Michael Albinus  <michael.albinus@gmx.de>
 
@@ -79681,14 +81234,14 @@
 
 2022-02-09  Po Lu  <luangruo@yahoo.com>
 
-       Explictly specify whether or not to respect alpha-background on Cairo
+       Explicitly specify whether or not to respect alpha-background on Cairo
 
        * src/ftcrfont.c (ftcrfont_draw): Don't respect
        `alpha-background' if drawing cursor.  (bug#53890)
        * src/xterm.c (x_set_cr_source_with_gc_foreground):
        (x_set_cr_source_with_gc_background): New parameters
        `respect_alpha_background'.  All callers changed.
-       * src/xterm.h: Update protoypes.
+       * src/xterm.h: Update prototypes.
 
 2022-02-09  Tassilo Horn  <tsdh@gnu.org>
 
@@ -79945,7 +81498,7 @@
 
        * src/widget.c (update_wm_hints): Accept frame separately from
        the shell widget.
-       (widget_update_wm_size_hints): Require WM shell to be explictly
+       (widget_update_wm_size_hints): Require WM shell to be explicitly
        specified.
        (EmacsFrameRealize):
        (EmacsFrameResize): Update callers to `update_wm_hints'.
@@ -80411,7 +81964,7 @@
        Add a :distant-foreground to the lazy-highlight face
 
        * lisp/isearch.el (lazy-highlight): Add a :distant-foreground
-       colour so that the text is always legible (bug#16969).
+       color so that the text is always legible (bug#16969).
 
 2022-02-05  Lars Ingebrigtsen  <larsi@gnus.org>
 
@@ -80841,7 +82394,7 @@
        error will occur in x_composite_image as libXpm will load
        pixmaps of depth 16 instead of depth 32.
 
-       * src/image.c (x_create_x_image_and_pixmap): Explictly specify
+       * src/image.c (x_create_x_image_and_pixmap): Explicitly specify
        display depth.
        (x_create_xrender_picture):
        (xpm_load):
@@ -81097,7 +82650,7 @@
        of not being in dumping or bootstrap, since it is no longer needed.  
Test that
        'debug-early's symbol-function is bound.  Ensure there is enough 
working space
        in specpdl and eval_depth.
-       (syms_of_eval): New DEFSYM for Qdebug_early.  Initialise Vdebugger to
+       (syms_of_eval): New DEFSYM for Qdebug_early.  Initialize Vdebugger to
        Qdebug_early rather than Qnil.
 
 2022-02-02  Juri Linkov  <juri@linkov.net>
@@ -81169,7 +82722,7 @@
 
 2022-02-02  Po Lu  <luangruo@yahoo.com>
 
-       Make behaviour of `mouse-autoselect-window' consistent with X on NS
+       Make behavior of `mouse-autoselect-window' consistent with X on NS
 
        * src/nsterm.m ([EmacsView mouseMoved:]): Ignore if
        `selected_window' is a minibuffer window.
@@ -81185,7 +82738,7 @@
 
 2022-02-01  Po Lu  <luangruo@yahoo.com>
 
-       Improve behaviour of `mouse-autoselect-window' on Haiku
+       Improve behavior of `mouse-autoselect-window' on Haiku
 
        * src/haikuterm.c (haiku_read_socket): Don't select windows if
        the selected window is a minibuffer window or a popup is
@@ -81445,7 +82998,7 @@
 
        We used to store in `load-history` when an autoload is redefined as
        a non-autoload and in the `autoload` symbol property we used to store
-       the autoload data that used to be used before it got overriden.
+       the autoload data that used to be used before it got overridden.
 
        Instead, store the history of the function definition of
        a symbol in its `function-history` symbol property.
@@ -81839,7 +83392,7 @@
 
 2022-01-29  Lars Ingebrigtsen  <larsi@gnus.org>
 
-       Modernise the security section in the efaq a bit
+       Modernize the security section in the efaq a bit
 
        * doc/misc/efaq.texi (Security risks with Emacs): Remove the X
        bit, and add a bit about browsing the web (bug#24489).
@@ -82477,7 +84030,7 @@
        Minor `concat` tweaks
 
        * src/fns.c (concat): Do things in the right order for speed.
-       (concat_strings): Initialise variable.
+       (concat_strings): Initialize variable.
 
 2022-01-26  Lars Ingebrigtsen  <larsi@gnus.org>
 
@@ -82648,7 +84201,7 @@
        (Fappend, Fvconcat): Adapt to changed signature of concat.
        (Fcopy_sequence): Faster implementation for lists, strings, and vectors.
        (concat_strings): New.
-       (concat): Strip code for string target, simplify, optimise.
+       (concat): Strip code for string target, simplify, optimize.
        (Fcopy_alist): Use Fcopy_sequence.
 
 2022-01-25  Lars Ingebrigtsen  <larsi@gnus.org>
@@ -83912,7 +85465,7 @@
        Make diff--iterate-hunks more resilient
 
        * lisp/vc/diff-mode.el (diff--iterate-hunks): Ignore malformed
-       hunks instead of signalling errors (bug#53343).
+       hunks instead of signaling errors (bug#53343).
 
 2022-01-21  Shuguang Sun  <shuguang79@qq.com>
 
@@ -83936,7 +85489,7 @@
        than before, for example when a subcommand is concatenated in an
        argument.
 
-       * lisp/eshell/esh-cmd.el (eshell--find-subcommands): New fuction.
+       * lisp/eshell/esh-cmd.el (eshell--find-subcommands): New function.
        (eshell--invoke-command-directly): Use 'eshell-find-subcommands'.
 
        * test/lisp/eshell/eshell-tests.el
@@ -84662,7 +86215,7 @@
 
        Fix event timestamp generation on Haiku
 
-       * src/haikuterm.c (haiku_read_socket): Use miliseconds for event
+       * src/haikuterm.c (haiku_read_socket): Use milliseconds for event
        time.
 
 2022-01-18  Stefan Monnier  <monnier@iro.umontreal.ca>
@@ -84849,7 +86402,7 @@
 
        This fixes several issues: tooltips having no right internal
        border, reusing tooltips occasionally freezing Emacs, and
-       inconsistent behaviour when compared to X.
+       inconsistent behavior when compared to X.
 
        * src/haiku_support.cc (BWindow_resize): Revert a recent change.
        (BView_move_frame):
@@ -85295,7 +86848,7 @@
 
        * src/haiku_support.c (be_popup_file_dialog): Reduce idle
        processor load by increasing timeout.  The timeout is still too
-       low to be noticable by the user.
+       low to be noticeable by the user.
 
 2022-01-16  Po Lu  <luangruo@yahoo.com>
 
@@ -85419,7 +86972,7 @@
        mechanism.
        (byte-compile-function-warn): Replace byte-compile-last-position by a
        symbol-with-pos-pos call.
-       (compile-defun): Use local variable start-read-position to fulfil 
purpose of
+       (compile-defun): Use local variable start-read-position to fulfill 
purpose of
        old byte-compile-read-position.  Push the just read FORM onto
        byte-compile-form-stack.
 
@@ -85640,7 +87193,7 @@
 
        No longer strip positions from symbols before each use of a form, 
instead
        relying on the low level C routines to do the right thing.  Instead 
strip them
-       from miscellaneous places where this is needed.  Stip them alson in
+       from miscellaneous places where this is needed.  Strip them also in
        `function-put'.
 
        Push forms onto byte-compile-form-stack and pop them "by hand" rather 
than by
@@ -85816,7 +87369,7 @@
 
        * lisp/battery.el (battery-status-function): In Termux, neither
        /sys/ or /proc/ are readable on phones that are not rooted. This
-       patch makes Emacs verify if they are readable before it attemps
+       patch makes Emacs verify if they are readable before it attempts
        reading them (bug#53026).
 
 2022-01-14  Robert Pluim  <rpluim@gmail.com>
@@ -85875,7 +87428,7 @@
 
        * lisp/progmodes/python.el (python-shell-send-string-no-output): Don't
        let-bind comint-preoutput-filter-functions globally for all comint
-       processes.  Modify the behaviour of only the current python
+       processes.  Modify the behavior of only the current python
        process (bug#53219).
 
 2022-01-14  Robert Pluim  <rpluim@gmail.com>
@@ -85904,7 +87457,7 @@
        Merge from origin/emacs-28
 
        34ca4ff9a5 Fix Edebug specification for inline functions (Bug#53068).
-       3c06c37a8b Remove mention of removed `gnus-treat-play-sounds' variabl...
+       3c06c37a8b Remove mention of removed `gnus-treat-play-sounds' 
variable...
 
 2022-01-13  Po Lu  <luangruo@yahoo.com>
 
@@ -86777,7 +88330,7 @@
        This was found during the investigation surrounding bug#53136,
        but is not directly related.
 
-       * src/filelock.c (lock_if_free): Explictly test err against -1
+       * src/filelock.c (lock_if_free): Explicitly test err against -1
        or -2, and reverse sign of system errors on Haiku.  (No Haiku
        error occupies -1 or -2.)
 
@@ -87231,7 +88784,7 @@
 
 2022-01-07  Po Lu  <luangruo@yahoo.com>
 
-       Disable new input method behaviour by default on X
+       Disable new input method behavior by default on X
 
        * src/xfns.c (supported_xim_styles): Default to STYLE_NONE.
 
@@ -87818,7 +89371,7 @@
        here.
 
        * src/haikufns.c (haiku_visualize_frame):
-       (haiku_unvisualize_frame): Sychronize after visibility changes.
+       (haiku_unvisualize_frame): Synchronize after visibility changes.
 
 2022-01-03  Po Lu  <luangruo@yahoo.com>
 
@@ -88558,9 +90111,9 @@
        (emit_ctxt_code): Export the global 
F_SYMBOLS_WITH_POS_ENABLED_RELOC_SYM.
        (define_lisp_symbol_with_position, define_GET_SYMBOL_WITH_POSITION): New
        functions.
-       (Fcomp__init_ctxt): Initialise comp.bool_ptr_type, call the two new
+       (Fcomp__init_ctxt): Initialize comp.bool_ptr_type, call the two new
        define_.... functions.
-       (load_comp_unit): Initialise **f_symbols_with_pos_enabled_reloc.
+       (load_comp_unit): Initialize **f_symbols_with_pos_enabled_reloc.
 
        * src/fns.c (Fput): Strip positions from symbols in PROPNAME and VALUE.
 
@@ -89045,7 +90598,7 @@
 
 2021-12-27  Michael Albinus  <michael.albinus@gmx.de>
 
-       The temprary "session" collection might not exist in Secret Service
+       The temporary "session" collection might not exist in Secret Service
 
        * doc/misc/auth.texi (Secret Service API):
        * test/lisp/net/secrets-tests.el 
(secrets--test-delete-all-session-items)
@@ -89600,7 +91153,7 @@
 
        Changes:
        - structure the result of mm-dissect-buffer of application/pkcs7-mime
-         like a multipart mail so there is no loosing of information of
+         like a multipart mail so there is no losing of information of
          verification and decryption results which can now be displayed by
          gnus-mime-display-security
 
@@ -89616,7 +91169,7 @@
          to print "Encrypted" or "Signed" accordingly in the security button
 
        - adjust mm-possibly-verify-or-decrypt to check for smime-type to ask
-         wether to verify or decrypt the part and not to always ask to decrypt
+         whether to verify or decrypt the part and not to always ask to decrypt
 
        - adjust mm-view-pkcs7-decrypt and verify to call mm-sec-status so
          success information can be displayed by gnus-mime-display-security
@@ -89992,7 +91545,7 @@
        * src/xfns.c (Fx_set_mouse_absolute_pixel_position):
        * src/xterm.c (frame_set_mouse_pixel_position): Replace
        calls to XWarpPointer with calls to XIWarpPointer with
-       the client pointer explictly specified.  This avoids the
+       the client pointer explicitly specified.  This avoids the
        odd situation where the client pointer of the root window
        is not the client pointer of the frame.
 
@@ -90655,7 +92208,7 @@
 
        Remove incorrect byte-hunk-handler for `eval`
 
-       This optimisation is of very limited utility and miscompiles top-level
+       This optimization is of very limited utility and miscompiles top-level
        code having the form (eval 'CODE t) by replacing it with CODE which
        will then, as things currently stand, be evaluated with dynamic binding.
 
@@ -92005,7 +93558,7 @@
        be860c1385 Fix manual entry of 'quit-restore-window' (Bug#52328)
        35a96139df Clarify a comment in xdisp.c
        6ba2f028cf Revert "Grep alias `all' shall not match parent directory"
-       eb9e33e238 ; * etc/NEWS: Non-nil repeat-keep-prefix is not the defaul...
+       eb9e33e238 ; * etc/NEWS: Non-nil repeat-keep-prefix is not the 
default...
        538fc1d0e0 Fix mode-line display in Calendar mode
 
        # Conflicts:
@@ -93530,14 +95083,14 @@
        Remove separators at the beginning and end of the context menu
 
        * lisp/mouse.el (context-menu-map): Remove beginning/end
-       seperators (bug#52237).
+       separators (bug#52237).
 
 2021-12-03  Lars Ingebrigtsen  <larsi@gnus.org>
 
        Improve how dired-mark-sexp interprets file sizes in non-C locales
 
        * lisp/dired-x.el (dired-x--string-to-number): Try to understand
-       localised numbers (with "." separators or the like) (bug#23373).
+       localized numbers (with "." separators or the like) (bug#23373).
 
 2021-12-03  Stefan Kangas  <stefan@marxist.se>
 
@@ -93572,7 +95125,7 @@
 
 2021-12-03  Stefan Kangas  <stefan@marxist.se>
 
-       image-mode: Advertize viewing as text less eagerly
+       image-mode: Advertise viewing as text less eagerly
 
        * lisp/image-mode.el (image-text-based-formats): New defcustom.
        (image-mode--setup-mode): Don't show message to show image as text
@@ -93716,7 +95269,7 @@
        2be090d5d3 ; * ChangeLog.3: Minor fixes.
        9963b11bf7 ; * admin/authors.el (authors-aliases): Further updates.
        50b40e1d4f ; * lisp/org/ob-julia.el: Fix Author header for authors.el.
-       84166ea2e6 CC Mode: Recognise "struct foo {" as introducing a type de...
+       84166ea2e6 CC Mode: Recognize "struct foo {" as introducing a type de...
 
 2021-12-02  Lars Ingebrigtsen  <larsi@gnus.org>
 
@@ -93943,7 +95496,7 @@
 
        * lisp/pixel-scroll.el (pixel-scroll-precision-scroll-down)
        (pixel-scroll-precision-scroll-up): Take scroll margin into
-       accout.
+       account.
 
 2021-12-01  Po Lu  <luangruo@yahoo.com>
 
@@ -94360,7 +95913,7 @@
 
 2021-11-30  Andrea Corallo  <akrl@sdf.org>
 
-       Improve native compiler startup circular dependecy prevention mechanism
+       Improve native compiler startup circular dependency prevention mechanism
 
        * src/comp.c (maybe_defer_native_compilation): Update to accumulate
        delayed objects in `comp--delayed-sources'.
@@ -94382,7 +95935,7 @@
 
 2021-11-30  Mattias Engdegård  <mattiase@acm.org>
 
-       Generalise CPS-conversion let optimisation
+       Generalize CPS-conversion let optimization
 
        * lisp/emacs-lisp/generator.el (cps--transform-1):
        Eliminate a temporary for the last of any `let` form, not just for
@@ -94452,7 +96005,7 @@
 
        30553d889d Merge branch 'emacs-28' of git.savannah.gnu.org:/srv/git/e...
        ecf3bf66ba Remove problematic characters from modus-themes.org (bug#5...
-       de9d27f679 Avoid undefined behaviour when copying part of structure
+       de9d27f679 Avoid undefined behavior when copying part of structure
 
        # Conflicts:
        #       doc/misc/modus-themes.org
@@ -94925,7 +96478,7 @@
 
 2021-11-29  Andreas Schwab  <schwab@linux-m68k.org>
 
-       Avoid undefined behaviour when copying part of structure
+       Avoid undefined behavior when copying part of structure
 
        * src/dispnew.c (copy_row_except_pointers): Don't use address of
        subobject as starting point.
@@ -97333,7 +98886,7 @@
 
        * lisp/emacs-lisp/ert.el (ert-batch-backtrace-line-length): Fix
        docstring.
-       (ert-run-tests-batch): Remove redundand let-binding.
+       (ert-run-tests-batch): Remove redundant let-binding.
        (ert-run-tests-interactively): Fix interactive spec.
 
 2021-11-18  Mattias Engdegård  <mattiase@acm.org>
@@ -98175,7 +99728,7 @@
        Merge from origin/emacs-28
 
        5dbad52 gnus-summary-line-format doc string clarification
-       d4536ff Fix follow-scroll-down in a small buffer which starts slightl...
+       d4536ff Fix follow-scroll-down in a small buffer which starts 
slightly...
 
 2021-11-14  Eli Zaretskii  <eliz@gnu.org>
 
@@ -98335,7 +99888,7 @@
 
 2021-11-13  Michael Albinus  <michael.albinus@gmx.de>
 
-       Revert accidential commit in icomplete.el
+       Revert accidental commit in icomplete.el
 
 2021-11-13  Michael Albinus  <michael.albinus@gmx.de>
 
@@ -98401,7 +99954,7 @@
 
        Where c-record-found-types gets "bound" to itself, we postpone the 
calling of
        c-fontify-new-type on possible new found types until these are 
confirmed by
-       the return from the function tentatively finding these types, for 
exmaple
+       the return from the function tentatively finding these types, for 
example
        c-forward-<>-arglist.  We check this "binding" by testing the value of
        c-record-found-types.
 
@@ -100934,7 +102487,7 @@
        5e9b4e70ab Fix dbus-test04-register-method on CentOS (Bug#51369)
        d96de23510 * lisp/transient.el: Update to package version v0.3.7-11-g...
        7343b0d0e4 ; * etc/NEWS: Native compilation is more picky about missi...
-       0d6b2b0b9d ; * etc/PROBLEMS: Move entry about LLVM plugin to the righ...
+       0d6b2b0b9d ; * etc/PROBLEMS: Move entry about LLVM plugin to the 
right...
 
        # Conflicts:
        #       etc/NEWS
@@ -100991,7 +102544,7 @@
        (ns_glyph_metrics): Stop escaping names.
 
        (ns_spec_to_descriptor): Fix font descriptor creation for symbolic
-       font spec entires.
+       font spec entries.
        (ns_descriptor_to_entity): Create entries with the correct symbolic
        styles.
 
@@ -101763,11 +103316,11 @@
 
 2021-11-02  Mattias Engdegård  <mattiase@acm.org>
 
-       Optimise (cond) => nil at source level
+       Optimize (cond) => nil at source level
 
        * lisp/emacs-lisp/byte-opt.el (byte-optimize-cond):
-       Optimise clause-free `cond`, which can arise from earlier
-       transformations.  This enables further optimisations.
+       Optimize clause-free `cond`, which can arise from earlier
+       transformations.  This enables further optimizations.
        * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-tests--test-cases):
        Add test cases.
 
@@ -102644,10 +104197,10 @@
 
 2021-10-26  Stefan Kangas  <stefan@marxist.se>
 
-       image-dired: Improve mouse behaviour
+       image-dired: Improve mouse behavior
 
        * lisp/image-dired.el (image-dired-thumbnail-mode-map): Improve mouse
-       behaviour: ignore dragging, as it currently doesn't do anything
+       behavior: ignore dragging, as it currently doesn't do anything
        useful, and make all clicks just select the thumbnail.
        (image-dired-mouse-display-image)
        (image-dired-mouse-select-thumbnail): Move point to closest image
@@ -102758,7 +104311,7 @@
        strings. The code originally set that charset for any server with
        literal+ capability, borking all searches on an Exchange server. This
        code only sets utf-8 for multibyte search strings in particular, which
-       would be borken for Exchange anyway.
+       would be broken for Exchange anyway.
 
        * lisp/gnus/gnus-search.el (gnus-search-imap-search-command): Ensure
        we're only doing the literal+ dance for multibyte strings (multibyte
@@ -102933,7 +104486,7 @@
 
 2021-10-24  Lars Ingebrigtsen  <larsi@gnus.org>
 
-       Display a message if HMTL rendering takes a long time
+       Display a message if HTML rendering takes a long time
 
        * lisp/net/eww.el (eww-display-html): Display a message if HTML
        rendering takes a long time (bug#19776).
@@ -102956,7 +104509,7 @@
        This aims to fix the scenario where on jit-lock's first scan of a type, 
it is
        not recognized as such, and only later does this happen.  The 
fontification of
        such found types is now done by background scanning in short time slices
-       immediately after initialising the mode.
+       immediately after initializing the mode.
 
        * lisp/progmodes/cc-engine.el (c-add-type-1): New function.
        (c-add-type): Extract c-add-type-1 from it, and reformulate the 
mechanism for
@@ -103172,7 +104725,7 @@
        Make dired-x-guess-file-name-at-point obsolete
 
        * lisp/dired-x.el (dired-x-guess-file-name-at-point): Make
-       obsolete in favour of 'thing-at-point'.
+       obsolete in favor of 'thing-at-point'.
        (dired-x-read-filename-at-point): Use 'thing-at-point' instead of
        above obsolete function.
 
@@ -103209,7 +104762,7 @@
        * lisp/image-dired.el (exif): Require.
        (image-dired-cmd-read-exif-data-program)
        (image-dired-cmd-read-exif-data-options)
-       (image-dired-get-exif-data): Make obsolete in favour of using
+       (image-dired-get-exif-data): Make obsolete in favor of using
        exif.el.  This removes a dependency on external exiftool for some
        operations.
        (image-dired-get-exif-file-name)
@@ -103254,7 +104807,7 @@
        This aims to fix the scenario where on jit-lock's first scan of a type, 
it is
        not recognized as such, and only later does this happen.  The 
fontification of
        such found types is now done by background scanning in short time slices
-       immediately after initialising the mode.
+       immediately after initializing the mode.
 
        * lisp/progmodes/cc-engine.el (c-add-type-1): New function.
        (c-add-type): Extract c-add-type-1 from it, and reformulate the 
mechanism for
@@ -104586,7 +106139,7 @@
 
        Merge from origin/emacs-28
 
-       47e09d1855 Copy parent face attributes to tab-line-tab-current instea...
+       47e09d1855 Copy parent face attributes to tab-line-tab-current 
instead...
        d96f8b22c0 Another fix for 'ibuffer-shrink-to-fit' (Bug#7218, Bug#51029)
 
 2021-10-12  Glenn Morris  <rgm@gnu.org>
@@ -104918,7 +106471,7 @@
        315fe20086 ; * src/Makefile.in (../native-lisp): Add comment.
        47cbd103f5 * lisp/bindings.el (mode-line-position): Improve tooltip.
        35a752863a * lisp/progmodes/xref.el: Bump the version.
-       bbcd8cc1a9 Slight simplificaiton
+       bbcd8cc1a9 Slight simplification
        e139dd1b1e Fix doc strings of 2 categories
        59782839cb (xref--collect-matches-1): Remove some intermediate alloca...
        1c7d056f4d ; Fix two typos where em dash was written as en dash
@@ -105585,7 +107138,7 @@
        (term-ansi-face-already-done): Make obsolete
        (term--maybe-brighten-color): Remove
        (term--color-as-hex): New function
-       (term-handle-colors-array): Make obsolete in favour of the new
+       (term-handle-colors-array): Make obsolete in favor of the new
        function 'term--handle-colors-list'.
        (term--handle-colors-list): New function, that can also handle ANSI
        codes 38 and 48.
@@ -106426,7 +107979,7 @@
        Use project-files to know which directory watchers to skip
 
        The directory-finding logic is probably a bit slower than using
-       eglot--directories-recursively, but since it honours `.gitignores` and
+       eglot--directories-recursively, but since it honors `.gitignores` and
        ignores more directories it's much faster overall.  And guaranteed to
        create less watchers.
 
@@ -106438,7 +107991,7 @@
 
 2021-05-26  João Távora  <joaotavora@gmail.com>
 
-       Hard code an exception to "node_modules" directores
+       Hard code an exception to "node_modules" directories
 
        * eglot.el (eglot--directories-recursively): Fix.
 
@@ -106833,7 +108386,7 @@
        tremendeously slow down the process.  But this is only a suspicion.
 
        This commit tries some simple optimizations: if a directory is known
-       to be watch-worthy becasue one of its files matched a single glob, no
+       to be watch-worthy because one of its files matched a single glob, no
        more files under that directory are tried.  This should help somewhat.
 
        Also fixed a bug in 'eglot--files-recursively', though I suspect that
@@ -107246,7 +108799,7 @@
        Simplify dir-watching strategy of w/didchangewatchedfiles
 
        Instead of massaging the globPattern to match directories instead of
-       files, which is fragile, gather the list of directoris to watch by
+       files, which is fragile, gather the list of directories to watch by
        matching the globPattern against every file recursively (except hidden
        files and dirs).
 
@@ -107783,7 +109336,7 @@
        Only makes two changes: a deletion of the "// " and a replacement of a
        newline with a space character.  The second change fooled Eglot's fix
        for https://github.com/joaotavora/eglot/issues/259, by making a change 
similar to the one it is made to detect
-       and correct.  That fix should taget things that happen on the same
+       and correct.  That fix should target things that happen on the same
        line, this not being one of those things.
 
        * eglot.el (eglot--after-change): Only apply fix to 
https://github.com/joaotavora/eglot/issues/259 if
@@ -107897,7 +109450,7 @@
        * src/pgtkselect.c:
        * src/pgtkselect.h:
        * src/pgtkterm.c:
-       * src/pgtkterm.h: Update copyright dates - No Funtional Changes
+       * src/pgtkterm.h: Update copyright dates - No Functional Changes
 
 2020-11-23  Yuuki Harano  <masm+github@masm11.me>
 
@@ -108296,7 +109849,7 @@
 
        minimize gtkutil.c differences.
 
-       * src/pgtkterm.h: remove compiletime ifdefs
+       * src/pgtkterm.h: remove compile time ifdefs
 
        * src/gtkutil.h: block out unused decl
 
@@ -108345,7 +109898,7 @@
 
        * src/gtkutil.c (xg_create_frame_widgets):
 
-       hacky GTK offsets taht will need better calculations
+       hacky GTK offsets that will need better calculations
 
        Get parent frame's editor widget allocation for the offset
 
@@ -108511,7 +110064,7 @@
 
 2020-11-21  Yuuki Harano  <masm+github@masm11.me>
 
-       Make multipdisplay work by limiting selection while enabed
+       Make multipdisplay work by limiting selection while enabled
 
        * src/pgtkterm.c (pgtk_mouse_position):
 
@@ -108528,12 +110081,12 @@
 
 2020-11-21  Yuuki Harano  <masm+github@masm11.me>
 
-       Improve drawing efficency by refactoring code
+       Improve drawing efficiency by refactoring code
 
                * ../src/pgtkterm.c (fill_background, fill_background_by_face)
                (x_draw_glyph_string_background, x_draw_glyph_string_bg_rect)
                (x_draw_image_glyph_string, x_draw_stretch_glyph_string)
-               (pgtk_clear_under_internal_border): Refator duplcate code
+               (pgtk_clear_under_internal_border): Refator duplicate code
 
        更に効率化。
 
@@ -108849,7 +110402,7 @@
 
 2020-11-21  Yuuki Harano  <masm+github@masm11.me>
 
-       Simplify compilaiton condtion
+       Simplify compilation condition
 
                * ../src/menu.c (single_menu_item):
 
@@ -109221,7 +110774,7 @@
        Uses Eldoc's eldoc-documentation-functions variable.  In Eldoc v1.0.0
        that variable was already available as a way of handling/composing
        multiple docstrings from different sources, but it didn't work
-       practically with mutiple concurrent async sources.  This was fixed in
+       practically with multiple concurrent async sources.  This was fixed in
        1.1.0, which Eglot now requires.
 
        This fixes the synchronization problems reported in 
https://github.com/joaotavora/eglot/issues/494 and also
@@ -109467,7 +111020,7 @@
        use-package--foo--post-config-hook
 
        This should make config customisations more predictable (for example, 
spacemacs
-       uses these hooks extensively to allow 'layers' to be customised).
+       uses these hooks extensively to allow 'layers' to be customized).
 
        I got rid of the "special" default value for :config, because it 
doesn't seem to
        be treated any differently than nil.
@@ -109565,14 +111118,14 @@
 
 2020-05-02  João Távora  <joaotavora@gmail.com>
 
-       Kind of honour eldoc-echo-area-use-multiline-p
+       Kind of honor eldoc-echo-area-use-multiline-p
 
        A reworking of an idea and original implementation by Andrii
        Kolomoiets <andreyk.mad@gmail.com>.  It doesn't honor it completely
        because the semantics for a non-t, non-nil value are tricky.  And we
        don't always exactly know what the symbol prefix reliably.
 
-       * eglot.el (eglot--update-doc): Kind of honour
+       * eglot.el (eglot--update-doc): Kind of honor
        eldoc-echo-area-use-multiline-p.
 
        GitHub-reference: close https://github.com/joaotavora/eglot/issues/443
@@ -110204,7 +111757,7 @@
 
        Support markdown for textdocument/hover ()
 
-       * eglot.el (eglot-client-capabilities): annouce markdown support for 
hover.
+       * eglot.el (eglot-client-capabilities): announce markdown support for 
hover.
        (eglot--format-markup): Format hover info with Markdown.
 
        Fixes: https://github.com/joaotavora/eglot/issues/328
@@ -110401,7 +111954,7 @@
        completion.  When the completion is close to done, the :exit-function
        is called, to potentially rework the inserted text so that the final
        result might be quite different from the proxy (it might be a snippet,
-       or even a suprising text edit).
+       or even a surprising text edit).
 
        The most important change in this commit reworks the way the
        completion "bounds" are calculated in the buffer.  This is the region
@@ -110418,7 +111971,7 @@
        https://github.com/microsoft/language-server-protocol/issues/651, we
        have no choice but to play along with that inneficient and grotesque
        strategy to implement flex-style matching.  Like ever in LSP, we do so
-       while being backward-compatible to all previously supported behaviour.
+       while being backward-compatible to all previously supported behavior.
 
        * eglot.el (eglot-completion-at-point): rework.
 
@@ -110429,8 +111982,8 @@
        Always filter completions client-side by prefix
 
        Prefix completion is all we get in LSP because there are some servers
-       that send *all* completions everytime.  This is horrible, but it's the
-       currently defined behaviour.  See
+       that send *all* completions every time.  This is horrible, but it's the
+       currently defined behavior.  See
        https://github.com/microsoft/language-server-protocol/issues/651.
 
        * eglot.el (eglot-completion-at-point): Use all-completions.
@@ -110584,7 +112137,7 @@
        Unbreak elm language server which does use :triggercharacters
 
        Only query completionProvider -> triggerCharacter information if the
-       server has provided it.  Elm's, and probaly other's, do not provide
+       server has provided it.  Elm's, and probably other's, do not provide
        it, which doesn't mean they don't support completion.
 
        * eglot.el (eglot-completion-at-point): Check that completion
@@ -111371,7 +112924,7 @@
 
        Use eglot--dbind and eglot--lambda throughout
 
-       The default behaviour of these macros is to be lenient towards servers
+       The default behavior of these macros is to be lenient towards servers
        sending unknown keys, which should fix the issue.
 
        * eglot.el (eglot--lsp-interface-alist): Add a bunch of new interfaces.
@@ -111456,7 +113009,7 @@
 
        Support completioncontext to help servers like ccls
 
-       * eglot.el (eglot-client-capabilities): Annouce
+       * eglot.el (eglot-client-capabilities): Announce
        textDocument/completion/contextSupport.
        (eglot--CompletionParams): New helper.
        (eglot-completion-at-point): Use it.
@@ -112024,7 +113577,7 @@
 
        :ensure-system-package was installing packages by running
        system-packages-get-command via async-shell-command. This meant that
-       system-packages-use-sudo wasn't being honoured.
+       system-packages-use-sudo wasn't being honored.
 
        This patch makes :ensure-system-package use system-packages-install
        for all cases, except where a custom install command is supplied, in
@@ -112032,7 +113585,7 @@
 
        This issue was introduced in 9f034a0bcfdd8c4 
[https://github.com/jwiegley/use-package/issues/673], as a fix for
        [https://github.com/jwiegley/use-package/issues/661]. Prior to that 
commit, system-packages-use-sudo was being
-       honoured.
+       honored.
 
        This patch also fixes a bug where a cons containing a lone symbol in a
        list of conses causes nil to used as the package to install.
@@ -112117,7 +113670,7 @@
 
        Ignore extra keys in textdocument/publishdiagnostics ()
 
-       Accoding to the "discussion" in https://reviews.llvm.org/D50571, it
+       According to the "discussion" in https://reviews.llvm.org/D50571, it
        was deemed sufficient that VSCode is fine with the non-standard
        extension -- jt
 
@@ -112277,7 +113830,7 @@
 
        * eglot.el (eglot-sync-connect): New defcustom.
        (eglot-ensure, eglot): Simplify.
-       (eglot--connect): Honour eglot-sync-connect.  Complicate
+       (eglot--connect): Honor eglot-sync-connect.  Complicate
        considerably.
        (eglot-connect-timeout): New defcustom.
        (Package-requires): Require jsonrpc 1.0.6
@@ -112364,7 +113917,7 @@
        requiring command-line invocations that depend on the specific
        momentary environment.
 
-       * eglot.el (eglot-server-programs): CONTACT can be a fucntion of no
+       * eglot.el (eglot-server-programs): CONTACT can be a function of no
        arguments.
        (eglot--guess-contact, eglot--connect): Accept function
        CONTACTs.
@@ -112565,7 +114118,7 @@
 
 2018-07-09  João Távora  <joaotavora@gmail.com>
 
-       Jsonrpc.el is now a gnu elpa depedency
+       Jsonrpc.el is now a gnu elpa dependency
 
        * Makefile (ELFILES): Don't include jsonrpc.
        (jsonrpc-check): Remove target.
@@ -113035,7 +114588,7 @@
 
        Fix indentation f@#$%^ by previous commit
 
-       Courtesy of aggressive-indent-mode... Agressive it is...
+       Courtesy of aggressive-indent-mode... Aggressive it is...
 
 2018-06-09  João Távora  <joaotavora@gmail.com>
 
@@ -113175,7 +114728,7 @@
 
 2018-06-04  João Távora  <joaotavora@gmail.com>
 
-       Support purposedly ignoring a server capability
+       Support purposely ignoring a server capability
 
        * eglot.el (eglot-ignored-server-capabilites): New defcustom.
        (eglot--server-capable): Use it.
@@ -113472,7 +115025,7 @@
 
 2018-05-26  João Távora  <joaotavora@gmail.com>
 
-       Simpify eglot--server-receive
+       Simplify eglot--server-receive
 
        * eglot.el (eglot--obj): Cleanup whitespace.
        (eglot--server-receive): Simplify.
@@ -113854,16 +115407,16 @@
 
        Robustify timer handling for eglot--async-request
 
-       This basically cherry-picks an ealier commit for the jsonrpc-refactor
+       This basically cherry-picks an earlier commit for the jsonrpc-refactor
        branch:
          a2aa1ed..: João Távora 2018-05-18 Robustify timer handling for 
jrpc-async-request
 
        * jrpc.el (jrpc--async-request): Improve timeout handling. Return a 
list (ID TIMER)
-       (jrpc--request): Protect against user-quits, cancelling timer
+       (jrpc--request): Protect against user-quits, canceling timer
 
 2018-05-19  João Távora  <joaotavora@gmail.com>
 
-       Simplify some infrastructure fucntions
+       Simplify some infrastructure functions
 
        * eglot.el (eglot--contact): Simplify docstring.
        (eglot--make-process): Simplify.
@@ -113974,7 +115527,7 @@
 
        Instead of introspecting the :params or :result object to discover if
        an object is present, and changing the Elisp function call type
-       (funcall vs apply) accordingly, alway funcall. It's up to the
+       (funcall vs apply) accordingly, always funcall. It's up to the
        application to destructure if it wishes. jrpc-lambda can help with
        that and keep the application code simple.
 
@@ -114273,7 +115826,7 @@
 
 2018-05-10  João Távora  <joaotavora@gmail.com>
 
-       Prepare to sumbit to gnu elpa
+       Prepare to submit to gnu elpa
 
        * eglot.el: Update headers.
 
@@ -114314,7 +115867,7 @@
        (eglot--TextDocumentIdentifier)
        (eglot--VersionedTextDocumentIdentifier)
        (eglot--TextDocumentPositionParams, eglot--TextDocumentItem):
-       Renamed from the more verbose eglot--current-buffer-* variante.
+       Renamed from the more verbose eglot--current-buffer-* variant.
        (eglot-rename, eglot-imenu, eglot-eldoc-function)
        (eglot-completion-at-point, xref-backend-definitions)
        (xref-backend-identifier-at-point)
@@ -114407,7 +115960,7 @@
 
        Adjust flymake integration
 
-       When opening a new file (signalling textDocument/didOpen) it makes
+       When opening a new file (signaling textDocument/didOpen) it makes
        sense to call the flymake callback (if it exists) with no diagnostics,
        just to get rid of that "Wait", since we don't know if later in this
        callback cycle the server will ever report new diagnostics.
@@ -114822,9 +116375,9 @@
 
 2018-05-04  João Távora  <joaotavora@gmail.com>
 
-       Honour textdocumentsync
+       Honor textdocumentsync
 
-       * eglot.el (eglot--signal-textDocument/didChange): Honour 
textDocumentSync
+       * eglot.el (eglot--signal-textDocument/didChange): Honor 
textDocumentSync
 
 2018-05-04  João Távora  <joaotavora@gmail.com>
 
@@ -115224,7 +116777,7 @@
 
 2018-05-02  João Távora  <joaotavora@gmail.com>
 
-       Change status to error everytime an error is found
+       Change status to error every time an error is found
 
        * eglot.el (eglot--process-receive): Also set error status.
        (eglot--request): Fix a compilation warning.
@@ -116556,7 +118109,7 @@
        (next-overlay-change, previous-overlay-change, overlay-put)
        (overlay-get, report_overlay_modification, evaporate_overlays)
        (init_buffer_once): Adapt to changes and tree data-structure.
-       (overlay-lists, overlay-recenter): Funtions are now obsolete, but
+       (overlay-lists, overlay-recenter): Functions are now obsolete, but
        kept anyway.
        (set_buffer_overlays_before, set_buffer_overlays_after)
        (recenter_overlay_lists,fix_start_end_in_overlays,fix_overlays_before)
@@ -117210,7 +118763,7 @@
 
        This means (use-package foopkg :mode (".foo")) will add (".foo"
        . foopkg) into auto-mode-alist instead of the broken (".foo" . nil),
-       this is more consistent with the behaviour of (use-package foopkg
+       this is more consistent with the behavior of (use-package foopkg
        :mode (".foo" ".bar")).
 
 2016-10-31  Noam Postavsky  <npostavs@gmail.com>
@@ -117678,12 +119231,12 @@
 
        Merge pull request from waymondo/extend-bind-handler
 
-       Pass in symbol of bind macro, for more extensible re-use of same handler
+       Pass in symbol of bind macro, for more extensible reuse of same handler
        GitHub-reference: https://github.com/jwiegley/use-package/issues/259
 
 2015-09-23  Justin Talbott  <justin@waymondo.com>
 
-       pass in symbol of bind macro, for more extensible re-use of same handler
+       pass in symbol of bind macro, for more extensible reuse of same handler
 
        related to https://github.com/jwiegley/use-package/issues/258
 
@@ -118474,7 +120027,7 @@
 
        Lower-priority idle functions are run first. Idle functions with no
        specified priority default to 5 and all functions with the same priority
-       are run in the order in which they are evaluated, meaning the behaviour
+       are run in the order in which they are evaluated, meaning the behavior
        is backwards compatible.
 
        Updated documentation as well.
@@ -118606,7 +120159,7 @@
 
        Merge pull request from aspiers/docs
 
-       Synchronise docs and then remove one copy to prevent future issues.
+       Synchronize docs and then remove one copy to prevent future issues.
        GitHub-reference: https://github.com/jwiegley/use-package/issues/78
 
 2014-01-06  Adam Spiers  <emacs@adamspiers.org>
@@ -119361,14 +120914,14 @@
 
 This file records repository revisions from
 commit f2ae39829812098d8269eafbc0fcb98959ee5bb7 (exclusive) to
-commit d9e1605122b4ba70a55f7b168505b7d7f8d2bdd6 (inclusive).
+commit 92a7132bd6c76a43860fa01ca3363857d8dfc8f3 (inclusive).
 See ChangeLog.3 for earlier changes.
 
 ;; Local Variables:
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2022 Free Software Foundation, Inc.
+  Copyright (C) 2022, 2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/ChangeLog.android b/ChangeLog.android
index 8cc66c4d7ea..e86ef7a2a77 100644
--- a/ChangeLog.android
+++ b/ChangeLog.android
@@ -700,7 +700,7 @@
        (build-counter.c): New target.  Generate this file using
        makecounter.sh upon changes to lisp.mk or shortlisp.
        (lisp.mk): Make and load relative to abs_top_builddir.
-       (emacs$(EXEEXT)): Adjust acordingly.
+       (emacs$(EXEEXT)): Adjust accordingly.
        (mostlyclean): Remove build-counter.c.
 
 2023-07-18  Po Lu  <luangruo@yahoo.com>
@@ -735,7 +735,7 @@
        prototypes.
 
        * java/org/gnu/emacs/EmacsWindow.java (motionEvent): Set
-       cancelation flag in events sent where appropriate.
+       cancellation flag in events sent where appropriate.
 
        * lisp/touch-screen.el (touch-screen-handle-point-update):
        Improve treatment of horizontal scrolling near window edges.
@@ -749,7 +749,7 @@
        (struct android_touch_event): New field `flags'.
 
        * src/androidterm.c (handle_one_android_event): Report
-       cancelation in TOUCHSCREEN_END_EVENTs.
+       cancellation in TOUCHSCREEN_END_EVENTs.
 
        * src/keyboard.c (make_lispy_event): Fix botched merge.
 
@@ -1005,7 +1005,7 @@
 
        * java/org/gnu/emacs/EmacsWindow.java (Coordinate): New fields
        `button' and `id'.
-       (<init>): Add new arguments to the construtor.
+       (<init>): Add new arguments to the constructor.
        (whatButtonWasIt): Return 0 if the button state has not changed.
        (buttonForEvent): New function.
        (figureChange): Return the Coordinate object associated to EVENT.
@@ -2384,7 +2384,7 @@
        (sfnt_read_avar_table): Fix sequencing problem.
 
        * src/sfntfont.c (sfntfont_setup_interpreter): Don't create
-       interpreter for blatently broken fonts.
+       interpreter for blatantly broken fonts.
        (sfntfont_open): Avoid specifying redundant blends.
 
        * src/sfnt.c (sfnt_validate_gs): Fix validation of projection
@@ -3466,7 +3466,7 @@
        (src/verbose.mk): Depend on verbose.mk.android in srcdir.
        (lib/Makefile): Edit srcdir and VPATH to LIB_SRCDIR.
        (src/Makefile): Edit -I$$(top_srcdir) to -I../$(srcdir)/lib,
-       instead of ommitting it.
+       instead of omitting it.
        (clean): Allow ndk-build clean to fail.
 
        * java/Makefile.in (builddir): New variable.
@@ -3714,7 +3714,7 @@
        module detection.
 
        * src/android.c (android_run_select_thread): Fix typos.
-       (android_run_select_thread): Lock select_mutex before signalling
+       (android_run_select_thread): Lock select_mutex before signaling
        condition variable.
        (android_select): Unlock event queue mutex prior to waiting for
        it.
@@ -4663,7 +4663,7 @@
        (ndk_CONFIG_FILES): Export NDK_BUILD_CFLAGS.
 
        * java/AndroidManifest.xml.in: Prevent the Emacs activity from
-       being overlayed by the emacsclient wrapper.
+       being overlaid by the emacsclient wrapper.
        * java/org/gnu/emacs/EmacsOpenActivity.java (run): Likewise.
        (onCreate): Set an appropriate theme on ICS and up.
 
@@ -5151,7 +5151,7 @@
        * m4/ndk-build.m4 (ndk_package_mape): Add package mapping for
        sqlite3.
 
-       * src/Makefile.in (SQLITE3_CFLAGS): New substition.
+       * src/Makefile.in (SQLITE3_CFLAGS): New substitution.
        (EMACS_CFLAGS): Add that variable.
 
        * src/android.c (android_api_level): New variable.
@@ -5532,7 +5532,7 @@
        (touch-screen-precision-scroll): New user option.
        (touch-screen-handle-scroll): Use traditional scrolling by
        default.
-       (touch-screen-handle-touch): Adust format of
+       (touch-screen-handle-touch): Adjust format of
        touch-screen-current-tool.
        (touch-screen-track-tap): Don't print waiting for events.
        (touch-screen-track-drag): Likewise.  Also, don't call UPDATE
@@ -5555,7 +5555,7 @@
        * lisp/ls-lisp.el (ls-lisp-use-insert-directory-program): Default
        to off on Android.
 
-       * src/android.c (android_is_directory): New fucntion.
+       * src/android.c (android_is_directory): New function.
        (android_fstatat): Handle directories created by
        `android_opendir'.
        (android_open): Return meaningful file mode.
@@ -5645,7 +5645,7 @@
        * java/org/gnu/emacs/EmacsNative.java (EmacsNative): Make all
        event sending functions return long.
 
-       * java/org/gnu/emacs/EmacsPreferencesActivity.java: New fle.
+       * java/org/gnu/emacs/EmacsPreferencesActivity.java: New file.
 
        * java/org/gnu/emacs/EmacsService.java (EmacsService)
        (onStartCommand, onCreate, startEmacsService): Start as a
@@ -6310,7 +6310,7 @@
        and `detectMouse'.
        (struct android_event_queue, android_init_events)
        (android_next_event, android_write_event): Remove write limit.
-       (android_file_access_p): Handle directories correcty.
+       (android_file_access_p): Handle directories correctly.
        (android_close): Fix coding style.
        (android_fclose): New function.
        (android_init_emacs_service): Initialize new methods.
@@ -7261,7 +7261,7 @@ and those made after the Android port was installed.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2023 Free Software Foundation, Inc.
+  Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/GNUmakefile b/GNUmakefile
index 014a98ca32e..16064672c65 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -1,6 +1,6 @@
 # Build Emacs from a fresh tarball or version-control checkout.
 
-# Copyright (C) 2011-2023 Free Software Foundation, Inc.
+# Copyright (C) 2011-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/INSTALL b/INSTALL
index 477ac16ba71..2aaa02f37d7 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,5 +1,5 @@
 GNU Emacs Installation Guide
-Copyright (C) 1992, 1994, 1996-1997, 2000-2023 Free Software Foundation,
+Copyright (C) 1992, 1994, 1996-1997, 2000-2024 Free Software Foundation,
 Inc.
 See the end of the file for license conditions.
 
diff --git a/INSTALL.REPO b/INSTALL.REPO
index ea88842cfa9..77d8153a5a8 100644
--- a/INSTALL.REPO
+++ b/INSTALL.REPO
@@ -98,7 +98,7 @@ never platform-specific.
 
 
 
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/Makefile.in b/Makefile.in
index 45540d2742f..5f3227a9ad5 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 1992-2023 Free Software Foundation, Inc.
+# Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/README b/README
index 694b3aa4c94..c0b4df650e1 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/admin/ChangeLog.1 b/admin/ChangeLog.1
index ed8b148b99b..65f0b94c071 100644
--- a/admin/ChangeLog.1
+++ b/admin/ChangeLog.1
@@ -2577,7 +2577,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/admin/README b/admin/README
index 37e55005571..419039b4fba 100644
--- a/admin/README
+++ b/admin/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
@@ -39,6 +39,11 @@ Build Emacs in various ways.
 
 Install emacs quickly ("incrementally").
 
+** run-codespell
+
+Run the codespell tool on the Emacs sources.  Requires codespell to be
+installed first.
+
 ** alloc-colors.c
 
 A utility program that allocates a given number of colors on X.  Can
@@ -57,15 +62,16 @@ Tests for custom types and load problems.
 Show files added/removed between two tar files.
 
 
-Brief description of sub-directories:
+* Brief description of sub-directories.
 
 charsets               scripts for generating charset map files
                        in ../etc/charsets
-coccinelle             patches to make coccinelle work with
-                       the latest Emacs version.  Since they
-                       apply a few minor changes in Emacs internals
-                       in multiple places, they are trivial for
-                       copyright purposes.
+coccinelle             semantic patches for use with the static code
+                       analyzer coccinelle.  Since they apply a few
+                       minor changes in Emacs internals in multiple
+                       places, they are trivial for copyright
+                       purposes.
+codespell              supporting files for the run-codespell script.
 grammars               wisent and bovine grammars, used to produce
                        files in lisp/cedet/.
 notes                  miscellaneous notes related to administrative
diff --git a/admin/admin.el b/admin/admin.el
index 1f4c6986b0e..7fa2727aeb7 100644
--- a/admin/admin.el
+++ b/admin/admin.el
@@ -1,6 +1,6 @@
 ;;; admin.el --- utilities for Emacs administration  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/admin/alloc-colors.c b/admin/alloc-colors.c
index 6bd857e393b..25910ad9148 100644
--- a/admin/alloc-colors.c
+++ b/admin/alloc-colors.c
@@ -1,6 +1,6 @@
 /* Allocate X colors.  Used for testing with dense colormaps.
 
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/admin/authors.el b/admin/authors.el
index 7fb616ac0b7..6c74f4dd7a1 100644
--- a/admin/authors.el
+++ b/admin/authors.el
@@ -1,6 +1,6 @@
 ;;; authors.el --- utility for maintaining Emacs's AUTHORS file  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Gerd Moellmann <gerd@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
@@ -218,6 +218,8 @@ files.")
     ("Simen Heggestøyl" "simenheg@gmail.com")
     (nil "prime.wizard")
     ("Shun-ichi Goto" "Shun-ichi GOTO")
+    ;; The trailing dash is a kludge, so this contributor is not ignored.
+    ("skykanin-" "skykanin@users\\.noreply\\.github\\.com")
     ;; There are other Stefans.
 ;;;    ("Stefan Monnier" "Stefan")
     ("Steven L. Baur" "SL Baur" "Steven L Baur")
diff --git a/admin/automerge b/admin/automerge
index b01e866ab61..e751183f5f4 100755
--- a/admin/automerge
+++ b/admin/automerge
@@ -1,7 +1,7 @@
 #!/bin/bash
 ### automerge - automatically merge the Emacs release branch to master
 
-## Copyright (C) 2018-2023 Free Software Foundation, Inc.
+## Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ## Author: Glenn Morris <rgm@gnu.org>
 ## Maintainer: Stefan Kangas <stefankangas@gmail.com>
diff --git a/admin/build-configs b/admin/build-configs
index 5447a7a3476..74418c5c090 100755
--- a/admin/build-configs
+++ b/admin/build-configs
@@ -1,7 +1,7 @@
 #! /usr/bin/perl
 # Build Emacs in several different configurations.
 
-# Copyright (C) 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/admin/charsets/Makefile.in b/admin/charsets/Makefile.in
index efb9106adad..0a3f334a978 100644
--- a/admin/charsets/Makefile.in
+++ b/admin/charsets/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 2015-2023 Free Software Foundation, Inc.
+# Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 # Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
 #   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/admin/charsets/mapconv b/admin/charsets/mapconv
index 19e2ff8d8f7..91d580e89d1 100755
--- a/admin/charsets/mapconv
+++ b/admin/charsets/mapconv
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-# Copyright (C) 2015-2023 Free Software Foundation, Inc.
+# Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 # Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
 #   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/admin/charsets/mapfiles/README b/admin/charsets/mapfiles/README
index 30889c9e9ef..81dad59290d 100644
--- a/admin/charsets/mapfiles/README
+++ b/admin/charsets/mapfiles/README
@@ -1,4 +1,4 @@
-Copyright (C) 2009-2023 Free Software Foundation, Inc.
+Copyright (C) 2009-2024 Free Software Foundation, Inc.
 Copyright (C) 2009, 2010, 2011
   National Institute of Advanced Industrial Science and Technology (AIST)
   Registration Number H13PRO009
diff --git a/admin/check-man-pages b/admin/check-man-pages
index 3fb87dd1b89..8f05b75d81c 100755
--- a/admin/check-man-pages
+++ b/admin/check-man-pages
@@ -1,7 +1,7 @@
 #!/bin/bash
 ### check-man-pages - check man pages for errors
 
-## Copyright (C) 2022-2023 Free Software Foundation, Inc.
+## Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ## Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/admin/coccinelle/alloc_cast.cocci 
b/admin/coccinelle/alloc_cast.cocci
new file mode 100644
index 00000000000..91810dbc7e4
--- /dev/null
+++ b/admin/coccinelle/alloc_cast.cocci
@@ -0,0 +1,6 @@
+// Remove redundant casts from memory allocation functions.
+@@
+type T;
+@@
+-(T *)
+ \(xmalloc\|xzalloc\|xrealloc\|xpalloc\|xnrealloc\)(...)
diff --git a/admin/coccinelle/build_string.cocci 
b/admin/coccinelle/build_string.cocci
index d47727018dd..9421a140658 100644
--- a/admin/coccinelle/build_string.cocci
+++ b/admin/coccinelle/build_string.cocci
@@ -4,3 +4,9 @@ identifier I;
 @@
 - make_string (I, strlen (I))
 + build_string (I)
+
+@@
+constant C;
+@@
+- make_string (C, strlen (C))
++ build_string (C)
diff --git a/admin/coccinelle/nilp.cocci b/admin/coccinelle/nilp.cocci
new file mode 100644
index 00000000000..ccebbbe1c80
--- /dev/null
+++ b/admin/coccinelle/nilp.cocci
@@ -0,0 +1,6 @@
+// Prefer NILP (x) to EQ (x, Qnil)
+@@
+expression X;
+@@
+- EQ (X, Qnil)
++ NILP (X)
diff --git a/admin/coccinelle/unibyte_string.cocci 
b/admin/coccinelle/unibyte_string.cocci
index 0ff8cafa15d..97f87e5a4ca 100644
--- a/admin/coccinelle/unibyte_string.cocci
+++ b/admin/coccinelle/unibyte_string.cocci
@@ -4,3 +4,9 @@ identifier I;
 @@
 - make_unibyte_string (I, strlen (I))
 + build_unibyte_string (I)
+
+@@
+constant C;
+@@
+- make_unibyte_string (C, strlen (C))
++ build_unibyte_string (C)
diff --git a/admin/coccinelle/xsave.cocci b/admin/coccinelle/xsave.cocci
deleted file mode 100644
index 5172bb55b33..00000000000
--- a/admin/coccinelle/xsave.cocci
+++ /dev/null
@@ -1,11 +0,0 @@
-// Adjust users of XSAVE_POINTER and XSAVE_INTEGER.
-@@
-expression E;
-@@
-(
-- XSAVE_POINTER (E)
-+ XSAVE_POINTER (E, 0)
-|
-- XSAVE_INTEGER (E)
-+ XSAVE_INTEGER (E, 1)
-)
diff --git a/admin/codespell/README b/admin/codespell/README
new file mode 100644
index 00000000000..fcc5e3b41d0
--- /dev/null
+++ b/admin/codespell/README
@@ -0,0 +1,27 @@
+This directory contains supporting files for running codespell.
+See the ./admin/run-codespell script.
+
+codespell.dictionary
+
+    This file contains additional, Emacs-specific corrections.  When
+    fixing typos in Emacs, consider adding them to this file.
+
+codespell.exclude
+
+    This file contains lines that are correct and should be ignored by
+    codespell.  Add any false positives to this file.
+
+    The lines must match lines in the Emacs source tree exactly,
+    including any whitespace.
+
+codespell.ignore
+
+    This file contains any words that are correct in the context of
+    Emacs, or that we otherwise choose to ignore.  Use your best
+    judgment when adding words to this file.  Common typos that are
+    only correct in highly specific contexts should probably be in
+    codespell.exclude instead.
+
+codespell.rc
+
+    This file contains the Emacs specific codespell configuration.
diff --git a/admin/codespell/codespell.dictionary 
b/admin/codespell/codespell.dictionary
new file mode 100644
index 00000000000..b082a48fe99
--- /dev/null
+++ b/admin/codespell/codespell.dictionary
@@ -0,0 +1,17 @@
+alis->alist, alias, alas, axis, alms,
+boostrap-clean->bootstrap-clean
+brunches->branches
+defalis->defalias
+defalises->defaliases
+ecmacs->emacs
+ehsell->eshell
+emcs->emacs
+finis->finish
+firs->first
+file-writeable-p->file-writable-p
+hep->help
+least-favourite->least-favorite
+lien->line
+liens->lines
+mecas->emacs
+sehell->eshell, shell,
diff --git a/admin/codespell/codespell.exclude 
b/admin/codespell/codespell.exclude
new file mode 100644
index 00000000000..416d79cf131
--- /dev/null
+++ b/admin/codespell/codespell.exclude
@@ -0,0 +1,1585 @@
+  say "And this happens inbetween";
+        @ture)
+       ($sig,$na,@ture)
+($sig,$na,@ture)
+@ture)
+((squery 10 "SQUERY alis :help list")
+ (0.01 ":Alis@hub.uk NOTICE tester :See also: HELP EXAMPLES"))
+ (0.04 ":Alis@hub.uk NOTICE tester :[...]")
+ (0.01 ":Alis@hub.uk NOTICE tester :/SQUERY Alis LIST mask [-options]")
+ (0.08 ":Alis@hub.uk NOTICE tester :Searches for a channel")
+        (erc-scenarios-common-say "/SQUERY alis help list")
+  (should (equal '((regexp . "(string-match-p \"^[fo]+\" \"foobar\")\n    => 
0"))
+       (or "comm" "comma" "comman" "command" "commands"
+      (when (and (not (or skipp erc-timestamp-format))
+      (unless skipp
+           (skipp (or (and erc-stamp--skip-when-invisible invisible)
+;; if you type "foo", but typing just "fo" doesn't show the preview.
+ (Emacs main thre), pid 32619 (org.gnu.emacs)
+F DEBUG   : pid: 32619, tid: 32644, name: Emacs main thre  >>> org.gnu.emacs 
<<<
+       bnez    $t2, .filld             # start filling longs
+       j       .filld                  # fill either doubleword or byte
+.filld:
+
+ (0.01 ":bob!~u@q2weir96jk3r2.irc PRIVMSG #chan :[06:08:40] alice: My sons 
would never so dishonour me.")
+           interger intger lits bool boolen constant filename
+                with typess = (sort (mapcar #'comp-supertypes
+                for types in typess
+;; FIXME: normalise `seq', both the construct and implicit sequences,
+;; `intersection', we may end up normalising subtrees multiple times
+;; One way to avoid this is to aggressively normalise the entire tree
+;; Such normalisation could normalise synonyms, eliminate `minimal-match'
+                  ;; Normalise the constructor to `or' and the args 
recursively.
+  "Intersection of the normalised FORMS, as an interval set."
+FORM must be normalised (from `rx--normalise-char-pattern')."
+  "Optimise `or' arguments.  Return a new rx form.
+Each element of ARGS should have been normalised using
+    (search-forward "retur")             ; leaves point before the "n"
+with typess = (sort (mapcar #'comp-supertypes
+               (font-spec :registry "iso10646-1" :otf '(khmr nil (pres)))))
+(0.01 ":bob!~u@q2weir96jk3r2.irc PRIVMSG #chan :[06:08:40] alice: My sons 
would never so dishonour me.")
+ (0.05 ":bob!~u@q2weir96jk3r2.irc PRIVMSG #chan :alice: Pawn me to this your 
honour, she is his."))
+        (funcall expect 1 "Entirely honour"))
+ (0 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :You have paid the heavens your 
function, and the prisoner the very debt of your calling. I have laboured for 
the poor gentleman to the extremest shore of my modesty; but my brother justice 
have I found so severe, that he hath forced me to tell him he is indeed 
Justice.")
+ (0.00 ":irc.example.net 501 tester x :is not a recognised user mode.")
+ (0.00 ":irc.example.net 501 dummy` x :is not a recognised user mode.")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #utf-8 :alice: Entirely honour; I 
would not be delay'd."))
+           integer integer list bool boolean constant filename
+           "def" "defi" "defin" "define"
+           "doc" "docu" "docum" "docume" "documen" "document"
+         case Aadd : overflow = ckd_add (&a, accum, next); break;
+   And this the second, again with the same distinction therefrom.
+Bonus: Return a cons cell: (COMPILED . UPTODATE).
+Bonus: Return a cons cell: (COMPILED . UPTODATE)."
+(defun semantic-grammar-create-package (&optional force uptodate)
+If the Lisp code seems up to date, do nothing (if UPTODATE
+         (if uptodate (setq output nil)))
+;; Updated by the RIPE Network Coordination Center.
+;; Thanks to jond@miter.org (Jonathan Doughty) for help with code for
+    \"VHDL Modeling Guidelines\".
+# PCRE LICENSE
+#   General Purpose Licence (GPL), or Lesser General Purpose Licence (LGPL),
+#   then the terms of that licence shall supersede any condition above with
+   Li, Luo et al. "The CRI-CAM02UCS colour rendering index." COLOR research
+   Luo et al. "Uniform colour spaces based on CIECAM02 colour appearance
+        "[o]utput/save MIME part; save [a]ll parts; \n"
+;;  Jari Aalto <jaalto@tre.tele.nokia.fi>
+;;  Alon Albert <alon@milcse.rtsg.mot.com>
+;;                  Jari Aalto <jaalto@tre.tele.nokia.fi>.
+  ("IRCnet: EU, AT, Linz" IRCnet "linz.irc.at" ((6666 6668)))
+                  ["Januar" "Februar" "März" "April" "Mai" "Juni" "Juli" 
"August"
+Both types of item should be moved en bloc to the new category,
+      return dum// -7-
+      struct Dum {
+      mutable a::b::Foo::Dum dumdum;
+    "Mot de Passe :" ; localized (Bug#29729)
+       (leapyear, ydhms_diff, guess_time_tm, __mktime_internal): Use it.
+       * config.bat: Build-in the first step towards X11 support with
+       * configure.ac (emacs_config_features): Don’t worry about GIR.
+       * configure.ac (WEBKIT, GIR, CAIRO): Use EMACS_CHECK_MODULES, not PKG_.
+       * configure.ac (emacs_config_features): Add XWIDGETS, WEBKIT, GIR.
+1995-04-20  Kevin Rodgers  <kevinr@ihs.com>
+(seq-mapn #'concat '("moskito" "bite") ["bee" "sting"])
+Steven E. Harris (seh at panix.com),
+Kevin Rodgers (kevin.rodgers at ihs.com),
+plot,x,alog(x+5*sin(x) + 2),
+be shown.  On positions 3,4, and 7, the @samp{alog} function will be
+As is my wont, I started hacking on it almost immediately. I first
+The latter criterion is the "je ne sais quoi" of the artistic aspect of
+order but are now listed consecutively en bloc.
+      "mot de passe" "Mot de passe")
+       Reported by Mor Zahavi <morzahavi@me.com>.  (Bug#51271)
+       * etc/refcards/fr-refcard.tex (section{Formater}): Remove mention
+       Reported by Ture Pålsson.
+       9261a219ec * doc/emacs/windows.texi (Window Convenience): Describe 
mor...
+       650a664ccd Let imenu to work on the menu bar when its list is a singl...
+             "\\(?:Currentl?y\\|Now\\) drawing from '\\(AC\\|Battery\\) Power'"
+             ;; Move done items en bloc to top of done items section.
+       * erc-complete.el: * added docfixes (thanks ore)
+  (interactive "DDelete directory from file cache: ")
+   some Agian scripts.  */
+       Rename from "Gnus Maintainance Guide".
+       * gnus-coding.texi (Gnus Maintainance Guide): Update to mention Emacs
+       * gnus-coding.texi (Gnus Maintainance Guide): Fix title typo.
+       * gnus-coding.texi (Gnus Maintainance Guide): Update conventions for
+2005-10-23  Lars Hansen  <larsh@soem.dk>
+1998-07-17  Gordon Matzigkeit  <gord@fig.org>
+1998-04-26  James Troup  <J.J.Troup@scm.brad.ac.uk>
+2003-06-11  Daniel Néri  <done@mayonnaise.net>
+2001-07-26 10:00:00  Steven E. Harris  <seh@speakeasy.org>
+2001-01-15  Jack Twilley  <jmt@tbe.net>
+       matching LAMDA as a word.  Noted by Stefan Monnier.
+       completion variant for every "LAMDA" name (bug#30513).
+                           "foto"
+           ("foto" . 0.375)
+       Add configury for GMP library
+       Include w32inevt.h, basetyps.h and unknwn.h.
+       * make-docfile.c (write_c_args): Correctly handle prefixes of "defalt".
+       * hexl.c [DOSNT]: Include fcntl.h.
+       * make-docfile.c (write_c_args): Print an argument named "defalt"
+2003-03-07  Kevin Rodgers  <kevin.rodgers@ihs.com>  (tiny change)
+2003-03-06  Kevin Rodgers  <kevin.rodgers@ihs.com>  (tiny change)
+       "Speedwave", "Simili", "Synopsys Design Compiler", "Cadence NC",
+       with-parsed-tramp-file-name macro which is wont to produce such stuff.
+2004-12-29  Sanghyuk Suh  <han9kin@mac.com>
+2007-02-28  Lars Hansen  <larsh@soem.dk>
+2006-11-24  Lars Hansen  <larsh@soem.dk>
+2006-10-29  Lars Hansen  <larsh@soem.dk>
+2006-09-12  Lars Hansen  <larsh@soem.dk>
+2006-06-23  Lars Hansen  <larsh@soem.dk>
+2006-05-14  Lars Hansen  <larsh@soem.dk>
+2006-05-13  Lars Hansen  <larsh@soem.dk>
+2006-02-09  Lars Hansen  <larsh@soem.dk>
+2006-02-06  Lars Hansen  <larsh@soem.dk>
+2005-11-22  Lars Hansen  <larsh@soem.dk>
+2005-11-08  Lars Hansen  <larsh@soem.dk>
+2005-11-03  Lars Hansen  <larsh@soem.dk>
+2005-11-02  Lars Hansen  <larsh@soem.dk>
+2005-10-08  Lars Hansen  <larsh@soem.dk>
+2005-08-10  Lars Hansen  <larsh@soem.dk>
+2005-07-12  Lars Hansen  <larsh@soem.dk>
+2011-02-22  Seppo Sade  <sepposade1@gmail.com>  (tiny change)
+2012-09-21  Joel Bion  <jpbion@westvi.com>  (tiny change)
+       * rmail.el: Major changes from Bob Weiner <weiner@pts.mot.com>
+       * rmailsum.el: Big rewrite from weiner@pts.mot.com.
+1995-05-19  Kevin Rodgers  <kevinr@ihs.com>  (tiny change)
+1994-08-29  Tom Tromey  (tromey@creche.colorado.edu)
+1994-07-11  Kevin Rodgers  <kevinr@ihs.com>  (tiny change)
+1994-06-17  Kevin Rodgers  (kevinr@ihs.com)  (tiny change)
+1995-12-13  Kevin Rodgers  <kevinr@ihs.com>
+1995-11-10  Kevin Rodgers  <kevinr@ihs.com>
+1995-06-30  Kevin Rodgers  <kevinr@ihs.com>
+1998-07-07  Kevin Rodgers  <kevinr@ihs.com>  (tiny change)
+1998-06-03  Kevin Rodgers  <kevinr@ihs.com>  (tiny change)
+1997-12-22  Kevin Rodgers  <kevinr@ihs.com>  (tiny change)
+1997-11-02  Kevin Rodgers  <kevinr@ihs.com>
+1997-10-21  Brad Howes  <bhowes@cssun3.corp.mot.com>
+1997-06-22  Howard Melman  <melman@absolut.osf.org>
+1997-03-24  Kevin Rodgers  <kevinr@ihs.com>
+1996-11-04  Kevin Rodgers  <kevinr@ihs.com>
+1996-10-20  Kevin Rodgers  <kevinr@ihs.com>
+1996-09-12  Kevin Rodgers  <kevinr@ihs.com>
+1999-11-16  Reto Zimmermann  <reto@synopsys.com>
+1999-06-12  Reto Zimmermann  <reto@synopsys.com>
+1999-05-15  Reto Zimmermann  <reto@Synopsys.COM>
+1998-08-26  Kevin Rodgers  <kevinr@ihs.com>  (tiny change)
+       directories.  From Kevin Rodgers <kevinr@ihs.com>.
+   "du Radis"              "de la Ruche"           "du Gainier"
+       Iinclude string.h, stdlib.h unconditionally.
+2006-04-23  Lars Hansen  <larsh@soem.dk>
+2006-04-20  Lars Hansen  <larsh@soem.dk>
+2005-11-10  Lars Hansen  <larsh@soem.dk>
+       explicitly sets the defalt value.
+       Unexpect wait_object in case of x errors (memory leak).
+       (receive_incremental_selection): Don't unexpect wait_object when done
+       append "CCL: Quitted" when the CCL program is quitted.
+       the loop.  When quitted, show a proper error message.
+       (read_minibuf_noninteractive): If defalt is cons, set val to its car.
+       (read_minibuf): If defalt is cons, set histstring to its car.
+       (Fcompleting_read): If defalt is cons, set val to its car.
+       but it still has blocs in it, don't return it to the system,
+       any, in the DEFALT argument into the root of the Emacs build or
+       * fileio.c (Fexpand_file_name): Default DEFALT at beginning,
+1992-03-03  Wilson H. Tien  (wtien@urbana.mcd.mot.com)
+       * fileio.c (Fexpand_file_name): Pass DEFALT through
+       * ralloc.c (relocate_some_blocs): Handle BLOC == NIL_BLOC.
+       malloc heap, zero it out even if we don't have any blocs in the
+       (r_alloc_sbrk): Provide hysteresis in relocating the blocs.
+       (get_bloc): Return zero if we can't allocate the new bloc.
+       * ralloc.c (r_re_alloc): Instead of allocating a new bloc at the
+       original bloc, just expand the original block.  This saves a copy
+       If string quotes don't match up, don't take value from OFROM;
+       Globally replaced INTERRUPTABLE with INTERRUPTIBLE.
+       * fileio.c (Fread_file_name): If defalt is nil and user tries to use
+1995-03-23  Kevin Rodgers  <kevinr@ihs.com>  (tiny change)
+       * fileio.c (Fexpand_file_name): Look for a handler for defalt.
+1994-09-21  Tom Tromey  <tromey@creche.colorado.edu>
+       (r_alloc_sbrk): Refuse to move blocs, if frozen.
+1994-08-26  Kevin Rodgers  <kevinr@ihs.com>
+       (Fcall_process_region) [DOSNT]: Canonicalize slashes in filename.
+       * minibuf.c (read_minibuf): Do use DEFALT in place of empty input
+       * minibuf.c (read_minibuf): Return DEFALT here, if minibuffer is empty.
+       (read_minibuf): Now static.  New arg DEFALT.  Callers changed.
+       CHAR_TABLE_ORDINARY_SLOTS for top, defalt, parent, and purpose.
+       is moved before `contents' so that XCHAT_TABLE (val)->defalt can
+       for an ASCII font, not defalt slot.
+      /* And if the configury during frame creation has been
+   Bob Desinger <hpsemc!bd@hplabs.hp.com>
+/* Calculate the checksum of a SOM header record. */
+     to preserve.  Then we map these VAs to the section entries in the
+#include <unknwn.h>
+  /* weiner@footloose.sps.mot.com reports that this causes
+   (VARN+1 SLOTN+1))
+dum@dots{} Nice tune, that@dots{} la la la@dots{} What, you're back?
+C'est la vie.
+        ("gnus-warning" "duplicat\\(e\\|ion\\) of message" "duplicate")
+James Troup,
+@cindex @code{multline}, AMS-LaTeX environment
+@code{align}, @code{gather}, @code{multline}, @code{flalign},
+      \openin 1 #1.pdf \ifeof 1
+        \openin 1 #1.PDF \ifeof 1
+          \openin 1 #1.png \ifeof 1
+            \openin 1 #1.jpg \ifeof 1
+              \openin 1 #1.jpeg \ifeof 1
+                \openin 1 #1.JPG \ifeof 1
+  \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks}
+  \openin 1 \jobname.\indexname s
+    % If the index file exists but is empty, then \openin leaves \ifeof
+\setbox\balancedcolumns=\vbox{shouldnt see this}%
+    \openin 1 \tocreadfilename\space
+  \openin 1 \jobname.aux
+\openin 1 = epsf.tex
+    \openin 1 txi-#1.tex
+  \openin 1 txi-#1.tex
+  @openin 1 texinfo.cnf
+                                             '("En" "To" "Tre"))
+=project.clj=, =build.boot= or =deps.edn=, falling back on
+    ("(.H)J" (1 :otf=beng=half+))
+-   (".H" :otf=beng=blwf,half,vatu+)
++   (".+H" :otf=beng=blwf,half,vatu+)
+    \quad \B{p}art: a)uthor (from), s)ubject, x)refs (cross-post), d)ate, 
l)ines,
+    message-i)d, t)references (parent), f)ollowup, b)ody, h)ead (all 
headers);\\*
+\key{show subtree in indirect buffer, ded.\ frame}{C-c C-x b}
+@tindex alog
+mode setting.  With the Inverse flag [@code{alog}], this command is
+@r{    a b@:    I B     @:             @:     2  @:alog@:(a,b)  b^a}
+@r{    a b@:    I f I   @:             @:     2  @:alog@:(a,b)  b^a}
+       Change comment about the iif hook to reflect the actual reason.
+     "\\`I' + \\`E' (ln), \\`L' (exp), \\`B' (alog: B^X); \\`f E' (lnp1), \\`f 
L' (expm1)"
+  (let (numer denom)
+    (setq numer (car (math-read-expr-list)))
+    (if (and (Math-num-integerp numer)
+        (list 'frac numer denom)
+      (list '/ numer denom))))
+       (calc-binary-op "alog" 'calcFunc-alog arg)
+       (let ((dum (math-lud-pivot-check sum)))
+         (if (or (math-zerop big) (Math-lessp big dum))
+             (setq big dum
+         (calc-pop-push-record-list 0 "larg"
+  (interactive "NNumber of columns = ")
+   (calc-binary-op "cros" 'calcFunc-cross arg)))
+   (calc-binary-op "unio" 'calcFunc-vunion arg '(vec) 'calcFunc-rdup)))
+  (calc-tabular-command 'calcFunc-table "Index" "tabl"
+                    (ptd (file-truename pd)))
+                (string-match (concat "^" (regexp-quote ptd)) ftn)))
+       (let ((aci (autoconf-parameters-for-macro "AC_INIT"))
+          ((> (length aci) 1)
+           (setq name (nth 0 aci)
+                 ver (nth 1 aci)
+                 bugrep (nth 2 aci)))
+       (princ "\nKnown members of ")
+           (peom (save-excursion (c-end-of-macro) (point))))
+            (when (> (point) peom)
+         (let ((larg (car args))
+           (if (stringp larg)
+               (setq larg (semantic-tag-new-variable
+                           larg nil nil)))
+            (srecode-semantic-tag (semantic-tag-name larg)
+                                  :prime larg)
+  (princ "\n--------------------------------------------\n\nNumber of tables: 
")
+;;            avk@rtsg.mot.com (Andrew V. Klein)     for a dired tip.
+    (args docstring interactive orig &optional befores arounds afters)
+and BEFORES, AROUNDS and AFTERS are the lists of advices with which ORIG
+    (dolist (advice befores)
+      (let* ((nam (buffer-substring (match-beginning 2) (match-end 2)))
+       (setq nmlst (cons nam nmlst)
+  "If we are in an rmail summary buffer, then chart out the froms."
+       (let* ((nam (buffer-substring (match-beginning 1) (match-end 1)))
+              (m (member nam nmlst)))
+         (message "Scanned username %s" nam)
+           (setq nmlst (cons nam nmlst)
+     ((memq word '(concat concating))
+         (crypted (cl-loop with str = (make-string (* 2 (length orig-name)) 0)
+         for c-sym = (concat prefix crypted "_" human-readable "_"
+      (concat prefix crypted "_" human-readable "_0"))))
+      (let* ((acces   (plist-get soptions :accessor))
+       (when acces
+          (push `(cl-defmethod (setf ,acces) (value (this ,name))
+          (push `(cl-defmethod ,acces ((this ,name))
+            (push `(cl-defmethod ,acces ((this (subclass ,name)))
+;;  => 
"(\\(c\\(atch\\|ond\\(ition-case\\)?\\)\\|if\\|let\\*?\\|prog[12n]\\|save-\\(current-buffer\\|excursion\\|match-data\\|restriction\\|window-excursion\\)\\|throw\\|un\\(less\\|wind-protect\\)\\|wh\\(en\\|ile\\)\\)\\>"
+G-C-g: Keyboard Quit              |Ex Ext Cmd|Fill Regio| REPLACE  |  UND W   |
+;; lisp example from Jari Aalto <jaalto@tre.tele.nokia.fi>
+;; perl example from Jari Aalto <jaalto@tre.tele.nokia.fi>
+;;    '(("\\<\\(uno\\|due\\|tre\\)\\>" . 'font-lock-keyword-face)
+  
"define\\|e\\(?:l\\(?:if\\|se\\)\\|ndif\\|rror\\)\\|file\\|i\\(?:f\\(?:n?def\\)?\\|mport\\|nclude\\)\\|line\\|pragma\\|undef\\|warning"
+2003-06-11  Daniel Néri  <dne@mayonnaise.net>
+                                         (lambda (valu symb)
+                    (let ((anumber (string-to-number
+                      (< anumber bnumber)))))
+    (curren      . 164)
+                ;; Now we must merge the Dows with the Doms. To do that, we
+                      (dows dow-list)
+                  ;; second add all possible dows
+                  (while (setq day (pop dows))
+;; Added by gord@enci.ucalgary.ca (Gordon Matzigkeit).
+       didnt nnmaildir--file nnmaildir-article-file-name
+            (setq didnt (cons (nnmaildir--art-num article) didnt)))
+                (setq didnt (cons (nnmaildir--art-num article) didnt))
+      didnt)))
+      (insert "\nKnown Certificates:\n"))))
+;; We could use `symbol-file' but this is a wee bit more efficient.
+       (beng . bengali)
+       (maka . makasar)
+              ,(font-spec :registry "iso10646-1" :otf '(beng nil (rphf))))
+     (khmer ,(font-spec :registry "iso10646-1" :otf '(khmr nil (pres))))
+    ("wee" . "Latin-2") ; MS Windows Lower Sorbian
+                ;; Unicode uses the spelling "lamda" in character
+                           (string-match "\\<LAMDA\\>" new-name))
+  "WINDOWS-1258 (Viet Nam)"
+    "mot de passe"     ; fr
+Je/sli czytasz ten tekst, to albo przegl/adasz plik /xr/od/lowy
+W drugim przypadku mo/zesz usun/a/c tekst z ekranu, stosuj/ac
+    przekodowuj/a zaznaczony fragment wzgl/ednie ca/ly buffor.
+    Poni/zsze przyk/lady powinny wyja/sni/c, jakich parametr/ow
+ Funkcje biblioteki odwo/luj/a si/e do pi/eciu zmiennych, kt/ore
+       ("capetown"        "Cape Town, South Africa")
+             (progn (error msg "preced") 0)))
+       <larsh@soem.dk> 2005-08-10.
+    (dolist (slot '(answers authorities additionals))
+          queries answers authorities additionals)
+      (setq additionals (dns-read-bytes 2))
+                                      (additionals ,additionals))
+  [nil                                 ; 1  ACI Item                        N
+    ("&curren;" . "(#)")
+;; Author: Alon Albert <alon@milcse.rtsg.mot.com>
+  "Mark region appropriately.  The next char REGION is 
d(efun),s(-exp),b(uffer),
+l(ines)."
+       (t (message "Mark: 
d(efun),s(-exp),b(uf),p(arag),P(age),f(unct),w(ord),e(os),l(ines)")
+  "Verify spelling for the objects specified by char UNIT : [b(uffer),
+       (t (message "Spell check: b(uffer), r(egion), s(tring), w(ord)")
+sWith: " )
+(defun org-babel-perl--var-to-perl (var &optional varn)
+  (if varn
+       (concat "my $" (symbol-name varn) "=" (when lvar "\n")
+             (if org-agenda-entry-text-mode " ETxt"   "")
+     ("curren" "\\textcurrency{}" nil "&curren;" "curr." "¤" "¤")
+  (interactive "nNumber of clones to produce: ")
+N          is the number of WHATs to shift.
+multlinewidth The width of the multline environment.
+              (list :tag "multlinewidth (width to use for the multline 
environment)"
+      "align"  "gather" "multline" "flalign"  "alignat"
+     ("ca" :default "Autor")
+     ("cs" :default "Autor")
+     ("de" :default "Autor")
+     ("es" :default "Autor")
+     ("et" :default "Autor")
+     ("pl" :default "Autor")
+     ("pt_BR" :default "Autor")
+     ("ro" :default "Autor")
+     ("sl" :default "Seznam tabel")
+     ("nl" :default "Zie tabel %s"
+      :html "Zie tabel&nbsp;%s" :latex "Zie tabel~%s")
+     ("et" :default "Tabel")
+     ("nl" :default "Tabel")
+     ("ro" :default "Tabel")
+     ("ro" :default "Tabele")
+     ("da" :default "Tabel %d")
+     ("et" :default "Tabel %d")
+     ("nl" :default "Tabel %d:" :html "Tabel&nbsp;%d:")
+     ("ro" :default "Tabel %d")
+     ("pl" :html "Spis tre&#x015b;ci")
+                        (thier their (their))
+                (whats up) (whats new) (what\'s up) (what\'s new)
+           refer refered referred refers
+    (c++-mode . 
"#\\(assert\\|cpu\\|define\\|endif\\|el\\(if\\|se\\)\\|i\\(dent\\|f\\(def\\|ndef\\)?\\|mport\\|nclude\\(_next\\)?\\)\\|line\\|machine\\|pragma\\|system\\|un\\(assert\\|def\\)\\|warning\\)\\>"))
+     "^\\(?:Error\\|Warnin\\(g\\)\\) \\(?:[FEW][0-9]+ \\)?\
+: \\(?:see declaration\\|\\(?:warnin\\(g\\)\\|[a-z ]+\\) C[0-9]+:\\)"
+     "^\\([^ \n]+\\)(\\([0-9]+\\)): 
\\(?:error\\|warnin\\(g\\)\\|remar\\(k\\)\\)"
+     
"^\"\\(.*\\)\",\\([0-9]+\\)\\s-+\\(?:Error\\|Warnin\\(g\\)\\)\\[[0-9]+\\]:"
+ \\(?:warnin\\(g\\)\\|informationa\\(l\\)\\)?" 1 2 3 (4 . 5))
+     "^ *\\([0-9]+\\)\\.[ \t]+.*\n +\\(<-*>\n\\*\\*\\* 
\\(?:Error\\|Warnin\\(g\\)\\)\\)"
+     "^\\(?:Error\\|Warnin\\(g\\)\\):.*\n.* line \\([0-9]+\\) char\
+     ": \\(?:ERROR\\|WARNIN\\(G\\)\\|REMAR\\(K\\)\\) \\(?:[[:alnum:] ]+, \\)?\
+     (" --?o\\(?:utfile\\|utput\\)?[= ]\\(\\S +\\)" . 1)
+          "^[ \t]*\\(format\\)[ \t]*\\([a-zA-Z0-9_]+\\)?[ \t]*=[ \t]*$" ;FRMAT
+    (insert "\n[U]nknown conditionals: ")
+  (struc info file tags-file &optional view where)
+STRUC is an `ebrowse-bs' structure (or a structure including that)
+FILE is not taken out of STRUC here because the filename in STRUC
+          (ebrowse-bs-name struc)))
+        (setf ebrowse-temp-position-to-view struc
+        (ebrowse-find-pattern struc info))))
+                            "cexp" "log" "alog" "dlog" "clog" "log10"
+  '("ASCII" "addto" "also" "and" "angle" "atleast" "batchmode"
+        "bre~ak" "bti~tle" "c~hange" "cl~ear" "col~umn" "conn~ect"
+        "repf~ooter" "reph~eader" "r~un" "sav~e" "sho~w" "shutdown"
+                "copyc~ommit" "copytypecheck" "def~ine" "describe"
+That is, all code between \"// synopsys translate_off\" and
+\"// synopsys translate_on\" is highlighted using a different background color
+option to intermix between input/output/inouts.
+       :help           "Help on AUTOINOUT - adding inouts from cells"]
+  (eval-when-compile (verilog-regexp-words '("Outputs" "Inouts" "Inputs" 
"Interfaces" "Interfaced"))))
+           '("surefire" "0in" "auto" "leda" "rtl_synthesis" "synopsys"
+           (structres nil)
+                   (setq structres (verilog-in-struct-nested-p))
+                   (cond ((not structres) nil)
+                         ;;((and structres (equal (char-after) ?\})) (throw 
'nesting 'struct-close))
+                         ((> structres 0) (throw 'nesting 'nested-struct))
+                         ((= structres 0) (throw 'nesting 'block))
+          (list 'block structres))
+// Created       : <credate>
+    (search-forward "<credate>") (replace-match "" t t)
+Return an array of [outputs inouts inputs wire reg assign const gparam intf]."
+         (when (looking-at "[^\n]*\\(auto\\|synopsys\\)\\s +enum\\s 
+\\([a-zA-Z0-9_]+\\)")
+Return an array of [ outputs inouts inputs ] signals for modules that are
+                 (while (re-search-forward "\\s *(?\\s *// Inouts" 
end-inst-point t)
+         (if (looking-at "[^\n]*\\(auto\\|synopsys\\)\\s +enum\\s 
+\\([a-zA-Z0-9_]+\\)")
+                             "// Inouts"
+  Inouts are not supported, as assignments must be unidirectional.
+            (verilog-auto-inst-port-list "// Inouts\n"
+  This ONLY detects inouts of AUTOINSTants (see `verilog-read-sub-decls').
+           // Beginning of automatic inouts
+              // Inouts
+from only extracting inouts starting with i:
+       (verilog-insert-indent "// Beginning of automatic inouts (from unused 
autoinst inouts)\n")
+           // Beginning of automatic in/out/inouts
+           (verilog-insert-indent "// Beginning of automatic in/out/inouts 
(from specific module)\n")
+          // Beginning of automatic in/out/inouts (from modport)
+           (verilog-insert-indent "// Beginning of automatic in/out/inouts 
(from modport)\n")
+finds all inputs and inouts in the module, and if that input is not otherwise
+First, parameters are built into an enumeration using the synopsys enum
+  \"synopsys enum\" may be used in place of \"auto enum\".
+                default:  state_ascii_r = \"%Erro\";
+    `verilog-auto-inout'        for AUTOINOUT making hierarchy inouts
+    `verilog-auto-unused'       for AUTOUNUSED unused inputs/inouts
+    ;; duluth: *E,430 (test.vhd,13): identifier (POSITIV) is not declared
+    ("GHDL" "ghdl" "-i --workdir=\\1 --ieee=synopsys -fexplicit " "make" "-f 
\\1"
+    ;; ERROR: test.vhd(14): Unknown identifier: positiv
+    ;; ProVHDL, Synopsys LEDA: provhdl -w work -f test.vhd
+    ;; Synopsys, VHDL Analyzer (sim): vhdlan -nc test.vhd
+    ("Synopsys" "vhdlan" "-nc -work \\1" "make" "-f \\1"
+     nil "mkdir \\1" "./" "work/" "Makefile" "synopsys"
+    ;; Synopsys, VHDL Analyzer (syn): vhdlan -nc -spc test.vhd
+    ("Synopsys Design Compiler" "vhdlan" "-nc -spc -work \\1" "make" "-f \\1"
+      ("Synopsys" "-vhdl87 \\2" "-f \\1 top_level" ((".*/datapath/.*" . 
"-optimize \\3") (".*_tb\\.vhd" . nil))))
+(defcustom vhdl-directive-keywords '("psl" "pragma" "synopsys")
+           (eq (vhdl-decision-query nil "(d)eclaration or (b)ody?") ?b))
+                (eq (vhdl-decision-query nil "(d)eclaration or (b)ody?") ?b)))
+;; Author: Alex Rezinsky <alexr@msil.sps.mot.com>
+;; Thanks to Gord Wait <Gord_Wait@spectrumsignal.com> for
+;; Thanks to Paul Furnanz <pfurnanz@synopsys.com> for XEmacs compatibility
+;; Thanks to Kevin Rodgers <kevinr@ihs.com> for handling control characters
+;;  * Check `ps-paper-type': Sudhakar Frederick <sfrederi@asc.corp.mot.com>
+;; Thanks to Kevin Rodgers <kevinr@ihs.com> for adding support for color and
+;; Thanks to Avishai Yacobi, avishaiy@mcil.comm.mot.com, for writing the
+;; Ralf Brown's Interrupt List. file INTERRUP.F, D-2138, Table 01400
+    ("portugues"                        ; Portuguese mode
+    ("portugues"     "pt_PT")
+;; of the document.  If WRAPP is true then wrap the search to the
+(defun reftex-isearch-switch-to-next-file (crt-buf &optional wrapp)
+      (if wrapp
+f / c      Toggle follow mode             / Toggle display of [c]ontext.
+ F t c      Toggle:  [F]ile borders, [t]able of contents,  [c]ontext
+\\`l' \\`i' \\`c' \\`F'    Toggle display of  [l]abels,  [i]ndex,  [c]ontext,  
[F]ile borders.
+                      ;; OK, get the makro name
+      ("multline"     ?e nil nil t)
+   "nbsp" "iexcl" "cent" "pound" "curren" "yen" "brvbar" "sect"
+;; |ment\|
+;; horizontale disigatan fenestron, si-         horizontally split window 
similar to
+;;         ^jus anta^ue faris C-x C-f.      file if you just did C-x C-f.
+;; per C-x u  kaj  plue  modifu  la  du         continue   to  edit the two 
buffers.
+;; Programistoj eble ^satus la  eblecon  Programmers might like the ability
+;; iliajn finojn dum redaktado.                 won't see their end during 
editing.
+    "news:"; "nfs://" "nntp://"; "opaquelocktoken:" "pop://" "pres:"
+;; Bob Weiner <weiner@footloose.sps.mot.com>,
+       control whether we try to do keep-alives for our connections.
+       keep-alives to time out on cached documents with no known
+         ;; seconds for the keep-alives to time out on some servers.
+         msglen = ccl->quit_silently ? 0 : sprintf (msg, "\nCCL: Quitted.");
+                                  Quitted" to the generated text when
+                                  CCL program is quitted. */
+   followings.  */
+  /* Followings are target of code detection.  */
+  /* Followings are NOT target of code detection.  */
+    /* The followings are extra attributes for each type.  */
+    Aadd,
+       case Aadd : accum += next; break;
+       case Aadd   :       mpz_add (mpz[0], *accum, *next); break;
+         case Aadd : overflow = INT_ADD_WRAPV (accum, next, &a); break;
+  return nargs == 1 ? a : arith_driver (Aadd, nargs, args, a);
+    /* The followings are used only for a font-entity and a font-object.  */
+    /* The followings are used only for a font-object.  */
+         /* We have already tried this element and the followings
+/* According to RBIL (INTERRUP.A, V-1000), 160 is the maximum possible
+   hole between the first bloc and the end of malloc storage.  */
+  /* First bloc in this heap.  */
+  /* Last bloc in this heap.  */
+  struct heap *heap;           /* Heap this bloc is in.  */
+/* Find the bloc referenced by the address in PTR.  Returns a pointer
+        callers that always expect a bloc to be returned should abort
+/* Allocate a bloc of SIZE bytes and append it to the chain of blocs.
+   Returns a pointer to the new bloc, or zero if we couldn't allocate
+  /* Put this bloc on the doubly-linked list of blocs.  */
+/* Calculate new locations of blocs in the list beginning with BLOC,
+in the quitted window.
+       trough color and main window's background color.
+       means the truck and arrow colors, and "trough" means the
+  bg[ACTIVE] = "blue"@ @ @ @ # @r{Trough color.}
+also for the trough of a scroll bar, i.e., @code{bg[ACTIVE] = "red"}
+sets the scroll bar trough to red.  Buttons that have been armed
+    (while (search-forward "nam" nil t)
+    (search-forward "som")
+    (search-forward "Nam")
+ (0 ":rando!~u@bivkhq8yav938.irc PRIVMSG tester :[09:17:51] u thur?")
+ (0.01 ":alice/foonet PRIVMSG #chan/foonet :bob: Sir, his wife some two months 
since fled from his house: her pretence is a pilgrimage to Saint Jaques le 
Grand; which holy undertaking with most austere sanctimony she accomplished; 
and, there residing, the tenderness of her nature became as a prey to her 
grief; in fine, made a groan of her last breath, and now she sings in heaven.")
+     "sav"
+                                           (if valu
+                                               (cons symb valu)))
+          (sample-text . "Er is een aantal manieren waarop je dit kan doen")
+Tai Daeng (also known as Red Tai or Tai Rouge),
+           ;; Ith character and the followings matches precomposable
+      sprintf (css, "scrollbar trough { background-color: #%06x; }",
+     OFROM[I] is position of the earliest comment-starter seen
+           sprintf (css, "scrollbar trough { background-color: #%02x%02x%02x; 
}",
+  /* Note: "background" is the thumb color, and "trough" is the color behind
+        (uptodate t))
+     (while (and files uptodate)
+            (setq uptodate nil)))))
+     uptodate)))
+      ptrdiff_t acount = 0;   /* The # of consecutive times A won.  */
+             acount = 0;
+             ++acount;
+             if (acount >= min_gallop)
+       acount = k;
+      } while (acount >= GALLOP_WIN_MIN || bcount >= GALLOP_WIN_MIN);
+    ptrdiff_t acount = 0;   /* The # of consecutive times A won.  */
+         ++acount;
+         if (acount >= min_gallop)
+         acount = 0;
+      acount = k;
+    } while (acount >= GALLOP_WIN_MIN || bcount >= GALLOP_WIN_MIN);
+       154cd116be (origin/emacs-27) * admin/release-process: Adapt bug numbe...
+       a38da0d cc-mode.texi: Work around makeinfo alignment bug.  Fix proble...
+       fd35804971 (origin/emacs-26) * doc/lispref/strings.texi (Case Convers...
+       be in line with the raison d'être of compiling printer which is speed.
+mace <mace@kirjakaapeli.lib.hel.fi>
+at that position, the result is @samp{fro!b}, with point between the
+doesnt
+minimize(xfit(gaus(a,b,c,d,x), x, [a,b,c], data)_5, d, guess)
+where @code{gaus} represents the Gaussian model with background,
+* Score Decays::                It can be useful to let scores wither away.
+providers if they were to do this---their @emph{raison d'être} is to
+While this design may be internally consistent with the raison d'être of
+Finally, just to whet your appetite for what can be done with the
+Wedler, Alan Williams, Roland Winkler, Hans-Christoph Wirth, Eli
+                 "Some Place\nIn some City\nSome country.")
+@c andrewm@@optimation.co.nz
+Emacs Macht Alle Computer Schoen
+GLib-GObject-WARNING **: /build/buildd/glib2.0-2.14.5/gobject/gsignal.c:1741: 
instance `0x8206790' has no handler with id `1234' at t-compilation-perl-gtk.pl 
line 3.
+    \quad \B{A}ction: I)ncrease, L)ower;\\*
+        (calc-unary-op "flor" 'calcFunc-ffloor arg)
+       (calc-unary-op "flor" 'calcFunc-floor arg)))))
+  ["de la Vertu" "du Génie" "du Travail" "de la Raison" "des Récompenses"
+   "de la Cuve"            "de la Pomme de terre"  "de l'Immortelle"
+   "de la Raison"          "des Récompenses"       "de la Révolution"]
+       (string-match "config\\(ure\\.\\(in\\|ac\\)\\|\\.status\\)?$" f)
+    ("\\.\\(dll\\|drv\\|386\\|vxd\\|fon\\|fnt\\|fot\\|ttf\\|grp\\)$" . t)
+      (insert (format "\nIn %s:\n" form)))
+                         (format "\nIn macro %s:" (cadr form)))
+                         (format "\nIn variable %s:" (cadr form)))
+    (insert "\nIn " package)
+             "\nIn order to use version `%s' of gnus, you will need to set\n"
+znak/ow diakrytycznych. Funkcje te mo/zna pogrupowa/c nast/epuj/aco.
+ oraz ich warto/sci domy/slne s/a nast/epuj/ace:
+    (insert "\nIn " (emacs-version))
+        "[n]ew messages; [']ticked messages; [s]earch;\n"
+    (?/ "Limit to [c]c, ran[g]e, fro[m], [s]ubject, [t]o; [w]iden")
+  (dictionary-send-command "show strat")
+r(egion), s(tring), w(ord) ]."
+         "ncl" "nfd" "ngu" "nin" "nma" "nmu" "nod" "nop" "npp" "nsf"
+                        (theyre they\'re (they are))
+    (insert "\n[K]nown conditionals: ")
+                   "[T]rue Face" "[F]alse Face" "[W]rite"))
+                                "[ \t]*in\\(?:put\\|clude\\)[ 
\t]*{\\(.*%s\\)}")))
+  (let ((siz (cond ((numberp size)
+    (and (< siz 0)
+    siz))
+     "\tHow to report bugs and contribute improvements to Emacs\n"
+     "\tHow to obtain the latest version of Emacs\n"
+  (insert "\tHow to report bugs and contribute improvements to Emacs\n\n")
+  (insert "\tHow to get the latest version of GNU Emacs\n")
+    ("/mod\\(?:ules\\|probe\\)\\.conf" . 
"alias\\|in\\(?:clude\\|stall\\)\\|options\\|remove")
+    ("/dictionary\\.lst\\'" . "DICT\\|HYPH\\|THES")
+      ;;     use-mark sizeA dateA  sizeB dateB  filename
+;; nin, nil are placeholders. See ediff-make-new-meta-list-element in
+;;   Andrew McRae <andrewm@optimation.co.nz>
+       * xmenu.c (apply_systemfont_to_menu): *childs was incorrectly used.
+DEFUN ("catch", Fcatch, Scatch, 1, UNEVALLED, 0,
+  defsubr (&Scatch);
+DEFUN ("elt", Felt, Selt, 2, 2, 0,
+  defsubr (&Selt);
+  (should (equal (string-truncate-left "longstring" 8) "...tring")))
+ (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Lady, I will commend 
you to mine own heart.")
+    (perl "GLib-GObject-WARNING **: 
/build/buildd/glib2.0-2.14.5/gobject/gsignal.c:1741: instance `0x8206790' has 
no handler with id `1234' at t-compilation-perl-gtk.pl line 3."
+    (rxp "Error: Mismatched end tag: expected </geroup>, got </group>\nin 
unnamed entity at line 71 char 8 of file:///home/reto/test/group.xml"
+    (rxp "Warning: Start tag for undeclared element geroup\nin unnamed entity 
at line 4 char 8 of file:///home/reto/test/group.xml"
+   (string= (python-util-strip-string "\n str \nin \tg \n\r") "str \nin \tg"))
+    (insert "hel")
+                         (format "\nIn function %s:" (cadr form)))
+                        (t "\nIn top level expression:"))))
+       All suggested by Ned Ludd.
+;; 2002-07-27 Added DELETESCRIPT.  Suggested by Ned Ludd.
+;;            Ned Ludd.
+To: Ned Freed <ned@innosoft.com>
+@strong{Te Deum}
+ If the termcap entry does not define the "ti" or "te" string,
+ and the "te" string is used to set it back on exit.
+         (te (solar-time-equation date ut)))
+    (setq ut (- ut te))
+       (let ((te (semantic-tag-end aftertag)))
+         (when (not te)
+         (goto-char te)
+    ("te" . "Telugu")
+     ("\\.te?xt\\'" . text-mode)
+     ("\\.te?xi\\'" . texinfo-mode)
+  
'(("\\.te?xt$\\|\\.doc$\\|read.*me\\|\\.c?$\\|\\.h$\\|\\.bat$\\|\\.asm$\\|makefile"
 "cat %s | sed 's/\r$//'")
+    ("\\.\\(te?xt\\|doc\\|c\\|h\\)$" "text/plain")
+                           (not (string-match "\\.te?xi\\'" name)) ;; not .texi
+          (?\ተ "te")
+          (?\ቴ "tE")
+          (?\ጠ "Te")
+          (?\ጤ "TE")
+          (?\∃ "TE")
+          (?\て "te")
+          (?\テ "Te")
+    ("te" "Telugu" utf-8) ; Telugu
+    "సంకేతపదము"                ; te
+       * org-clock.el (org-clocktable-steps): Allow ts and te to be day
+        issue face m te ts dt ov)
+             te nil ts nil)
+                 te (match-string 3)
+                 te (float-time (org-time-string-to-time te))
+                 dt (- te ts))))
+      (setq tlend (or te tlend) tlstart (or ts tlstart))
+         ts te s h m remove)
+         (setq te (org-insert-time-stamp (or at-time now) 'with-hm 'inactive))
+                   (org-time-string-to-time te)
+                  te (org-duration-from-minutes (+ (* 60 h) m)))
+                  (te (float-time
+                  (dt (- (if tend (min te tend) te)
+          (te (plist-get params :tend))
+             te (nth 1 cc)))
+       (unless (or block (and ts te))
+        (te (plist-get params :tend))
+           te (nth 1 cc)))
+    (when (integerp te) (setq te (calendar-gregorian-from-absolute te)))
+    (when (and te (listp te))
+      (setq te (format "%4d-%02d-%02d" (nth 2 te) (car te) (nth 1 te))))
+    (if te (setq te (org-matcher-time te)))
+      (org-clock-sum ts te
+           ts te h m s neg)
+               te (match-string 3))
+                     (apply #'encode-time (org-parse-time-string te)))
+;; Emulate more complete preprocessor support for tbl (.TS/.TE)
+This applies to text between .TE and .TS directives.
+     ;; ((looking-at "[te]") (setq c nil))   ; reject t(roff) and e(ven page)
+              (set-marker to (woman-find-next-control-line "TE"))
+  tty->TS_end_termcap_modes = tgetstr ("te", address);
+  const char *TS_end_termcap_modes; /* "te" */
+ (0 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :[09:19:19] mike: Chi non te 
vede, non te pretia.")
+ (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Chi non te vede, non te 
pretia.")
+          "un moyen, et te trompant ainsi sur la route =C3=A0 suivre les 
voil=C3=A0 bi=\n"
+          "ent=C3=B4t qui te d=C3=A9gradent, car si leur musique est vulgaire 
ils te f=\n"
+          "abriquent pour te la vendre une =C3=A2me vulgaire."))
+          "un moyen, et te trompant ainsi sur la route à suivre les voilà bi"
+          "entôt qui te dégradent, car si leur musique est vulgaire ils te f"
+          "abriquent pour te la vendre une âme vulgaire."))
+    (".TS" . ".TE")
+    (define-key vhdl-template-map "te" #'vhdl-template-terminal)
+    ("te" "telugu")
+                    (format "%s.TE\n"
+:NR:te=\\E[47l:ti=\\E[47h\
+  ;; don't define :te=\\E[2J\\E[?47l\\E8:ti=\\E7\\E[?47h\
+       nil nil nil nil "FA" "C." "dP" "TE" "~TE" "/0"
+(defalias 'woman2-TE #'woman2-fi)
+;;; Preliminary table support (.TS/.TE)
+  ;; ".TE -- End of table code for the tbl processor."
+       8804ac857b * src/buffer.c (syms_of_buffer) <ctl-arrow>: Doc fix.  (Bu...
+       da00a6f317 Fix Xaw widget text disappearing when built with cairo (bu...
+2020-11-10  Andrew G Cohen  <cohen@andy.bu.edu>
+2020-09-23  Andrew G Cohen  <cohen@andy.bu.edu>
+2020-09-11  Andrew G Cohen  <cohen@andy.bu.edu>
+2020-09-10  Andrew G Cohen  <cohen@andy.bu.edu>
+2020-09-09  Andrew G Cohen  <cohen@andy.bu.edu>
+2020-09-07  Andrew G Cohen  <cohen@andy.bu.edu>
+2020-09-05  Andrew G Cohen  <cohen@andy.bu.edu>
+2020-08-29  Andrew G Cohen  <cohen@andy.bu.edu>
+2020-08-27  Andrew G Cohen  <cohen@andy.bu.edu>
+       121be3e118 ; * etc/NEWS: Remove temporary note on documentation.  (Bu...
+       224e8d1464 Make call_process call signal_after_change.  This fixes bu...
+       891f7de8ed * test/lisp/simple-tests.el: Full path to Emacs binary (bu...
+       8b7c776 * lisp/simple.el (kill-do-not-save-duplicates): Doc fix.  (Bu...
+       beb4eac * doc/lispref/display.texi (Showing Images): Fix a typo.  (Bu...
+       60b5c10 Provide more details in doc-string of 'delete-windows-on' (Bu...
+       57bcdc7 Don't call XGetGeometry for frames without outer X window (Bu...
+       f64c277 (origin/emacs-26) Let bookmark-jump override window-point (Bu...
+       4bd43b0 Increase max-lisp-eval-depth adjustment while in debugger (bu...
+       55c9bb9f3c Fix comint-get-old-input-default for output field case (Bu...
+       e244fed Clarify that nil doesn't match itself as a cl-case clause (Bu...
+       e21f018 * doc/lispref/functions.texi (Inline Functions): Fix typo (Bu...
+       c59ecb005e New customization variable for python-mode indentation (Bu...
+       a36a090 * lisp/progmodes/verilog-mode.el (verilog-mode): Fix typo (Bu...
+       98ca7d5 Improve edit-kbd-macro prompting in case of remapped keys (Bu...
+       804b37ca63 Save and restore text-pixel height and width of frames (Bu...
+       9715317dfd * lisp/dired.el (dired-find-alternate-file): Doc fix.  (Bu...
+       234b1e3864 Flymake backends must check proc obsoleteness in source bu...
+       dc8812829b Remove resizable attribute on macOS undecorated frames (bu...
+       43fac3beae Make "unsafe directory" error message more informative (Bu...
+2017-04-25  Andrew G Cohen  <cohen@andy.bu.edu>
+2017-04-23  Andrew G Cohen  <cohen@andy.bu.edu>
+       dbb3410 python.el: Fix detection of native completion in Python 3 (bu...
+       4b2d77d * lisp/emacs-lisp/macroexp.el (macroexp--expand-all): Fix (bu...
+       d59bcbc Handle mouse leaving initial window in `mouse-set-region' (Bu...
+       586b213 * lisp/url/url.el (url-retrieve-synchronously): Doc fix.  (Bu...
+       f3653ec * configure.ac (HAVE_MODULES): Treat gnu like gnu-linux.  (Bu...
+2010-12-15  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-14  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-13  Andrew Cohen  <cohen@andy.bu.edu>
+;; Author: Joe Wells <jbw@bigbird.bu.edu>
+  (define-key calc-mode-map "bu" 'calc-unpack-bits)
+    (ruby-mode "*.r[bu]" "*.rake" "*.gemspec" "*.erb" "*.haml"
+2002-03-31  Andrew Cohen  <cohen@andy.bu.edu>  (tiny change)
+2013-05-04  Andrew Cohen  <cohen@bu.edu>
+2013-04-25  Andrew Cohen  <cohen@bu.edu>
+2013-04-24  Andrew Cohen  <cohen@bu.edu>
+2013-04-14  Andrew Cohen  <cohen@bu.edu>
+2013-04-10  Andrew Cohen  <cohen@bu.edu>
+2013-04-04  Andrew Cohen  <cohen@bu.edu>
+2013-04-01  Andrew Cohen  <cohen@bu.edu>
+2013-03-31  Andrew Cohen  <cohen@bu.edu>
+2013-03-30  Andrew Cohen  <cohen@bu.edu>
+2013-03-29  Andrew Cohen  <cohen@bu.edu>
+2013-03-27  Andrew Cohen  <cohen@bu.edu>
+2013-03-26  Andrew Cohen  <cohen@bu.edu>
+2012-07-22  Andrew Cohen  <cohen@bu.edu>
+2011-09-12  Andrew Cohen  <cohen@andy.bu.edu>
+2011-09-05  Andrew Cohen  <cohen@andy.bu.edu>
+2011-09-01  Andrew Cohen  <cohen@andy.bu.edu>
+2011-08-11  Andrew Cohen  <cohen@andy.bu.edu>
+2011-08-05  Andrew Cohen  <cohen@andy.bu.edu>
+2011-08-04  Andrew Cohen  <cohen@andy.bu.edu>
+2011-08-03  Andrew Cohen  <cohen@andy.bu.edu>
+2011-08-02  Andrew Cohen  <cohen@andy.bu.edu>
+2011-07-24  Andrew Cohen  <cohen@andy.bu.edu>
+2011-07-23  Andrew Cohen  <cohen@andy.bu.edu>
+2011-07-20  Andrew Cohen  <cohen@andy.bu.edu>
+2011-07-14  Andrew Cohen  <cohen@andy.bu.edu>
+2011-07-02  Andrew Cohen  <cohen@andy.bu.edu>
+2011-07-01  Andrew Cohen  <cohen@andy.bu.edu>
+2011-06-30  Andrew Cohen  <cohen@andy.bu.edu>
+2011-06-21  Andrew Cohen  <cohen@andy.bu.edu>
+2011-02-22  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-17  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-16  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-10  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-08  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-07  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-06  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-05  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-04  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-03  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-02  Andrew Cohen  <cohen@andy.bu.edu>
+2010-12-01  Andrew Cohen  <cohen@andy.bu.edu>
+2010-11-29  Andrew Cohen  <cohen@andy.bu.edu>
+2010-11-28  Andrew Cohen  <cohen@andy.bu.edu>
+2010-11-27  Andrew Cohen  <cohen@andy.bu.edu>
+2010-11-23  Andrew Cohen  <cohen@andy.bu.edu>
+2010-11-21  Andrew Cohen  <cohen@andy.bu.edu>
+2010-11-17  Andrew Cohen  <cohen@andy.bu.edu>
+2010-11-11  Andrew Cohen  <cohen@andy.bu.edu>
+2010-11-06  Andrew Cohen  <cohen@andy.bu.edu>
+2010-11-04  Andrew Cohen  <cohen@andy.bu.edu>
+2010-11-03  Andrew Cohen  <cohen@andy.bu.edu>
+2010-11-01  Andrew Cohen  <cohen@andy.bu.edu>
+2010-10-31  Andrew Cohen  <cohen@andy.bu.edu>
+2010-10-30  Andrew Cohen  <cohen@andy.bu.edu>
+2010-10-22  Andrew Cohen  <cohen@andy.bu.edu>
+2010-10-18  Andrew Cohen  <cohen@andy.bu.edu>
+2010-10-16  Andrew Cohen  <cohen@andy.bu.edu>
+2010-10-15  Andrew Cohen  <cohen@andy.bu.edu>
+2010-10-14  Andrew Cohen  <cohen@andy.bu.edu>
+2010-10-10  Andrew Cohen  <cohen@andy.bu.edu>
+2010-09-25  Andrew Cohen  <cohen@andy.bu.edu>  (tiny change)
+2010-09-23  Andrew Cohen  <cohen@andy.bu.edu>
+2004-02-26  Andrew Cohen  <cohen@andy.bu.edu>
+       <cohen@andy.bu.edu>.
+       syntax table here.  Reported by Andrew Cohen <cohen@andy.bu.edu>.
+            ;; Fix by Mike Dugan <dugan@bucrf16.bu.edu>.
+;; Author: Andrew Cohen <cohen@andy.bu.edu>
+          (?\ቡ "bu")
+          (?\ぶ "bu")
+          (?\ブ "Bu")
+;; Author: Joe Wells <jbw@cs.bu.edu>
+;; Tue Mar 23 21:23:18 1993  Joe Wells  (jbw at csd.bu.edu)
+;; Mon Mar 22 21:20:56 1993  Joe Wells  (jbw at bigbird.bu.edu)
+;; Mon Mar 22 20:16:57 1993  Joe Wells  (jbw at bigbird.bu.edu)
+;; Mon Mar 22 00:46:12 1993  Joe Wells  (jbw at bigbird.bu.edu)
+;; Sun Mar 21 21:41:06 1993  Joe Wells  (jbw at bigbird.bu.edu)
+;; Sun Mar 21 14:39:38 1993  Joe Wells  (jbw at bigbird.bu.edu)
+;; Mon Feb  1 22:23:31 1993  Joe Wells  (jbw at bigbird.bu.edu)
+;; Mon Apr  6 23:59:09 1992  Joe Wells  (jbw at bigbird.bu.edu)
+;; Sun Apr  5 19:39:08 1992  Joe Wells  (jbw at bigbird.bu.edu)
+;; Sun Feb  2 14:45:24 1992  Joe Wells  (jbw at bigbird.bu.edu)
+             " --------Unsent Message below:" ; from sendmail at BU
+;; Mostly rewritten by Andrew Cohen <cohen@bu.edu> from 2010
+                             ((string= "*" bullet) "\\(bu")
+  (gud-def gud-finish "bu\\t"      "\C-f" "Finish executing current function.")
+    ("bu" "*"   "\267" . t)            ; bullet
+            '("+l" "#s" "#bu")))
+       da6234e2df Make sure pixel sizes are zero when setting window size fo...
+       d38fd9229c0 Narrow scope of modification hook renabling in org-src fo...
+is the last word in the buffer that starts with @samp{fo}.  A numeric
+after the first @samp{FO}; the @samp{F} in that @samp{FO} might not be
+expression @samp{fo}, which matches only the string @samp{fo}.  To do
+expression.  Thus, @samp{fo*} has a repeating @samp{o}, not a repeating
+@samp{fo}.  It matches @samp{f}, @samp{fo}, @samp{foo}, and so on.
+$ ls -li fo*
+(file-name-all-completions "fo" "")
+ nil t "fo")
+Complete a foo: fo@point{}
+and @samp{o} to get the regular expression @samp{fo}, which matches only
+the string @samp{fo}.  Still trivial.  To do something more powerful, you
+fo
+@samp{fo#.el} matches @file{f.el}, @file{fo.el}, @file{foo.el}, etc.
+@samp{fo#.el} matches @file{fo.el}, @file{foo.el}, @file{fooo.el},
+    <style:text-properties fo:background-color="#ff0000"/>
+    <style:paragraph-properties fo:break-before="page"/>
+  \futurelet\next\fo@t
+M-f    Fo      Alias (keep?)
+% |  fo     |
+        fo ;; List of final overloaded functions
+                           (if (get s 'constant-flag) fo ov))
+    (when fo
+      (mapc #'mode-local-print-binding fo))
+   :eval (string-match-p "^[fo]+" "foobar"))
+   :eval (and (string-match "^\\([fo]+\\)b" "foobar")
+    ("fo" . "Faroese")
+          (?\ፎ "fo")
+    ("fo" . "Latin-1") ; Faroese
+       ("fo" "Faroe Islands")
+       M-f -> Fo       Alias (keep?)
+  ;; quotes (for example), we end up completing "fo" to "foobar and throwing
+  ;; completing "fo" to "foO" when completing against "FOO" (bug#4219).
+  <style:table-properties style:rel-width=\"%s%%\" fo:margin-top=\"0cm\" 
fo:margin-bottom=\"0.20cm\" table:align=\"center\"/>
+   <style:paragraph-properties fo:background-color=\"%s\" 
fo:padding=\"0.049cm\" fo:border=\"0.51pt solid #000000\" style:shadow=\"none\">
+   <style:text-properties fo:color=\"%s\"/>
+                       (format " fo:min-width=\"%0.2fcm\"" (or width .2))))
+          (concat (format " fo:min-height=\"%0.2fcm\"" (or height .2))
+  <style:text-properties fo:color=\"%s\"/>
+          ;; Are we coalescing two tokens together, e.g. "fo o"
+                        ;; user from completing "fo" to "foo/" when she
+;; |        |        | fo     |        | fo     |        |        |
+page-height == bm + print-height + tm - fo - fh
+                             ("fo+bar" nil "2nd")
+                             ("fo*bar" nil "3rd")))
+  (should (equal (ert--abbreviate-string "foo" 2 nil) "fo"))
+  (should (equal (string-limit "foo" 2) "fo"))
+  (should (equal (string-limit "foó" 10 nil 'utf-8) "fo\303\263"))
+  (should (equal (string-limit "foó" 3 nil 'utf-8) "fo"))
+  (should (equal (string-limit "foó" 4 nil 'utf-8) "fo\303\263"))
+  (should (equal (string-limit "foóa" 4 nil 'utf-8) "fo\303\263"))
+  (should (equal (string-limit "foóá" 4 nil 'utf-8) "fo\303\263"))
+  (should (equal (string-limit "foóa" 4 nil 'iso-8859-1) "fo\363a"))
+  (should (equal (string-limit "foóá" 4 nil 'iso-8859-1) "fo\363\341"))
+  (should (equal (string-limit "foó" 10 t 'utf-8) "fo\303\263"))
+  (should (equal (string-limit "foó" 4 t 'utf-8) "fo\303\263"))
+  (should (equal (string-limit "foóa" 4 t 'iso-8859-1) "fo\363a"))
+  (should (equal (string-limit "foóá" 4 t 'iso-8859-1) "fo\363\341"))
+                 "   fo"))
+    (("foo" 2 nil nil "...") . "fo") ;; XEmacs failure?
+        (non-directories '("/abso-folder/fo" "rela-folder/fo"
+                           "/testdir/Mail/rela-folder/fo"
+                    (format "+%s/fo" mh-test-rel-folder) nil 'lambda)))))
+                    (format "+%s/fo" mh-test-abs-folder) nil 'lambda)))))
+         (should (equal (file-name-completion "fo" tmp-name) "foo."))
+           (sort (file-name-all-completions "fo" tmp-name) #'string-lessp)
+             (should (equal (file-name-completion "fo" tmp-name) "foo"))
+              (equal (file-name-all-completions "fo" tmp-name) '("foo")))
+               (should (equal (file-name-completion "fo" tmp-name) "foo"))
+  (should (equal (string-replace "fo" "bar" "lafofofozot")
+    (should (= (replace-regexp-in-region "fo+" "new" (point-min) (point-max))
+    (should (= (replace-regexp-in-region "fo+" "new" (point-min) 14)
+    (should-error (replace-regexp-in-region "fo+" "new" (point-min) 30)))
+    (should (= (replace-regexp-in-region "Fo+" "new" (point-min))
+  (should-not (yank-media--utf-16-p "fo"))
+  (should (equal (fns-tests--with-region base64-encode-region "fo") "Zm8="))
+  (should (equal (base64-encode-string "fo") "Zm8="))
+  (should (equal (fns-tests--with-region base64url-encode-region "fo") "Zm8="))
+  (should (equal (fns-tests--with-region base64url-encode-region "fo" t) 
"Zm8"))
+  (should (equal (fns-tests--with-region base64url-encode-region 
(fns-tests--string-repeat "fo" 50) t)
+  (should (equal (base64url-encode-string "fo") "Zm8="))
+  (should (equal (base64url-encode-string "fo" t) "Zm8"))
+  (should (equal (base64url-encode-string (fns-tests--string-repeat "fo" 50) 
t) (concat (fns-tests--string-repeat "Zm9mb2Zv" 16) "Zm9mbw")))
+  (should (equal (base64-decode-string "Zm8=") "fo"))
+  (should (equal (base64-decode-string "Zm8" t) "fo"))
+  (should (equal (base64-decode-string "Zm8=" t) "fo"))
+                 (fns-tests--string-repeat "fo" 50)))
+@samp{o} (oblique), @samp{ri} (reverse italic), or @samp{ot} (other).
+@deffn Method project-update-version :AFTER ot
+The @code{:version} of the project @var{OT} has been updated.
+@deffn Method project-remove-file :AFTER ot fnnd
+Remove the current buffer from project target @var{OT}.
+@deffn Method project-delete-target :AFTER ot
+Delete the current target @var{OT} from its parent project.
+@deffn Method project-edit-file-target :AFTER ot
+Edit the target @var{OT} associated with this file.
+@deffn Method project-add-file :AFTER ot file
+Add the current buffer into project target @var{OT}.
+-      (font (nil phetsarath\ ot unicode-bmp)))
+  "Remove the current buffer from project target OT.
+(cl-defmethod project-update-version ((ot ede-project))
+  "The :version of the project OT has been updated.
+  (error "project-update-version not supported by %s" (eieio-object-name ot)))
+  ;;  no  so  ea  we  ne  se  nw  sw  up  do  in  ot
+  ;; no  so  ea  we  ne  se  nw  sw  up  do  in  ot
+  (define-key vhdl-template-map "ot"   #'vhdl-template-others)
+  { 200, { "italic" ,"i", "ot" }},
+(cl-defmethod oclosure-interactive-form ((ot oclosure-test))
+  (let ((snd (oclosure-test--snd ot)))
+       (math-simplify-divisor): Only bind math-simplify-divisor-[nd]over
+     @result{} Nd
+   "s section[eg- emacs / p4-blame]:\nD source-dir: \nD output-dir: ")
+(define-key ctl-x-map "nd" 'narrow-to-defun)
+    (aref ["th" "st" "nd" "rd"] (% n 10))))
+  (let* ((nd date)
+        (setq nd (list (car date) (1+ (cadr date))
+        (setq nd (list (car date) (1- (cadr date))
+    (setq nd (calendar-gregorian-from-absolute ; date standardization
+              (calendar-absolute-from-gregorian nd)))
+    (list nd ut)))
+  (interactive "*P\nd")
+  (interactive "^p\nd")
+  (interactive "^p\nd\nd")
+                             (if (string= "" nd)
+                               (concat "\\`" (regexp-quote nd)))
+        (nd (file-name-nondirectory auto-save-list-file-prefix)))
+               ((= digit 2) "nd")
+   \"s section[eg- emacs / p4-blame]:\\nD source-dir: \\nD output-dir: \")
+  (interactive "D source directory: \nD output directory: ")
+(defun mailcap-parse-mailcap-extras (st nd)
+      (narrow-to-region st nd)
+    ("New York" . "ny") ("North Carolina" . "nc") ("North Dakota" . "nd")
+  '(Lu Ll Lt Lm Lo Mn Mc Me Nd Nl No Pc Pd
+(xsdre-def-derived-category 'N '(union Nd Nl No))
+         "cm=^p=%+ %+ :cr=^p^a:le=^p^b:nd=^p^f:"
+p(aragraph), P(age), f(unction in C/Pascal etc.), w(ord), e(nd of sentence),
+;;  - an ordinal suffix (st, nd, rd, th) for the year
+    - an ordinal suffix (st, nd, rd, th) for the year
+    '(", *\\(e\\(nd\\|rr\\)\\)\\> *\\(= *\\([0-9]+\\)\\)?"
+  
"\\<\\(&&\\|and\\|b\\(egin\\|reak\\)\\|c\\(ase\\|o\\(mpile_opt\\|ntinue\\)\\)\\|do\\|e\\(lse\\|nd\\(case\\|else\\|for\\|if\\|rep\\|switch\\|while\\)?\\|q\\)\\|for\\(ward_function\\)?\\|g\\(oto\\|[et]\\)\\|i\\(f\\|nherits\\)\\|l[et]\\|mod\\|n\\(e\\|ot\\)\\|o\\(n_\\(error\\|ioerror\\)\\|[fr]\\)\\|re\\(peat\\|turn\\)\\|switch\\|then\\|until\\|while\\|xor\\|||\\)\\>")
+             "and\\|begin\\|case\\|do\\|e\\(lse\\|nd\\)\\|for\\|i[fn]\\|"
+  (interactive "P\nd")
+  (interactive "*p\nd")
+  Right (tty) = tgetstr ("nd", address);
+                       "c\nd\n")))
+    (insert "a\nb\nc\nd\ne\nf")
+    (insert "a\nb\nc\nd\ne")
+  (interactive "i\nd\nP")
+       * lisp/term.el (term-termcap-format): Fix a typo in the "ue="
+Urban Engberg (ue at cci.dk),
+       * quail/latin-post.el ("german-postfix"): Do not translate ue to
+  (define-key calc-mode-map "ue" 'calc-explain-units)
+  le ue pe)
+     (bindat--make :ue ,(bindat--toplevel 'unpack type)
+       Trivial patch from Urban Engberg <ue@ccieurope.com>.
+    ("ü" "ue")
+    ("Ü" "Ue")
+;; AE -> Ä   OE -> Ö   UE -> Ü
+;; ae -> ä   oe -> ö   ue -> ü   ss -> ß
+;; AEE -> AE   OEE -> OE   UEE -> UE
+;; aee -> ae   oee -> oe   uee -> ue   sss -> ss"
+;;  ("UE" ?Ü)
+;;  ("ue" ?ü)
+;;  ("UEE" "UE")
+;;  ("uee" "ue")
+     ("Uuml" "\\\"{U}" nil "&Uuml;" "Ue" "Ü" "Ü")
+     ("uuml" "\\\"{u}" nil "&uuml;" "ue" "ü" "ü")
+:so=\\E[7m:se=\\E[m:us=\\E[4m:ue=\\E[m:md=\\E[1m:mr=\\E[7m:me=\\E[m\
+             (("\"U" "\\\"U") . "Ue")              ; "U,\"U        -> Ue
+             (("\"u" "\\\"u") . "ue")              ; "u,\"u        -> ue
+/^#undef INTERNAL_TERMINAL *$/s,^.*$,#define INTERNAL_TERMINAL "pc|bios|IBM PC 
with color 
display::co#80:li#25:Co#16:pa#256:km:ms:cm=<CM>:cl=<CL>:ce=<CE>::se=</SO>:so=<SO>:us=<UL>:ue=</UL>:md=<BD>:mh=<DIM>:mb=<BL>:mr=<RV>:me=<NV>::AB=<BG
 %d>:AF=<FG %d>:op=<DefC>:",
+       * s/msdos.h (INTERNAL_TERMINAL): Add capabilities se, so, us, ue,
+  tty->TS_exit_underline_mode = tgetstr ("ue", address);
+:bl=^G:do=^J:le=^H:ta=^I:se=\\E[27m:ue=\\E[24m\
+  const char *TS_enter_underline_mode; /* "ue" -- end underlining.  */
+       ((equal (aref (car lines) 0) "fpr")
+  (let* ((fpr (epg-sub-key-fingerprint subkey))
+        (candidates (epg-list-keys context fpr 'secret))
+      (error "Found %d secret keys with same fingerprint %s" candno fpr))
+        (fpr (epg-sub-key-fingerprint primary)))
+                      (string-match-p (concat fingerprint "$") fpr)
+            (dolist (fpr signer-fprs nil)
+                                   fpr
+                                 (substring fpr -16 nil)))
+                (let ((fpr (if (eq protocol 'OpenPGP)
+                  (should (string-match-p (concat "-r " fpr) match))))
+       time.  The reverse is true in Ireland, where standard time "IST"
+(e.g., especially with l(ist) and k(ill)).
+;; 
<http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.42.6421&rep=rep1&type=pdf>
+  ;; 
<http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.42.6421&rep=rep1&type=pdf>.
+       ("ist"             "İstanbul, Turkey")
+       consistency (e.g., esp. with l(ist) and k(ill).
+    (?F "[l]ist; [v]isit folder;\n"
+        "[s]equences, [l]ist,\n"
+        "exec~ute" "exit" "get" "help" "ho~st" "[$]" "i~nput" "l~ist"
+        (calendar-standard-time-zone-name "IST")
+              "1972-07-01 05:29:59.999 +0530 (IST)"))
+         (let ((thi (if (math-lessp hi '(float -2 0))
+                        (math-float lo) (math-float thi) 'inf)
+                 lo thi)))
+Joakim Hove wrote @file{html2text.el}, a html to plain text converter.
+Hove, Denis Howe, Lars Ingebrigtsen, Andrew Innes, Seiichiro Inoue,
+       * html2text.el: New file from Joakim Hove <hove@phys.ntnu.no>.
+;; Author: Joakim Hove <hove@phys.ntnu.no>
+Damon Anton Permezel wrote @file{hanoi.el}, an animated demonstration of
+Jeff Peck, Damon Anton Permezel, Tom Perrine, William M. Perry, Per
+;; Author: Damon Anton Permezel
+; Author (a) 1985, Damon Anton Permezel
+;; JAVE I preferred ecmascript-mode.
+;;JAVE break needs labels
+;JAVE this just instantiates a default empty ebrowse struct?
+JAVE: stub for needs-refresh, because, how do we know if BROWSE files
+;JAVE what it actually seems to do is split the original tree in "tables" 
associated with files
+    ;(semantic-fetch-tags) ;JAVE could this go here?
+JAVE this thing would need to be recursive to handle java and csharp"
+;  (re-search-forward (concat "/\\*" indicator "\\*/")); JAVE this isn't 
generic enough for different languages
+            clen cidx)
+         (setq clen (length lao-consonant))
+                   str (if (= clen 1)
+       * bidi.c (bidi_level_of_next_char): clen should be EMACS_NT, not int.
+         if (ident_length == 6 && memcmp (ident_start, "defalt", 6) == 0)
+  if (! NILP (XCHAR_TABLE (table)->defalt))
+                          Fcopy_sequence (XCHAR_TABLE (table)->defalt));
+make_sub_char_table (int depth, int min_char, Lisp_Object defalt)
+    XSUB_CHAR_TABLE (table)->contents[i] = defalt;
+  set_char_table_defalt (copy, XCHAR_TABLE (table)->defalt);
+      val = tbl->defalt;
+                      Lisp_Object defalt, bool is_uniprop, bool is_subtable)
+                                       defalt, is_uniprop);
+    val = defalt;
+                             Lisp_Object defalt, bool is_uniprop)
+                            defalt, is_uniprop, true);
+                                defalt, is_uniprop, true);
+                            tbl->defalt, is_uniprop, false);
+                                tbl->defalt, is_uniprop, false);
+    val = XCHAR_TABLE (char_table)->defalt;
+           this = XCHAR_TABLE (top)->defalt;
+      ? (dp)->defalt                                   \
+decode_env_path (const char *evarname, const char *defalt, bool empty)
+      path = ns_relocate (defalt);
+      path = defalt;
+     (name, defalt)
+      if (NILP (defalt))
+      CHECK_STRING (defalt);
+  if (CHAR_TABLE_P (vector) && ! NILP (XCHAR_TABLE (vector)->defalt))
+      (*elt_describer) (XCHAR_TABLE (vector)->defalt, args);
+       The size counts the defalt, parent, purpose, ascii,
+    Lisp_Object defalt;
+       val = tbl->defalt;
+       counts the ordinary slots and the top, defalt, parent, and purpose
+verify (offsetof (struct Lisp_Char_Table, defalt) == header_size);
+  XCHAR_TABLE (table)->defalt = val;
+   string, and DEFALT is a string, read from DEFALT instead of VAL.  */
+string_to_object (Lisp_Object val, Lisp_Object defalt)
+      if (STRINGP (defalt))
+      else if (CONSP (defalt) && STRINGP (XCAR (defalt)))
+                            Lisp_Object defalt)
+    val = string_to_object (val, CONSP (defalt) ? XCAR (defalt) : defalt);
+   DEFALT specifies the default value for the sake of history commands.
+             Lisp_Object histvar, Lisp_Object histpos, Lisp_Object defalt,
+  specbind (Qminibuffer_default, defalt);
+      val = read_minibuf_noninteractive (prompt, expflag, defalt);
+  else if (STRINGP (defalt))
+  else if (CONSP (defalt) && STRINGP (XCAR (defalt)))
+    val = string_to_object (val, defalt);
+  Lisp_Object defalt = Fassq (prop, Vtext_property_default_nonsticky);
+  if (ignore_previous_character || (CONSP (defalt) && !NILP (XCDR (defalt))))
+    val = dp->defalt;
+     Lisp_Object name, defalt;
+       defalt = current_buffer->directory;
+      newdir = SDATA (defalt);
+       val = defalt;
+       val = XCAR (defalt);
+    histstring = defalt;
+    histstring = XCAR (defalt);
+       EIEIO: Promote the CLOS behavior over the EIEIO-specific behavior
+       Change the implementation of `:initform` to better match the CLOS 
semantics,
+       (CLOS compatibility, Wish List): Adjust to new featureset.
+@cindex CLOS
+(@acronym{CLOS}), this support is based on @dfn{generic functions}.
+The Emacs generic functions closely follow @acronym{CLOS}, including
+use of similar names, so if you have experience with @acronym{CLOS},
+       * eieio.texi (Accessing Slots, CLOS compatibility): Adjust wording
+       (Method Invocation, CLOS compatibility):
+       * eieio.texi (Class Values, CLOS compatibility):
+       EIEIO and CLOS from 'Building Classes' to here.
+       (Class Values, CLOS compatibility): Mention that
+       * eieio.texi (top): Make clear that EIEIO is not a full CLOS
+to Emacs Lisp programmers.  CLOS and Common Lisp streams are fine
+a subset of CLOS functionality.  @xref{Top, , Introduction, eieio, EIEIO}.)
+The Common Lisp Object System (CLOS) is not implemented,
+CLOS functionality.
+bugs in @ede{}.  A knowledge of Emacs Lisp, and some @eieio{}(CLOS) is
+@ede{} uses @eieio{}, the CLOS package for Emacs, to define two object
+concepts of the Common Lisp Object System (CLOS).  It provides a
+* CLOS compatibility::    What are the differences?
+Lisp Object System (CLOS) and also differs from it in several aspects,
+on the other hand you are already familiar with CLOS, you should be
+aware that @eieio{} does not implement the full CLOS specification and
+@pxref{CLOS compatibility}).
+and methods using inheritance similar to CLOS.
+Method definitions similar to CLOS.
+Public and private classifications for slots (extensions to CLOS)
+Customization support in a class (extension to CLOS)
+Due to restrictions in the Emacs Lisp language, CLOS cannot be
+setf.  Here are some important CLOS features that @eieio{} presently
+This CLOS method tag is non-functional.
+will use the list as a value.  This is incompatible with CLOS (which would
+This option is in the CLOS spec, but is not fully compliant in @eieio{}.
+This option is specific to Emacs, and is not in the CLOS spec.
+what CLOS does when a monotonic class structure is defined.
+Unsupported CLOS option.  Enables the use of a different base class other
+Unsupported CLOS option.  Specifies a list of initargs to be used when
+@xref{CLOS compatibility}, for more details on CLOS tags versus
+The following accessors are defined by CLOS to reference or modify
+This is not a CLOS function.  It is therefore
+of CLOS.
+objects.  In CLOS, this would be named @code{STANDARD-CLASS}, and that
+This function takes arguments in a different order than in CLOS.
+In @var{clos}, the argument list is (@var{class} @var{object} 
@var{slot-name}), but
+@node CLOS compatibility
+@chapter CLOS compatibility
+CLOS.
+CLOS supports the @code{describe} command, but @eieio{} provides
+@eieio{} is an incomplete implementation of CLOS@.  Finding ways to
+improve the compatibility would help make CLOS style programs run
+@c LocalWords: cb cdr charquote checkcache cindex CLOS
+System (CLOS).  It is used by the other CEDET packages.
+CLOS class and slot documentation.
+  "Convert a list of CLOS class slot PARTLIST to `variable' tags."
+C++ and CLOS can define methods that are not in the body of a class
+Some languages such as C++ and CLOS permit the declaration of member
+the class.  C++ and CLOS both permit methods of a class to be defined
+;; Standard CLOS name.
+This may prevent classes from CLOS applications from being used with EIEIO
+since EIEIO does not support all CLOS tags.")
+      ;; not by CLOS and is mildly inconsistent with the :initform thingy, so
+            ;; (but not CLOS) but is a bad idea (for one: it's slower).
+  "Abstractly modify a CLOS object."
+  "Instance of a CLOS class."
+;; CLOS, the Common Lisp Object System.  In addition, EIEIO also adds
+The following are extensions on CLOS:
+Options in CLOS not supported in EIEIO:
+       ;; test, so we can let typep have the CLOS documented behavior
+;;; Handy CLOS macros
+;; CLOS name, maybe?
+The CLOS function `class-direct-superclasses' is aliased to this function."
+The CLOS function `class-direct-subclasses' is aliased to this function."
+;; Official CLOS functions.
+;;; CLOS queries into classes and slots
+;; FIXME: CLOS uses "&rest INITARGS" instead.
+In CLOS, the argument list is (CLASS OBJECT SLOT-NAME), but
+;;; Unimplemented functions from CLOS
+                              ;; CLOS and EIEIO
+     ;; this works for SOS, STklos, SCOOPS, Meroon and Tiny CLOS.
+            ;; EIEIO's :initform is not 100% compatible with CLOS in
+;; Also test behavior of `call-next-method'.  From clos.org:
+  ;; CLOS form of make-instance
+  (interactive "p\nd\nd")
+  (interactive "p\nd")
+    (let (st nd pt)
+                            (setq nd (match-beginning 0)
+                                  pt nd)
+                        (setq nd (match-beginning 0)
+                            (setq nd (match-beginning 0))))
+                      (setq nd (match-beginning 0)))
+                    (or st nd))))
+       (narrow-to-region (or st (point-min)) (or nd (point-max)))
+           (when nd
+             (goto-char nd)
+  (fortran-blink-match "e\\(nd[ \t]*if\\|lse\\([ \t]*if\\)?\\)\\b"
+  ;; FIXME: `foo a!nd bar' should transpose into `bar and foo'.
+         (make-directory nd t)
+         (speedbar-goto-this-file nd)
+       (let ((nd (file-name-nondirectory file)))
+              (concat "] \\(" (regexp-quote nd)
+:nd=\\E[C:up=\\E[A:ce=\\E[K:ho=\\E[H:pt\
+(defun url-http-content-length-after-change-function (_st nd _length)
+       (funcall byte-count-to-string-function (- nd url-http-end-of-headers))
+       (url-percentage (- nd url-http-end-of-headers)
+     (funcall byte-count-to-string-function (- nd url-http-end-of-headers))
+     (url-percentage (- nd url-http-end-of-headers)
+  (if (> (- nd url-http-end-of-headers) url-http-content-length)
+(defun url-http-chunked-encoding-after-change-function (st nd length)
+                         url-http-chunked-counter st nd length)
+             (if (> nd (+ url-http-chunked-start url-http-chunked-length))
+                                  nd))
+(defun url-http-wait-for-headers-change-function (_st nd _length)
+         (setq nd (- nd (url-http-clean-headers)))))
+         (when (> nd url-http-end-of-headers)
+            (marker-position url-http-end-of-headers) nd
+            (- nd url-http-end-of-headers))))
+          ((> nd url-http-end-of-headers)
+            nd
+            (- nd url-http-end-of-headers)))
+  Lu, Ll, Lt, Lm, Lo, Mn, Mc, Me, Nd, Nl, No, Pc, Pd, Ps, Pe, Pi, Pf, Po,
+    const char *cm_right;      /* right (nd) */
+      (should (equal (ert-test-result-messages result) "a\nb\nc\nd\n")))))
+      (insert "a\nb\nc\nd\n")
+    (insert "a\nb\nc\nd\n")
+    (should (string= (buffer-string) "Abc\nd efg\n(h ijk)."))))
+              (nd (read-directory-name "Create directory: "
+DESCRIPTION:In this meeting\\, we will cover topics from product and enginee
+@item @samp{.crate} ---
+@cindex @file{crate} file archive suffix
+@cindex file archive suffix @file{crate}
+;; * ".crate" - Cargo (Rust) packages
+    "crate" ;; Cargo (Rust) packages.  Not in libarchive testsuite.
+      ;; RFC5546 refers to uninvited attendees as "party crashers".
+That includes both spelling (e.g., "behavior", not "behaviour") and
+       * doc/lispref/control.texi (Signalling Errors)
+Re "behavior" vs "behaviour", etc.
++ 
[[https://protesilaos.com/codelog/2020-07-08-modus-themes-nuanced-colours/][Modus
 themes: major review of "nuanced" colours]] (2020-07-08)
++ 
[[https://protesilaos.com/codelog/2020-09-14-modus-themes-review-blues/][Modus 
themes: review of blue colours]] (2020-09-14)
++ 
[[https://protesilaos.com/codelog/2021-01-11-modus-themes-review-select-faint-colours/][Modus
 themes: review of select "faint" colours]] (2021-01-11)
++ 
[[https://protesilaos.com/codelog/2022-01-02-review-modus-themes-org-habit-colours/][Modus
 themes: review of the org-habit graph colours]] (2022-01-02)
++ 
[[https://protesilaos.com/codelog/2022-04-20-modus-themes-case-study-avy/][Modus
 themes: case study on Avy faces and colour combinations]] (2022-04-20)
++ 
[[https://protesilaos.com/codelog/2022-04-21-modus-themes-colour-theory/][Emacs:
 colour theory and techniques used in the Modus themes]] (2022-04-21)
+ *  :- initialise
+ *  :- finalise
+  "initialise", "finalise", "mutable", "module", "interface", "implementation",
+;;;                     ( A cancelled )  Ignore this cache entry;
+       (.DEFAULT): Use $(FLAVOUR) instead of $@ for clarity.
+1998-04-26  Justin Sheehy  <justin@linus.mitre.org>
+1997-10-25  David S. Goldberg  <dsg@linus.mitre.org>
+;; Updated by the RIPE Network Coordination Centre.
+;; Thanks to jond@mitre.org (Jonathan Doughty) for help with code for
+         (when (and ok tod (not (string-match "\\`DONE\\|CANCELLED" evt)))
+"all" "analyse" "analyze" "and" "array" "asc" "as" "asymmetric"
+    \"VHDL Modelling Guidelines\".
+  {WSAECANCELLED           , "Operation cancelled"},       /* not sure */
+  {WSA_E_CANCELLED         , "Operation already cancelled"}, /* really not 
sure */
+       2013-09-26 dup2, dup3: work around another cygwin crasher
+       cc3ad9a ; * CONTRIBUTE: Clarify rules for committing to release branc...
+Paul Raines (raines at slack.stanford.edu),
+    \qquad date: b)efore, a)t, n)this,\\*
+place an (I)nstall flag on the available version and a (D)elete flag
+       Improved verbiage of prompt. Aliases are now inserted "[b]efore"
+       or "[a]fter" the existing alias instead of "[i]nsert" or
+                                       "[b]efore or [a]fter: ")
+    (let* ((max (read-char "Number of [e]ntries [t]odos [T]ags [E]ffort? "))
+       (mark_image): Move from allo.c.
+Forward propagate immediate involed in assignments." ; FIXME: Typo.  Involved 
or invoked?
+            (setq te (org-insert-time-stamp (or at-time now) 'with-hm 
'inactive))
+                     (org-time-string-to-time te)
+                    (te (org-time-string-to-seconds se))
+                    (dt (- (if tend (min te tend) te)
+                te (match-string 3))
+          (setq s (- (org-time-string-to-seconds te)
+    ("te"  :babel-ini-only "telugu" :polyglossia "telugu" :lang-name "Telugu")
+2016-09-10  Toke Høiland-Jørgensen  <toke@toke.dk>  (tiny change)
+       Reported by Toke Høiland-Jørgensen <toke@toke.dk>.
+2012-07-17  Toke Høiland-Jørgensen  <toke@toke.dk>  (tiny change)
+2012-06-17  Toke Høiland-Jørgensen  <toke@toke.dk>  (tiny change)
+(doctor-put-meaning toke 'toke)
+                      "\\|"                    ; per toke.c
+               const struct sockaddr *to, int tolen);
+2014-11-26  Toke Høiland-Jørgensen  <toke@toke.dk>  (tiny change)
+          ptrdiff_t tolen = strlen (key_symbols[i].to);
+          eassert (tolen <= fromlen);
+          memcpy (match, key_symbols[i].to, tolen);
+          memmove (match + tolen, match + fromlen,
+          len -= fromlen - tolen;
+          p = match + tolen;
+                         const struct sockaddr * to, int tolen);
+           const struct sockaddr * to, int tolen)
+      int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
+Put dialogue in buffer."
+  "Function called by ], the ket.  View registers and call ]]."
+;;   Matches a char which is a constituent of a variable or number, or a ket
+(defun verilog-expand-vector-internal (bra ket)
+  "Given start brace BRA, and end brace KET, expand one line into many lines."
+                  (regexp-quote ket)
+                             (int-to-string (car vec)) ket sig-tail "\n"))
+           m | mo | mot | moti | motif )       val=motif ;;
+    i | in | ino | inot | inoti | inotif | inotify )   val=inotify ;;
+2001-04-23  Kahlil Hodgson  <kahlil@discus.anu.edu.au>
+        (funcall expect 20 "ingenuous")))))
+ (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: Mehercle! if their sons 
be ingenuous, they shall want no instruction; if their daughters be capable, I 
will put it to them. But, vir sapit qui pauca loquitur. A soul feminine 
saluteth us."))
+        (search-forward "return te")
+           "fn test() -> i32 { let test=3; return te; }"))))
+             ts te h m s neg)
+                  te (match-string 3))
+            (setq s (- (org-time-string-to-seconds te)
+       Rename from whitespace-skipping-for-quotes-not-ouside.
+       (whitespace-skipping-for-quotes-not-ouside)
+Thread-Modell: posix
+(ert-deftest indent-sexp-cant-go ()
+(ert-deftest thunk-let-bound-vars-cant-be-set-test ()
+              (mml-secure-cust-fpr-lookup context 'encrypt "sub@example.org")))
+       (let ((p-e-fprs (mml-secure-cust-fpr-lookup
+            (p-s-fprs (mml-secure-cust-fpr-lookup
+       (let ((s-e-fprs (mml-secure-cust-fpr-lookup
+            (s-s-fprs (mml-secure-cust-fpr-lookup
+(ert-deftest doesnt-time-out ()
+(ert-deftest json-el-cant-serialize-this ()
+    (should (equal (try-completion "B-hel" subvtable)
+    (should (equal (all-completions "B-hel" subvtable) '("-hello")))
+    (should (equal (completion-boundaries "B-hel" subvtable
+(ert-deftest ruby-regexp-doesnt-start-in-string ()
+       Rename from wisent-inaccessable-symbols, fixing a misspelling.
+ ("calc-math" calcFunc-alog calcFunc-arccos
+                             ( ?B 2 calcFunc-alog )
+       (change-log-function-face, change-log-acknowledgement-face):
+       (bs-appearance) <defgroup>: Renamed from bs-appearence.
+       typo `fortran-strip-sqeuence-nos'.
+       * progmodes/fortran.el (fortran-strip-sqeuence-nos): Doc fix.
+       (fortran-strip-sqeuence-nos): Make arg optional.  Fix regexp and
+1999-06-01  Jae-youn Chung  <jay@compiler.kaist.ac.kr>
+doc/emacs/docstyle.texi:14: fied ==> field
+(define-obsolete-variable-alias 'hfy-optimisations 'hfy-optimizations "25.1")
+(define-obsolete-function-alias 'hfy-colour-vals #'hfy-color-vals "27.1")
+(define-obsolete-function-alias 'hfy-colour #'hfy-color "27.1")
+(define-obsolete-variable-alias 'eglot-ignored-server-capabilities
+       setenv ("TZ", "IST-02IDT-03,M4.1.6/00:00,M9.5.6/01:00", 0);
+    "kana-TA", "kana-CHI", "kana-TSU", "kana-TE",
+       (internal--after-with-selected-window): Fix typo seleted->selected.
+       * subr.el (internal--before-with-seleted-window)
+       (internal--after-with-seleted-window): New functions.
+       * follow.el (follow-inactive-menu): Rename from follow-deactive-menu.
+       * emacs-lisp/cconv.el (cconv-analyse-form): Warn use of ((λ ...) ...).
+       (feedmail-sendmail-f-doesnt-sell-me-out)
+       Respect feedmail-sendmail-f-doesnt-sell-me-out.
+       * terminal.el (te-get-char, te-tic-sentinel):
+from server-external-socket-initialised, since it should be
+       * lisp/server.el: (server-external-socket-initialised): New
+       Rename from help-fns--analyse-function.
+       c-ambiguous-overloadable-or-identifier-prefices.  Caller changed.
+       * lisp/progmodes/cc-langs.el 
(c-ambiguous-overloadable-or-identifier-prefices)
+       Rename from nndiary-last-occurence.
+       Rename from nndiary-next-occurence.  All uses changed.
+       lisp/textmodes/flyspell.el (flyspell-ajust-cursor-point): Rename to
+       * test/file-organization.org: Rename from test/file-organisation.org.
+       character class (namely ‘fo’ leaving ‘o’ in the string), but since the
+       change-log-acknowledgement-face):
+       9daf1cf * etc/NEWS: Improve wording of vc-git-log-output-coding-syste...
+       a05fb21 * lisp/emacs-lisp/package.el (package-install-selected-packag...
+       5cc6919 Fix a caching bug, which led to inordinately slow c-beginnin...
+       (mml-secure-cust-usage-lookup, mml-secure-cust-fpr-lookup)
+       * test/file-organisation.org: New file.
+    ("test/file-organisation.org" . "file-organization.org")
+       `message-insert-formated-citation-line'.
+      info.addons = (\"hald-addon-acpi\")
+       deactive->inactive, inactivate->deactivate spelling fixes (Bug#10150)
+       (org-detach-overlay): Rename from `org-detatch-overlay'.
+       (change-log-acknowledgement): Remove "-face" suffix from face names.
+       (appt-visible): Rename from appt-visable.
+       (pascal-seperator-keywords): Renamed to pascal-separator-keywords.
+       mouse-union-first-prefered.
+       * sc.el (sc-consistent-cite-p): Renamed from sc-consistant-cite-p.
+       bibtex-name-alignement.
+   "d-elete, u-ndelete, x-punge, f-ind, o-ther window, R-ename, C-opy, h-elp"))
+       (erc-coding-sytem-for-target): Removed.
+       (erc-coding-sytem-for-target): New.
+Paul Raines (raines at slac.stanford.edu),
+    "union" "unsafe" "use" "where" "while" (crate) (self) (super)
+       term-ansi-face-alredy-done.
+       (ebnf-syntactic): Change group name and tag from "ebnf-syntatic".
+       "ebnf-syntatic".
+       Rename from ucs-input-inactivate.
+       Rename from hangul-input-method-inactivate.
+       * terminal.el (te-create-terminfo): Use make-temp-file
+       (org-detatch-overlay, org-move-overlay, org-overlay-put):
+  'gnus-score-find-favourite-words
+  'nndiary-last-occurence
+  'nndiary-next-occurence
+(define-obsolete-function-alias 'org-truely-invisible-p
+(define-obsolete-variable-alias 'eglot-ignored-server-capabilites
+            ("`fo"  . "format"       )
+(define-obsolete-function-alias 'rtree-normalise-range
+       `org-attch-delete'.  Add a security query before deleting the
+       `org-toggel-region-headings'.
+   "3 Oktober 2000 16:30 multiline
+                   "September" "Oktober" "November" "Dezember"])
+   "de la Cognée"          "de l'Ellébore"         "du Brocoli"
+       1fe596d89f (origin/emacs-27) Fix another compilation problem in a bui...
+   "du Buis"               "du Lichen"             "de l'If"
+    if (c == BIG) {            /* caint get thar from here */
+       Christoph Groth <cwg@falma.de> and Liu Xin <x_liu@neusoft.com>.
+    "passord"          ; nb
+  (should (equal (rfc6068-unhexify-string "caf%C3%A9") "café")))
+   (equal (rfc6068-parse-mailto-url 
"mailto:user@example.org?subject=caf%C3%A9&body=caf%C3%A9";)
+;; Paul Lew <paullew@cisco.com> suggested implementing fixed width
+       (TUNG@WAIF.MIT.EDU <8704130324.AA10879@prep.ai.mit.edu>)
+    (ruby-ts-mode "*.r[bu]" "*.rake" "*.gemspec" "*.erb" "*.haml"
+(doctor-put-meaning cunt 'sexnoun)
+(doctor-put-meaning cunts 'sexnoun)
+(doctor-put-meaning skool 'school)
+       Add ".crate" to Tramp archive file suffixes.
+       * lisp/net/tramp-archive.el (tramp-archive-suffixes): Add ".crate".
+2021-11-10  Benj  <Benjamin.Schwerdtner@gmail.com>  (tiny change)
+       allow party crashers to respond to ical events
+       calling those respondents "party crashers".
+2019-12-17  Antoine Kalmbach  <ane@iki.fi>  (tiny change)
+2014-02-18  Matus Goljer  <dota.keys@gmail.com>
+2014-02-13  Matus Goljer  <dota.keys@gmail.com>
+2004-05-20  Magnus Henoch  <mange@freemail.hu>
+2004-11-14  Magnus Henoch  <mange@freemail.hu>
+2006-10-16  Magnus Henoch  <mange@freemail.hu>
+2006-11-01  Magnus Henoch  <mange@freemail.hu>
+2006-11-08  Magnus Henoch  <mange@freemail.hu>
+2006-11-15  Magnus Henoch  <mange@freemail.hu>
+2006-11-26  Magnus Henoch  <mange@freemail.hu>
+2006-12-08  Magnus Henoch  <mange@freemail.hu>
+2007-01-14  Magnus Henoch  <mange@freemail.hu>
+2007-10-28  Magnus Henoch  <mange@freemail.hu>
+2007-12-03  Magnus Henoch  <mange@freemail.hu>
+2008-02-04  Magnus Henoch  <mange@freemail.hu>
+2008-03-09  Magnus Henoch  <mange@freemail.hu>
+2008-09-30  Magnus Henoch  <mange@freemail.hu>
+                      (secnd (cdr (cadr dlist))))
+                                    (car secnd))) ; fetch_date
+                        secnd (cdr secnd))
+                                    (car secnd))) ; Keep_flag
+                                    (car secnd))) ; NOV_entry_position
+@c LocalWords: DesBrisay Dcc devel dir dired docstring filll forw
+Older versions of the themes provided options ~grayscale~ (or ~greyscale~)
+       > The requestor should delete [...] the property specified in the
+       We are not the requestor, so we should not be deleting this property
+       needs to remain available as the requestor will generally want to read
+               [t]ime [s]cheduled  [d]eadline  [c]reated  cloc[k]ing
+  (message "Sparse tree: [r]egexp [t]odo [T]odo-kwd [m]atch [p]roperty
+;;    -grey    Render in greyscale as 8bits/pixel.
+   -grey       Render in greyscale as 8bits/pixel.
+         (if (looking-at "p\\(ublic\\|rotected\\|rivate\\)")
+              "\\=p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\>[^_]" nil t)
+                          
"\\(p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|more\\)\\>"
+       * sysdep.c (WRITABLE): Renamed from WRITEABLE.
+DEFUN ("cond", Fcond, Scond, 0, UNEVALLED, 0,
+  defsubr (&Scond);
+    /* XXX: who is wrong, the requestor or the implementation?  */
+  /* "Data" to send a requestor for a failed MULTIPLE subtarget.  */
+  /* This formula is from a paper titled `Colour metric' by Thiadmer Riemersma.
+ (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: Good gentleman, go your 
gait, and let poor volk pass. An chud ha' bin zwaggered out of my life, 'twould 
not ha' bin zo long as 'tis by a vortnight. Nay, come not near th' old man; 
keep out, che vor ye, or ise try whether your costard or my ballow be the 
harder. Chill be plain with you.")
+       db "create table if not exists test10 (col1 text, col2 blob, col3 
numbre)")
+          (const :format "[%v] %t\n" :tag "Alias for `gray-background'" 
greyscale)
+2008-09-11  Magnus Henoch  <mange@freemail.hu>
+       <mange@freemail.hu>.
+2006-10-07  Magnus Henoch  <mange@freemail.hu>
+2006-09-07  Magnus Henoch  <mange@freemail.hu>
+       Reported by Magnus Henoch <mange@freemail.hu>.
+2005-09-24  Magnus Henoch  <mange@freemail.hu>
+2005-09-17  Magnus Henoch  <mange@freemail.hu>
+2005-09-10  Magnus Henoch  <mange@freemail.hu>
+2005-08-09  Magnus Henoch  <mange@freemail.hu>
+2008-10-16  Magnus Henoch  <mange@freemail.hu>
+2008-10-01  Magnus Henoch  <mange@freemail.hu>
+2008-07-02  Magnus Henoch  <mange@freemail.hu>
+2008-04-23  Magnus Henoch  <mange@freemail.hu>
+2008-03-28  Magnus Henoch  <mange@freemail.hu>
+       * bibtex.el (bibtex-entry): Add OPTkey/annote.  If OPTcrossref set
+;; :booktitle     :month          :annote      :abstract
+    (:annote       . "An annotation.  It is not used by the standard 
bibliography styles, but may be used by others that produce an annotated 
bibliography.")
+       :annote (or (cdr (assoc "annote" entry)) "[no annotation]")
+  '(("annote" "Personal annotation (ignored)"))
+      (r2b-put-field "annote" r2bv-annote)
+2006-10-29  Magnus Henoch  <mange@freemail.hu>
+2006-10-28  Magnus Henoch  <mange@freemail.hu>
+2006-10-27  Magnus Henoch  <mange@freemail.hu>
+2006-10-12  Magnus Henoch  <mange@freemail.hu>
+2006-10-11  Magnus Henoch  <mange@freemail.hu>
+2006-10-09  Magnus Henoch  <mange@freemail.hu>
+2007-12-31  Magnus Henoch  <mange@freemail.hu>
+2007-12-05  Magnus Henoch  <mange@freemail.hu>
+       (ENUMABLE): Remove; no longer needed.
+       * lisp.h (ENUMABLE) [!_AIX]: Don't define to 0 merely because we're
+       * lisp.h (ENUMABLE, DEFINE_GDB_SYMBOL_ENUM): New macros.
+       * lisp.h (ENUMABLE, DEFINE_GDB_SYMBOL_ENUM): Delete macros.
+2023-06-29  Andrew G Cohen  <cohen@andy.bu.edu>
+2023-05-07  Andrew G Cohen  <cohen@andy.bu.edu>
+          C-x b fo
+       avoid failures due to MS-Windows "numeric tails" (mis)feature and
+2022-04-07  Andrew G Cohen  <cohen@andy.bu.edu>
+2022-04-03  Andrew G Cohen  <cohen@andy.bu.edu>
+2022-03-22  Andrew G Cohen  <cohen@andy.bu.edu>
+2022-03-20  Andrew G Cohen  <cohen@andy.bu.edu>
+2022-03-17  Andrew G Cohen  <cohen@andy.bu.edu>
+2022-03-04  Andrew G Cohen  <cohen@andy.bu.edu>
+2022-02-18  Andrew G Cohen  <cohen@andy.bu.edu>
+2022-02-11  Andrew G Cohen  <cohen@andy.bu.edu>
+2022-02-08  Andrew G Cohen  <cohen@andy.bu.edu>
+2022-02-03  Andrew G Cohen  <cohen@andy.bu.edu>
+2021-12-21  Andrew G Cohen  <cohen@andy.bu.edu>
+2021-12-18  Andrew G Cohen  <cohen@andy.bu.edu>
+       6d5886e780 * test/lisp/repeat-tests.el (repeat-tests-call-b): Test fo...
+       0771d8939a * etc/PROBLEMS: Mention problems with regexp matcher.  (Bu...
+       59df93e2dd * lisp/help.el (help--analyze-key): Add new arg BUFFER (bu...
+       3832b983cf In Fdelete_other_windows_internal fix new total window siz...
+       3a9d5f04fb Mention ffap-file-name-with-spaces in the ffap doc strin
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+@item Unform
+J. Otto Tennant,
+extern struct servent *hes_getservbyname (/* char *, char * */);
+  struct servent *servent;
+      servent = hes_getservbyname (service, "tcp");
+      if (servent)
+      servent = getservbyname (service, "tcp");
+         struct servent *srv = getservbyname (service, protocol);
+2003-04-10  Sebastian Tennant  <seb@albert.vcisp.net>  (tiny change)
+       Reported by Sebastian Tennant <sebyte@smolny.plus.com>.
+       causing truncation of AUTOWIRE signals.  Reported by Bruce Tennant.
+       Tennant.
+1997-10-21  Jens Lautenbacher  <jens@metrix.de>
+  unform       Use unformatted display: add(a, mul(b,c)).
+                       (memq calc-language '(nil flat unform))
+          (memq calc-language '(nil flat unform)))
+                          '(flat big unform))))
+;; Sebastian Tennant <sebyte@smolny.plus.com>
+                    (message "Mark as unread: (n)one / (a)ll / all 
(d)ownloaded articles? (n) ")
+          (wheight (window-height))
+          (rest (- wheight pheight)))
+       (vai #xA500)
+       (vai\  . vai)
+                 ts te h m s neg)
+                      te (match-string 3))
+                (setq s (- (org-time-string-to-seconds te)
+(defun dun-listify-string (strin)
+    (while (setq end-pos (string-match "[ ,:;]" (substring strin pos)))
+                                           (substring strin pos end-pos))))))
+(defun dun-listify-string2 (strin)
+    (while (setq end-pos (string-search " " (substring strin pos)))
+"any" "append" "as" "asc" "ascic" "async" "at_begin" "at_end" "audit"
+          "attribute" "(d)eclaration or (s)pecification?" t) ?s)
+                "quantity" "(f)ree, (b)ranch, or (s)ource quantity?" t)))
+  "Spacify table frame.
+    ("\\oint" . ?∮)
+struct servent * sys_getservbyname (const char * name, const char * proto);
+       Supplement, Latin Extended-A/B, Vai, Supplemental Punctuation, Tai
+       Remove the "mis;tak-+;;" line from the code; apparently this
+       it->dpvec_char_len if dpend reached.
+                                       3:000MSTRIN[0]STRIN[1]STRIN[2]
+                                       [2:000MSTRIN[0]STRIN[1]STRIN[2]]
+  Lisp_Object *dpvec, *dpend;
+             struct servent *svc_info
+struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * 
proto);
+struct servent *
+  struct servent * serv;
+         struct servent *srv = sys_getservbyname (service, protocol);
+      /* Reset bits 4 (Phonetic), 12 (Vai), 14 (Nko), 27 (Balinese).  */
+  DEFSYM (Qvai, "vai");
+      it->dpend = v->contents + v->header.size;
+      it->dpend = default_invis_vector + 3;
+                 it->dpend = v->contents + v->header.size;
+             it->dpend = it->dpvec + ctl_len;
+      if (it->dpvec + it->current.dpvec_index >= it->dpend)
+  if (it->dpend - it->dpvec > 0        /* empty dpvec[] is invalid */
+      if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
+          && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
+         && it->dpvec + it->current.dpvec_index != it->dpend);
+VERY VERY LONG STRIN | VERY VERY LONG STRIN
+    (ert-info ("Joined by bouncer to #foo, pal persent")
+    (ert-info ("Joined by bouncer to #chan@foonet, pal persent")
+    (ert-info ("Joined by bouncer to #chan@barnet, pal persent")
+.UE .
diff --git a/admin/codespell/codespell.ignore b/admin/codespell/codespell.ignore
new file mode 100644
index 00000000000..34de02e969b
--- /dev/null
+++ b/admin/codespell/codespell.ignore
@@ -0,0 +1,41 @@
+acknowledgements
+afile
+ake
+analogue
+ans
+bloc
+blocs
+callint
+clen
+crossreference
+crossreferences
+debbugs
+dedented
+dependant
+doas
+ede
+grey
+gud
+ifset
+inout
+keypair
+keyserver
+keyservers
+lightening
+mapp
+master
+mimicks
+mitre
+msdos
+ot
+parm
+parms
+reenable
+reenabled
+requestor
+sie
+spawnve
+statics
+stdio
+texline
+typdef
diff --git a/admin/codespell/codespell.rc b/admin/codespell/codespell.rc
new file mode 100644
index 00000000000..9ef5f40369c
--- /dev/null
+++ b/admin/codespell/codespell.rc
@@ -0,0 +1,4 @@
+[codespell]
+skip=.git/*,*.elc,*.eln,*.gpg,*.gz,*.icns,*.jpg,*.kbx,*.key,*.pbm,*.png,*.rnc,*.so,*.tiff,*.tit,*.xml,*.xpm,*.zip,*random_seed
+builtin=clear,rare,en-GB_to_en-US
+quiet-level=35
diff --git a/admin/cus-test.el b/admin/cus-test.el
index c833ddacd84..10d6e34358d 100644
--- a/admin/cus-test.el
+++ b/admin/cus-test.el
@@ -1,6 +1,6 @@
 ;;; cus-test.el --- tests for custom types and load problems  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998, 2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000, 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Markus Rost <rost@math.uni-bielefeld.de>
 ;; Created: 13 Sep 1998
@@ -146,7 +146,7 @@ Names should be as they appear in loaddefs.el.")
 
 (defvar cus-test-errors nil
   "List of problematic variables found by `cus-test-apropos'.
-Each element is (VARIABLE . PROBLEM); see `cus-test--format-problem'.")
+Each element is (VARIABLE . PROBLEM); see `cus-test--format-error'.")
 
 (defvar cus-test-tested-variables nil
   "List of options tested by last call of `cus-test-apropos'.")
@@ -424,7 +424,12 @@ in the Emacs source directory."
   (mapatoms
    ;; This code is mainly from `custom-load-symbol'.
    (lambda (symbol)
-     (let ((custom-load-recursion t))
+     (let ((custom-load-recursion t)
+           (load-path
+            (cons
+             (expand-file-name
+              "quail" (file-name-directory (locate-library 
leim-list-file-name)))
+             load-path)))
        (dolist (load (get symbol 'custom-loads))
         (cond
          ((symbolp load)
diff --git a/admin/diff-tar-files b/admin/diff-tar-files
index 89abc7fa382..9b34d9c4538 100755
--- a/admin/diff-tar-files
+++ b/admin/diff-tar-files
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Copyright (C) 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/admin/emacs-shell-lib b/admin/emacs-shell-lib
index 67f76f61300..1c4d895fdb4 100644
--- a/admin/emacs-shell-lib
+++ b/admin/emacs-shell-lib
@@ -1,7 +1,7 @@
 #!/bin/bash
 ### emacs-shell-lib - shared code for Emacs shell scripts
 
-## Copyright (C) 2022-2023 Free Software Foundation, Inc.
+## Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ## Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/admin/emake b/admin/emake
index c9e59d34067..93958740dc2 100755
--- a/admin/emake
+++ b/admin/emake
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# Copyright (C) 2022-2023 Free Software Foundation, Inc.
+# Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/admin/find-gc.el b/admin/find-gc.el
index 7cb319d867a..7c5672f4a46 100644
--- a/admin/find-gc.el
+++ b/admin/find-gc.el
@@ -1,6 +1,6 @@
 ;;; find-gc.el --- detect functions that call the garbage collector  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 
diff --git a/admin/git-bisect-start b/admin/git-bisect-start
index 30a738267fa..f9933b3ae4d 100755
--- a/admin/git-bisect-start
+++ b/admin/git-bisect-start
@@ -6,7 +6,7 @@
 ### default options, on a GNU/Linux computer and with GCC; see below),
 ### are skipped.
 
-## Copyright (C) 2022-2023 Free Software Foundation, Inc.
+## Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ## This file is part of GNU Emacs.
 
@@ -84,7 +84,7 @@ done
 # SKIP-BRANCH 58cc931e92ece70c3e64131ee12a799d65409100
 
 ## The list below is the exhaustive list of all commits between Dec 1
-## 2016 and Oct 2 2023 on which building Emacs with the default
+## 2016 and Jan 13 2024 on which building Emacs with the default
 ## options, on a GNU/Linux computer and with GCC, fails.  It is
 ## possible (though unlikely) that building Emacs with non-default
 ## options, with other compilers, or on other platforms, would succeed
@@ -1788,3 +1788,9 @@ $REAL_GIT bisect skip $(cat $0 | grep '^# SKIP-SINGLE ' | 
sed 's/^# SKIP-SINGLE
 # SKIP-SINGLE f7fd21b06865d20a16c11e20776e843db24d4b14
 # SKIP-SINGLE 35fbf6f15830f576fd1909f4a8d30e7ba1d777bd
 # SKIP-SINGLE 0e44ab5f061c81874dd8298a0f3318f14ef95a24
+# SKIP-SINGLE 4675aff76828b0747d1ac900d65d4a92a457ebf5
+# SKIP-SINGLE bf4d4ab4ddecffbee6d740f9c271dcca514d6a3d
+# SKIP-SINGLE 2a8e6c8c84ed33674e525625644d5ce84ee8c59a
+# SKIP-SINGLE fa5f06c1251ff717d661f05fcd240b4792054aae
+# SKIP-SINGLE d3cefd3e98354929d96c9396e5920e8a123784dc
+# SKIP-SINGLE 486094126ba77e45c50acb87f5ad3e4147608446
diff --git a/admin/gitmerge.el b/admin/gitmerge.el
index 396d2fe2ac5..7c815c729e5 100644
--- a/admin/gitmerge.el
+++ b/admin/gitmerge.el
@@ -1,6 +1,6 @@
 ;;; gitmerge.el --- help merge one Emacs branch into another  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Authors: David Engster <deng@randomsample.de>
 ;;          Stefan Monnier <monnier@iro.umontreal.ca>
diff --git a/admin/grammars/Makefile.in b/admin/grammars/Makefile.in
index 04a5e0d7205..5904c07dfcd 100644
--- a/admin/grammars/Makefile.in
+++ b/admin/grammars/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-## Copyright (C) 2013-2023 Free Software Foundation, Inc.
+## Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ## This file is part of GNU Emacs.
 
diff --git a/admin/grammars/c.by b/admin/grammars/c.by
index a152e3d8696..b3ebd3324fb 100644
--- a/admin/grammars/c.by
+++ b/admin/grammars/c.by
@@ -1,5 +1,5 @@
 ;;; c.by -- LL grammar for C/C++ language specification
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;;         David Ponce <david@dponce.com>
diff --git a/admin/grammars/grammar.wy b/admin/grammars/grammar.wy
index 1821948ffcb..a81a2df4a6f 100644
--- a/admin/grammars/grammar.wy
+++ b/admin/grammars/grammar.wy
@@ -1,6 +1,6 @@
 ;;; semantic-grammar.wy -- LALR grammar of Semantic input grammars
 ;;
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: David Ponce <david@dponce.com>
 ;; Created: 26 Aug 2002
diff --git a/admin/grammars/java-tags.wy b/admin/grammars/java-tags.wy
index 578172c0b7b..0f8f50fd606 100644
--- a/admin/grammars/java-tags.wy
+++ b/admin/grammars/java-tags.wy
@@ -1,6 +1,6 @@
 ;;; java-tags.wy -- Semantic LALR grammar for Java
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: David Ponce <david@dponce.com>
 ;; Created: 26 Aug 2002
diff --git a/admin/grammars/js.wy b/admin/grammars/js.wy
index fc68471face..13e8b756e47 100644
--- a/admin/grammars/js.wy
+++ b/admin/grammars/js.wy
@@ -1,6 +1,6 @@
 ;;; javascript-jv.wy -- LALR grammar for Javascript
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1998-2011 Ecma International.
 
 ;; Author: Joakim Verona
diff --git a/admin/grammars/make.by b/admin/grammars/make.by
index 7bee4ed0ab4..f7a8023b1cf 100644
--- a/admin/grammars/make.by
+++ b/admin/grammars/make.by
@@ -1,6 +1,6 @@
 ;;; make.by -- BY notation for Makefiles.
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;;         David Ponce <david@dponce.com>
diff --git a/admin/grammars/python.wy b/admin/grammars/python.wy
index 081a4d7ea3f..cf01ff6f5f9 100644
--- a/admin/grammars/python.wy
+++ b/admin/grammars/python.wy
@@ -1,6 +1,6 @@
 ;;; python.wy -- LALR grammar for Python
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 ;; Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
 ;; 2009, 2010 Python Software Foundation; All Rights Reserved
 
diff --git a/admin/grammars/scheme.by b/admin/grammars/scheme.by
index 288557db54e..d96529e6389 100644
--- a/admin/grammars/scheme.by
+++ b/admin/grammars/scheme.by
@@ -1,6 +1,6 @@
 ;;; scheme.by -- Scheme BNF language specification
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/admin/grammars/srecode-template.wy 
b/admin/grammars/srecode-template.wy
index 957c00ab1b9..3dc8b533f33 100644
--- a/admin/grammars/srecode-template.wy
+++ b/admin/grammars/srecode-template.wy
@@ -1,6 +1,6 @@
 ;;; srecode-template.wy --- Semantic Recoder Template parser
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/admin/last-chance.el b/admin/last-chance.el
index a9aaa400b75..c9cc88031f2 100644
--- a/admin/last-chance.el
+++ b/admin/last-chance.el
@@ -1,6 +1,6 @@
 ;;; last-chance.el --- dangling deterrence     -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Thien-Thi Nguyen <ttn@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/admin/make-emacs b/admin/make-emacs
index f31c2383fc0..e6ab6a51f7b 100755
--- a/admin/make-emacs
+++ b/admin/make-emacs
@@ -2,7 +2,7 @@
 # Build Emacs with various options for profiling, debugging,
 # with and without warnings enabled etc.
 
-# Copyright (C) 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/admin/make-manuals b/admin/make-manuals
index f1a46861533..477daa09a4c 100755
--- a/admin/make-manuals
+++ b/admin/make-manuals
@@ -1,7 +1,7 @@
 #!/bin/bash
 ### make-manuals - create the Emacs manuals to upload to the gnu.org website
 
-## Copyright 2018-2023 Free Software Foundation, Inc.
+## Copyright 2018-2024 Free Software Foundation, Inc.
 
 ## Author: Glenn Morris <rgm@gnu.org>
 ## Maintainer: emacs-devel@gnu.org
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index fe88d1106ae..5246fb14e1e 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -4,7 +4,7 @@
 #
 #      admin/merge-gnulib
 
-# Copyright 2012-2023 Free Software Foundation, Inc.
+# Copyright 2012-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
@@ -52,7 +52,7 @@ GNULIB_MODULES='
 '
 
 AVOIDED_MODULES='
-  btowc chmod close crypto/af_alg dup fchdir fstat
+  access btowc chmod close crypto/af_alg dup fchdir fstat
   iswblank iswctype iswdigit iswxdigit langinfo lock
   mbrtowc mbsinit memchr mkdir msvc-inval msvc-nothrow nl_langinfo
   openat-die opendir pthread-h raise
@@ -107,9 +107,6 @@ test -x "$gnulib_srcdir"/gnulib-tool || {
 # gnulib-tool has problems with a bare checkout (Bug#32452#65).
 test -f configure || ./autogen.sh || exit
 
-# Old caches can confuse autoconf when some Gnulib-related changes take effect.
-rm -fr autom4te.cache || exit
-
 avoided_flags=
 for module in $AVOIDED_MODULES; do
   avoided_flags="$avoided_flags --avoid=$module"
diff --git a/admin/merge-pkg-config b/admin/merge-pkg-config
index ba3c48b546b..8bceb0ba2ca 100755
--- a/admin/merge-pkg-config
+++ b/admin/merge-pkg-config
@@ -4,7 +4,7 @@
 #
 #      admin/merge-pkg-config
 
-# Copyright 2014-2023 Free Software Foundation, Inc.
+# Copyright 2014-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/admin/notes/copyright b/admin/notes/copyright
index a06d92a2c5f..55924157e9a 100644
--- a/admin/notes/copyright
+++ b/admin/notes/copyright
@@ -1,4 +1,4 @@
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/admin/notes/emba b/admin/notes/emba
index 88ac3ebe351..2e61ec49ae5 100644
--- a/admin/notes/emba
+++ b/admin/notes/emba
@@ -1,6 +1,6 @@
 -*- mode: outline; coding: utf-8 -*-
 
-Copyright (C) 2019-2023 Free Software Foundation, Inc.
+Copyright (C) 2019-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 NOTES FOR EMACS CONTINUOUS BUILD ON EMBA
diff --git a/admin/notes/hydra b/admin/notes/hydra
index 12d3f356020..8ee32df07a7 100644
--- a/admin/notes/hydra
+++ b/admin/notes/hydra
@@ -1,6 +1,6 @@
 -*- mode: outline; coding: utf-8 -*-
 
-Copyright (C) 2013-2023 Free Software Foundation, Inc.
+Copyright (C) 2013-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 NOTES FOR EMACS CONTINUOUS BUILD ON HYDRA
diff --git a/admin/notes/java b/admin/notes/java
index 125ac0aad67..e10f09f780f 100644
--- a/admin/notes/java
+++ b/admin/notes/java
@@ -1,5 +1,5 @@
 Installation instructions for Android
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
@@ -15,7 +15,7 @@ Java is required because the entire Android runtime is based 
around
 Java, and there is no way to write an Android program which runs
 without Java.
 
-This text exists to prime other Emacs developers, already familar with
+This text exists to prime other Emacs developers, already familiar with
 C, on the basic architecture of the Android port, and to teach them
 how to read and write the Java code found in this directory.
 
@@ -445,7 +445,7 @@ loaded by the special invocation:
 where ``static'' defines a section of code which will be run upon the
 object (containing class) being loaded.  This is like:
 
-  __attribute__((constructor))
+  __attribute__ ((constructor))
 
 on systems where shared object constructors are supported.
 
@@ -570,7 +570,7 @@ Let us go back and review the definition of 
``startEmacsService'':
          context.startService (new Intent (context,
                                            EmacsService.class));
        else
-         /* Display the permanant notification and start Emacs as a
+         /* Display the permanent notification and start Emacs as a
             foreground service.  */
          context.startForegroundService (new Intent (context,
                                                      EmacsService.class));
@@ -796,7 +796,7 @@ Next, `max_handle' is saved, and a new handle is allocated 
for
   if (!window)
     error ("Out of window handles!");
 
-An error is signalled if Emacs runs out of available handles.
+An error is signaled if Emacs runs out of available handles.
 
   if (!class)
     {
diff --git a/admin/notes/multi-tty b/admin/notes/multi-tty
index 16f2bec4d80..f021799b294 100644
--- a/admin/notes/multi-tty
+++ b/admin/notes/multi-tty
@@ -1,6 +1,6 @@
 -*- coding: utf-8; mode: text; -*-
 
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 From README.multi-tty in the multi-tty branch.
diff --git a/admin/notes/tree-sitter/build-module/batch.sh 
b/admin/notes/tree-sitter/build-module/batch.sh
index 9988d1eae4e..012b5882e83 100755
--- a/admin/notes/tree-sitter/build-module/batch.sh
+++ b/admin/notes/tree-sitter/build-module/batch.sh
@@ -18,6 +18,7 @@ languages=(
     'json'
     'lua'
     'python'
+    'ruby'
     'rust'
     'toml'
     'tsx'
diff --git a/admin/notes/unicode b/admin/notes/unicode
index 3748989e2fe..4a25d8159cb 100644
--- a/admin/notes/unicode
+++ b/admin/notes/unicode
@@ -1,6 +1,6 @@
                                             -*-mode: text; coding: utf-8;-*-
 
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Importing a new Unicode Standard version into Emacs
diff --git a/admin/notes/www b/admin/notes/www
index d6e15ffe955..0a2d4aa9859 100644
--- a/admin/notes/www
+++ b/admin/notes/www
@@ -1,6 +1,6 @@
 -*- outline -*-
 
-Copyright (C) 2013-2023 Free Software Foundation, Inc.
+Copyright (C) 2013-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 NOTES FOR EMACS WWW PAGES
diff --git a/admin/notes/years b/admin/notes/years
index 113e6608d3f..0510cb24b81 100644
--- a/admin/notes/years
+++ b/admin/notes/years
@@ -24,6 +24,8 @@ A few known problems with the build-aux/update-copyright 
script:
   . several README and XPM files under etc/images/, and also
     etc/refcards/README, msdos/README, and nt/icons/README aren't
     updated either
+  - the copyright notice for headers generated by exec/configure.ac is
+    not updated as the file already bears a notice above it
 
 These files need to be updated by hand.
 
diff --git a/admin/nt/README-UNDUMP.W32 b/admin/nt/README-UNDUMP.W32
index b151df1eb0f..8b13d10159b 100644
--- a/admin/nt/README-UNDUMP.W32
+++ b/admin/nt/README-UNDUMP.W32
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
                           Emacs for Windows
diff --git a/admin/nt/dist-build/README-windows-binaries 
b/admin/nt/dist-build/README-windows-binaries
index f53558960c4..c51cea73333 100644
--- a/admin/nt/dist-build/README-windows-binaries
+++ b/admin/nt/dist-build/README-windows-binaries
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
                      Precompiled Distributions of
diff --git a/admin/nt/dist-build/build-dep-zips.py 
b/admin/nt/dist-build/build-dep-zips.py
index 71105a071ec..fb0aca87731 100755
--- a/admin/nt/dist-build/build-dep-zips.py
+++ b/admin/nt/dist-build/build-dep-zips.py
@@ -1,6 +1,6 @@
 #!/usr/bin/python3
 
-## Copyright (C) 2017-2023 Free Software Foundation, Inc.
+## Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ## This file is part of GNU Emacs.
 
diff --git a/admin/nt/dist-build/build-zips.sh 
b/admin/nt/dist-build/build-zips.sh
index 28aee4a0b67..3b9db3deef5 100755
--- a/admin/nt/dist-build/build-zips.sh
+++ b/admin/nt/dist-build/build-zips.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-## Copyright (C) 2017-2023 Free Software Foundation, Inc.
+## Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ## This file is part of GNU Emacs.
 
diff --git a/admin/quick-install-emacs b/admin/quick-install-emacs
index 4ca8cee5d7a..985e71d9977 100755
--- a/admin/quick-install-emacs
+++ b/admin/quick-install-emacs
@@ -1,7 +1,7 @@
 #!/bin/sh
 ### quick-install-emacs --- do a halfway-decent job of installing emacs quickly
 
-## Copyright (C) 2001-2023 Free Software Foundation, Inc.
+## Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ## Author: Miles Bader <miles@gnu.org>
 
diff --git a/admin/run-codespell b/admin/run-codespell
new file mode 100755
index 00000000000..991b72073b2
--- /dev/null
+++ b/admin/run-codespell
@@ -0,0 +1,68 @@
+#!/bin/bash
+### run-codespell - run codespell on Emacs
+
+## Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+## Author: Stefan Kangas <stefankangas@gmail.com>
+
+## 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:
+
+## Run codespell on the Emacs source tree.
+##
+## codespell 2.2.2 or later is recommended.  Earlier versions had a
+## bug where the line count was incorrect for files containing "^L"
+## characters.
+
+source "${0%/*}/emacs-shell-lib"
+
+CODESPELL_DIR="${PD}/codespell"
+
+CODESPELL_RC="${CODESPELL_DIR}/codespell.rc"
+CODESPELL_EXCLUDE="${CODESPELL_DIR}/codespell.exclude"
+CODESPELL_IGNORE="${CODESPELL_DIR}/codespell.ignore"
+CODESPELL_DICTIONARY="${CODESPELL_DIR}/codespell.dictionary"
+
+emacs_run_codespell ()
+{
+    git ls-files |\
+        grep -v -E -e '^(lib|m4)/.*' |\
+        grep -v -E -e '^admin/(charsets|codespell|unidata)/.*' |\
+        grep -v -E -e '^doc/misc/texinfo.tex$' |\
+        grep -v -E -e '^etc/(AUTHORS|HELLO|publicsuffix.txt)$' |\
+        grep -v -E -e '^etc/refcards/(cs|de|fr|pl|pt|sk)-.+.tex$' |\
+        grep -v -E -e '^etc/tutorials/TUTORIAL\..+' |\
+        grep -v -E -e '^leim/(MISC|SKK)-DIC/.*' |\
+        grep -v -E -e '^lisp/language/ethio-util.el' |\
+        grep -v -E -e '^lisp/ldefs-boot.el' |\
+        grep -v -E -e '^lisp/leim/.*' |\
+        grep -v -E -e '^test/lisp/net/puny-resources/IdnaTestV2.txt' |\
+        grep -v -E -e '^test/manual/(etags|indent)/.*' |\
+        grep -v -E -e '^test/src/regex-resources/.*' |\
+        xargs codespell \
+              --config "$CODESPELL_RC" \
+              --exclude-file "$CODESPELL_EXCLUDE" \
+              --ignore-words "$CODESPELL_IGNORE" \
+              --disable-colors \
+              --write-changes \
+              $@
+}
+
+emacs_run_codespell
+emacs_run_codespell --dictionary "$CODESPELL_DICTIONARY"
+
+exit 0
diff --git a/admin/unidata/Makefile.in b/admin/unidata/Makefile.in
index c7737583700..a5fd927f548 100644
--- a/admin/unidata/Makefile.in
+++ b/admin/unidata/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 2012-2023 Free Software Foundation, Inc.
+# Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 # Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
 #   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/admin/unidata/blocks.awk b/admin/unidata/blocks.awk
index 80ce7478a45..122164ce5b6 100755
--- a/admin/unidata/blocks.awk
+++ b/admin/unidata/blocks.awk
@@ -1,6 +1,6 @@
 #!/usr/bin/awk -f
 
-## Copyright (C) 2015-2023 Free Software Foundation, Inc.
+## Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ## Author: Glenn Morris <rgm@gnu.org>
 ## Maintainer: emacs-devel@gnu.org
@@ -60,6 +60,7 @@ BEGIN {
     alias["cjk strokes"] = "cjk-misc"
     alias["cjk symbols and punctuation"] = "cjk-misc"
     alias["halfwidth and fullwidth forms"] = "cjk-misc"
+    alias["yijing hexagram symbols"] = "cjk-misc"
     alias["common indic number forms"] = "north-indic-number"
 
     tohex["a"] = 10
@@ -94,7 +95,7 @@ function name2alias(name   , w, w2) {
     if (alias[name]) return alias[name]
     else if (name ~ /for symbols/) return "symbol"
     else if (name ~ /latin|combining .* marks|spacing modifier|tone 
letters|alphabetic presentation/) return "latin"
-    else if (name ~ /cjk|yijing|enclosed ideograph|kangxi/) return "han"
+    else if (name ~ /cjk|enclosed ideograph|kangxi/) return "han"
     else if (name ~ /arabic/) return "arabic"
     else if (name ~ /^greek/) return "greek"
     else if (name ~ /^coptic/) return "coptic"
diff --git a/admin/unidata/emoji-zwj.awk b/admin/unidata/emoji-zwj.awk
index fc4a2edd559..c69bc6822d0 100644
--- a/admin/unidata/emoji-zwj.awk
+++ b/admin/unidata/emoji-zwj.awk
@@ -1,6 +1,6 @@
 #!/usr/bin/awk -f
 
-## Copyright (C) 2020, 2022-2023 Free Software Foundation, Inc.
+## Copyright (C) 2020, 2022-2024 Free Software Foundation, Inc.
 
 ## Author: Robert Pluim <rpluim@gmail.com>
 
diff --git a/admin/unidata/unidata-gen.el b/admin/unidata/unidata-gen.el
index 1ad347c9425..7be03fe63af 100644
--- a/admin/unidata/unidata-gen.el
+++ b/admin/unidata/unidata-gen.el
@@ -1,6 +1,6 @@
 ;;; unidata-gen.el --- Create files containing character property data  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/admin/unidata/uvs.el b/admin/unidata/uvs.el
index 70f6d323f12..736d5d67bd1 100644
--- a/admin/unidata/uvs.el
+++ b/admin/unidata/uvs.el
@@ -1,6 +1,6 @@
 ;;; uvs.el --- utility for UVS (format 14) cmap subtables in OpenType fonts  
-*- lexical-binding:t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
 
diff --git a/admin/update-copyright b/admin/update-copyright
index df6f6c7d487..b9007100b35 100755
--- a/admin/update-copyright
+++ b/admin/update-copyright
@@ -7,7 +7,7 @@
 # By default, this script uses the local-time calendar year.
 # Set the UPDATE_COPYRIGHT_YEAR environment variable to override the default.
 
-# Copyright 2013-2023 Free Software Foundation, Inc.
+# Copyright 2013-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/admin/update_autogen b/admin/update_autogen
index 5088bc674ca..224d6c66eed 100755
--- a/admin/update_autogen
+++ b/admin/update_autogen
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 ### update_autogen - update some auto-generated files in the Emacs tree
 
-## Copyright (C) 2011-2023 Free Software Foundation, Inc.
+## Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ## Author: Glenn Morris <rgm@gnu.org>
 ## Maintainer: Stefan Kangas <stefankangas@gmail.com>
diff --git a/admin/upload-manuals b/admin/upload-manuals
index a206177a5c1..2e6d03e6bc6 100755
--- a/admin/upload-manuals
+++ b/admin/upload-manuals
@@ -2,7 +2,7 @@
 
 ### upload-manuals - upload the Emacs manuals to the gnu.org website
 
-## Copyright 2018-2023 Free Software Foundation, Inc.
+## Copyright 2018-2024 Free Software Foundation, Inc.
 
 ## Author: Glenn Morris <rgm@gnu.org>
 ## Maintainer: emacs-devel@gnu.org
diff --git a/autogen.sh b/autogen.sh
index 0d89b7cfc9a..f56966ae0d1 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 ### autogen.sh - tool to help build Emacs from a repository checkout
 
-## Copyright (C) 2011-2023 Free Software Foundation, Inc.
+## Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ## Author: Glenn Morris <rgm@gnu.org>
 ## Maintainer: emacs-devel@gnu.org
@@ -239,6 +239,16 @@ Please report any problems with this script to 
bug-gnu-emacs@gnu.org .'
 
   fi                            # do_check
 
+  # Stale caches can confuse autoconf.
+  rm -fr autom4te.cache exec/autom4te.cache || exit
+
+  # In build-aux save config.guess, config.sub and install-sh
+  # in case autoreconf overwrites them, as we rely on the copies
+  # in Git, which are updated by admin/merge-gnulib.
+  for file in config.guess config.sub install-sh; do
+    cp -p build-aux/$file build-aux/$file.tmp || exit
+  done
+
   # Build aclocal.m4 here so that autoreconf need not use aclocal.
   # aclocal is part of Automake and might not be installed, and
   # autoreconf skips aclocal if aclocal.m4 is already supplied.
@@ -269,6 +279,12 @@ Please report any problems with this script to 
bug-gnu-emacs@gnu.org .'
   # Now, run autoreconf inside the exec directory to generate its
   # configure script.
   autoreconf -fi exec || exit
+
+  # Restore config.guess etc. in build-aux, and copy them to exec.
+  for file in config.guess config.sub install-sh; do
+    cp build-aux/$file.tmp exec/$file &&
+    mv build-aux/$file.tmp build-aux/$file || exit
+  done
 fi
 
 
diff --git a/build-aux/config.guess b/build-aux/config.guess
index b187213930f..f6d217a49f8 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-2023 Free Software Foundation, Inc.
+#   Copyright 1992-2024 Free Software Foundation, Inc.
 
 # shellcheck disable=SC2006,SC2268 # see below for rationale
 
-timestamp='2023-07-20'
+timestamp='2024-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-2023 Free Software Foundation, Inc.
+Copyright 1992-2024 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."
@@ -155,6 +155,9 @@ Linux|GNU|GNU/*)
 
        set_cc_for_build
        cat <<-EOF > "$dummy.c"
+       #if defined(__ANDROID__)
+       LIBC=android
+       #else
        #include <features.h>
        #if defined(__UCLIBC__)
        LIBC=uclibc
@@ -162,6 +165,8 @@ Linux|GNU|GNU/*)
        LIBC=dietlibc
        #elif defined(__GLIBC__)
        LIBC=gnu
+       #elif defined(__LLVM_LIBC__)
+       LIBC=llvm
        #else
        #include <stdarg.h>
        /* First heuristic to detect musl libc.  */
@@ -169,6 +174,7 @@ Linux|GNU|GNU/*)
        LIBC=musl
        #endif
        #endif
+       #endif
        EOF
        cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | 
sed 's, ,,g'`
        eval "$cc_set_libc"
@@ -904,7 +910,7 @@ EOF
        fi
        ;;
     *:FreeBSD:*:*)
-       UNAME_PROCESSOR=`/usr/bin/uname -p`
+       UNAME_PROCESSOR=`uname -p`
        case $UNAME_PROCESSOR in
            amd64)
                UNAME_PROCESSOR=x86_64 ;;
@@ -1589,6 +1595,9 @@ EOF
     *:Unleashed:*:*)
        GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
        ;;
+    *:Ironclad:*:*)
+       GUESS=$UNAME_MACHINE-unknown-ironclad
+       ;;
 esac
 
 # Do we have a guess based on uname results?
diff --git a/build-aux/config.sub b/build-aux/config.sub
index 6ae25027537..2c6a07ab3c3 100755
--- a/build-aux/config.sub
+++ b/build-aux/config.sub
@@ -1,10 +1,10 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright 1992-2023 Free Software Foundation, Inc.
+#   Copyright 1992-2024 Free Software Foundation, Inc.
 
 # shellcheck disable=SC2006,SC2268 # see below for rationale
 
-timestamp='2023-07-31'
+timestamp='2024-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
@@ -76,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright 1992-2023 Free Software Foundation, Inc.
+Copyright 1992-2024 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."
@@ -1181,7 +1181,7 @@ case $cpu-$vendor in
                case $cpu in
                        1750a | 580 \
                        | a29k \
-                       | aarch64 | aarch64_be \
+                       | aarch64 | aarch64_be | aarch64c | arm64ec \
                        | abacus \
                        | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
                        | alpha64 | alpha64ev[4-8] | alpha64ev56 | 
alpha64ev6[78] \
@@ -1200,6 +1200,7 @@ case $cpu-$vendor in
                        | d10v | d30v | dlx | dsp16xx \
                        | e2k | elxsi | epiphany \
                        | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+                       | javascript \
                        | h8300 | h8500 \
                        | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
                        | hexagon \
@@ -1221,6 +1222,7 @@ case $cpu-$vendor in
                        | moxie \
                        | mt \
                        | msp430 \
+                       | nanomips* \
                        | nds32 | nds32le | nds32be \
                        | nfp \
                        | nios | nios2 | nios2eb | nios2el \
@@ -1252,6 +1254,7 @@ case $cpu-$vendor in
                        | ubicom32 \
                        | v70 | v850 | v850e | v850e1 | v850es | v850e2 | 
v850e2v3 \
                        | vax \
+                       | vc4 \
                        | visium \
                        | w65 \
                        | wasm32 | wasm64 \
@@ -1284,11 +1287,12 @@ esac
 
 # Decode manufacturer-specific aliases for certain operating systems.
 
-if test x$basic_os != x
+if test x"$basic_os" != x
 then
 
 # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
 # set os.
+obj=
 case $basic_os in
        gnu/linux*)
                kernel=linux
@@ -1488,10 +1492,16 @@ case $os in
                        os=eabi
                        ;;
                    *)
-                       os=elf
+                       os=
+                       obj=elf
                        ;;
                esac
                ;;
+       aout* | coff* | elf* | pe*)
+               # These are machine code file formats, not OSes
+               obj=$os
+               os=
+               ;;
        *)
                # No normalization, but not necessarily accepted, that comes 
below.
                ;;
@@ -1510,12 +1520,15 @@ else
 # system, and we'll never get to this point.
 
 kernel=
+obj=
 case $cpu-$vendor in
        score-*)
-               os=elf
+               os=
+               obj=elf
                ;;
        spu-*)
-               os=elf
+               os=
+               obj=elf
                ;;
        *-acorn)
                os=riscix1.2
@@ -1525,28 +1538,35 @@ case $cpu-$vendor in
                os=gnu
                ;;
        arm*-semi)
-               os=aout
+               os=
+               obj=aout
                ;;
        c4x-* | tic4x-*)
-               os=coff
+               os=
+               obj=coff
                ;;
        c8051-*)
-               os=elf
+               os=
+               obj=elf
                ;;
        clipper-intergraph)
                os=clix
                ;;
        hexagon-*)
-               os=elf
+               os=
+               obj=elf
                ;;
        tic54x-*)
-               os=coff
+               os=
+               obj=coff
                ;;
        tic55x-*)
-               os=coff
+               os=
+               obj=coff
                ;;
        tic6x-*)
-               os=coff
+               os=
+               obj=coff
                ;;
        # This must come before the *-dec entry.
        pdp10-*)
@@ -1568,19 +1588,24 @@ case $cpu-$vendor in
                os=sunos3
                ;;
        m68*-cisco)
-               os=aout
+               os=
+               obj=aout
                ;;
        mep-*)
-               os=elf
+               os=
+               obj=elf
                ;;
        mips*-cisco)
-               os=elf
+               os=
+               obj=elf
                ;;
-       mips*-*)
-               os=elf
+       mips*-*|nanomips*-*)
+               os=
+               obj=elf
                ;;
        or32-*)
-               os=coff
+               os=
+               obj=coff
                ;;
        *-tti)  # must be before sparc entry or we get the wrong os.
                os=sysv3
@@ -1589,7 +1614,8 @@ case $cpu-$vendor in
                os=sunos4.1.1
                ;;
        pru-*)
-               os=elf
+               os=
+               obj=elf
                ;;
        *-be)
                os=beos
@@ -1670,10 +1696,12 @@ case $cpu-$vendor in
                os=uxpv
                ;;
        *-rom68k)
-               os=coff
+               os=
+               obj=coff
                ;;
        *-*bug)
-               os=coff
+               os=
+               obj=coff
                ;;
        *-apple)
                os=macos
@@ -1691,10 +1719,11 @@ esac
 
 fi
 
-# Now, validate our (potentially fixed-up) OS.
+# Now, validate our (potentially fixed-up) individual pieces (OS, OBJ).
+
 case $os in
        # Sometimes we do "kernel-libc", so those need to count as OSes.
-       musl* | newlib* | relibc* | uclibc*)
+       llvm* | musl* | newlib* | relibc* | uclibc*)
                ;;
        # Likewise for "kernel-abi"
        eabi* | gnueabi*)
@@ -1702,6 +1731,9 @@ case $os in
        # VxWorks passes extra cpu info in the 4th filed.
        simlinux | simwindows | spe)
                ;;
+       # See `case $cpu-$os` validation below
+       ghcjs)
+               ;;
        # Now accept the basic system types.
        # The portable systems comes first.
        # Each alternative MUST end in a * to match a version number.
@@ -1719,11 +1751,11 @@ case $os in
             | mirbsd* | netbsd* | dicos* | openedition* | ose* \
             | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
             | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
-            | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
-            | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+            | bosx* | nextstep* | cxux* | oabi* \
+            | ptx* | ecoff* | winnt* | domain* | vsta* \
             | udi* | lites* | ieee* | go32* | aux* | hcos* \
             | chorusrdb* | cegcc* | glidix* | serenity* \
-            | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+            | cygwin* | msys* | moss* | proelf* | rtems* \
             | midipix* | mingw32* | mingw64* | mint* \
             | uxpv* | beos* | mpeix* | udk* | moxiebox* \
             | interix* | uwin* | mks* | rhapsody* | darwin* \
@@ -1736,71 +1768,115 @@ case $os in
             | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
             | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
             | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
-            | fiwix* | mlibc* | cos* | mbr* )
+            | fiwix* | mlibc* | cos* | mbr* | ironclad* )
                ;;
        # This one is extra strict with allowed versions
        sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
                # Don't forget version if it is 3.2v4 or newer.
                ;;
+       # This refers to builds using the UEFI calling convention
+       # (which depends on the architecture) and PE file format.
+       # Note that this is both a different calling convention and
+       # different file format than that of GNU-EFI
+       # (x86_64-w64-mingw32).
+       uefi)
+               ;;
        none)
                ;;
        kernel* | msvc* )
                # Restricted further below
                ;;
+       '')
+               if test x"$obj" = x
+               then
+                       echo "Invalid configuration '$1': Blank OS only allowed 
with explicit machine code file format" 1>&2
+               fi
+               ;;
        *)
                echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2
                exit 1
                ;;
 esac
 
+case $obj in
+       aout* | coff* | elf* | pe*)
+               ;;
+       '')
+               # empty is fine
+               ;;
+       *)
+               echo "Invalid configuration '$1': Machine code format '$obj' 
not recognized" 1>&2
+               exit 1
+               ;;
+esac
+
+# Here we handle the constraint that a (synthetic) cpu and os are
+# valid only in combination with each other and nowhere else.
+case $cpu-$os in
+       # The "javascript-unknown-ghcjs" triple is used by GHC; we
+       # accept it here in order to tolerate that, but reject any
+       # variations.
+       javascript-ghcjs)
+               ;;
+       javascript-* | *-ghcjs)
+               echo "Invalid configuration '$1': cpu '$cpu' is not valid with 
os '$os$obj'" 1>&2
+               exit 1
+               ;;
+esac
+
 # As a final step for OS-related things, validate the OS-kernel combination
 # (given a valid OS), if there is a kernel.
-case $kernel-$os in
-       linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
-                  | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* 
)
+case $kernel-$os-$obj in
+       linux-gnu*- | linux-android*- | linux-dietlibc*- | linux-llvm*- \
+                   | linux-mlibc*- | linux-musl*- | linux-newlib*- \
+                   | linux-relibc*- | linux-uclibc*- )
                ;;
-       uclinux-uclibc* )
+       uclinux-uclibc*- )
                ;;
-       managarm-mlibc* | managarm-kernel* )
+       managarm-mlibc*- | managarm-kernel*- )
                ;;
-       windows*-gnu* | windows*-msvc*)
+       windows*-msvc*-)
                ;;
-       -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* )
+       -dietlibc*- | -llvm*- | -mlibc*- | -musl*- | -newlib*- | -relibc*- \
+                   | -uclibc*- )
                # These are just libc implementations, not actual OSes, and thus
                # require a kernel.
                echo "Invalid configuration '$1': libc '$os' needs explicit 
kernel." 1>&2
                exit 1
                ;;
-       -kernel* )
+       -kernel*- )
                echo "Invalid configuration '$1': '$os' needs explicit kernel." 
1>&2
                exit 1
                ;;
-       *-kernel* )
+       *-kernel*- )
                echo "Invalid configuration '$1': '$kernel' does not support 
'$os'." 1>&2
                exit 1
                ;;
-       *-msvc* )
+       *-msvc*- )
                echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2
                exit 1
                ;;
-       kfreebsd*-gnu* | kopensolaris*-gnu*)
+       kfreebsd*-gnu*- | kopensolaris*-gnu*-)
                ;;
-       vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+       vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-)
                ;;
-       nto-qnx*)
+       nto-qnx*-)
                ;;
-       os2-emx)
+       os2-emx-)
                ;;
-       *-eabi* | *-gnueabi*)
+       *-eabi*- | *-gnueabi*-)
                ;;
-       none-coff* | none-elf*)
+       none--*)
                # None (no kernel, i.e. freestanding / bare metal),
-               # can be paired with an output format "OS"
+               # can be paired with an machine code file format
                ;;
-       -*)
+       -*-)
                # Blank kernel with real OS is always fine.
                ;;
-       *-*)
+       --*)
+               # Blank kernel and OS with real machine code file format is 
always fine.
+               ;;
+       *-*-*)
                echo "Invalid configuration '$1': Kernel '$kernel' not known to 
work with OS '$os'." 1>&2
                exit 1
                ;;
@@ -1884,7 +1960,7 @@ case $vendor in
                ;;
 esac
 
-echo "$cpu-$vendor-${kernel:+$kernel-}$os"
+echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}"
 exit
 
 # Local variables:
diff --git a/build-aux/git-hooks/commit-msg b/build-aux/git-hooks/commit-msg
index d0578bcfb46..1eb2560bba2 100755
--- a/build-aux/git-hooks/commit-msg
+++ b/build-aux/git-hooks/commit-msg
@@ -1,7 +1,7 @@
 #!/bin/sh
 # Check the format of GNU Emacs change log entries.
 
-# Copyright 2014-2023 Free Software Foundation, Inc.
+# Copyright 2014-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/build-aux/git-hooks/commit-msg-files.awk 
b/build-aux/git-hooks/commit-msg-files.awk
index 5c9b70a5de5..2fbbd059500 100644
--- a/build-aux/git-hooks/commit-msg-files.awk
+++ b/build-aux/git-hooks/commit-msg-files.awk
@@ -1,6 +1,6 @@
 # Check the file list of GNU Emacs change log entries for each commit SHA.
 
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/build-aux/git-hooks/post-commit b/build-aux/git-hooks/post-commit
index e02fee48db4..e6b5effc93a 100755
--- a/build-aux/git-hooks/post-commit
+++ b/build-aux/git-hooks/post-commit
@@ -1,7 +1,7 @@
 #!/bin/sh
 # Check the file list of GNU Emacs change log entries after committing.
 
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/build-aux/git-hooks/pre-commit b/build-aux/git-hooks/pre-commit
index 2e0dd7dfd7c..a86bbf642a5 100755
--- a/build-aux/git-hooks/pre-commit
+++ b/build-aux/git-hooks/pre-commit
@@ -1,7 +1,7 @@
 #!/bin/sh
 # Check file names in git commits for GNU Emacs.
 
-# Copyright 2014-2023 Free Software Foundation, Inc.
+# Copyright 2014-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/build-aux/git-hooks/pre-push b/build-aux/git-hooks/pre-push
index a342814c1e3..86c81e02d9a 100755
--- a/build-aux/git-hooks/pre-push
+++ b/build-aux/git-hooks/pre-push
@@ -1,7 +1,7 @@
 #!/bin/sh
 # Check the file list of GNU Emacs change log entries before pushing.
 
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/build-aux/git-hooks/prepare-commit-msg 
b/build-aux/git-hooks/prepare-commit-msg
index 1520ef3f5f8..0367858ea7e 100755
--- a/build-aux/git-hooks/prepare-commit-msg
+++ b/build-aux/git-hooks/prepare-commit-msg
@@ -1,7 +1,7 @@
 #!/bin/sh
 # Check the format of GNU Emacs change log entries.
 
-# Copyright 2019-2023 Free Software Foundation, Inc.
+# Copyright 2019-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/build-aux/gitlog-to-changelog b/build-aux/gitlog-to-changelog
index ceb1f0cf320..16a9405a7cb 100755
--- a/build-aux/gitlog-to-changelog
+++ b/build-aux/gitlog-to-changelog
@@ -3,7 +3,7 @@
 
 # Convert git log output to ChangeLog format.
 
-# Copyright (C) 2008-2023 Free Software Foundation, Inc.
+# Copyright (C) 2008-2024 Free Software Foundation, Inc.
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
diff --git a/build-aux/gitlog-to-emacslog b/build-aux/gitlog-to-emacslog
index 73bf973dbb1..e9e9420fe40 100755
--- a/build-aux/gitlog-to-emacslog
+++ b/build-aux/gitlog-to-emacslog
@@ -2,7 +2,7 @@
 
 # Convert git log output to ChangeLog format for GNU Emacs.
 
-# Copyright (C) 2014-2023 Free Software Foundation, Inc.
+# Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 # Author: Paul Eggert
 
diff --git a/build-aux/install-sh b/build-aux/install-sh
index ec298b53740..7c56c9c0151 100755
--- a/build-aux/install-sh
+++ b/build-aux/install-sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 # install - install a program, script, or datafile
 
-scriptversion=2020-11-14.01; # UTC
+scriptversion=2023-11-23.18; # UTC
 
 # This originates from X11R5 (mit/util/scripts/install.sh), which was
 # later released in X11R6 (xc/config/util/install.sh) with the
@@ -124,9 +124,9 @@ it's up to you to specify -f if you want it.
 
 If -S is not specified, no backups are attempted.
 
-Email bug reports to bug-automake@gnu.org.
-Automake home page: https://www.gnu.org/software/automake/
-"
+Report bugs to <bug-automake@gnu.org>.
+GNU Automake home page: <https://www.gnu.org/software/automake/>.
+General help using GNU software: <https://www.gnu.org/gethelp/>."
 
 while test $# -ne 0; do
   case $1 in
diff --git a/build-aux/make-info-dir b/build-aux/make-info-dir
index 64cf2d43f16..703abc7bd0a 100755
--- a/build-aux/make-info-dir
+++ b/build-aux/make-info-dir
@@ -2,7 +2,7 @@
 
 ### make-info-dir - create info/dir, for systems without install-info
 
-## Copyright (C) 2013-2023 Free Software Foundation, Inc.
+## Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ## Author: Glenn Morris <rgm@gnu.org>
 ## Maintainer: emacs-devel@gnu.org
diff --git a/build-aux/makecounter.sh b/build-aux/makecounter.sh
index 3bebd288031..a63fcbb7c61 100755
--- a/build-aux/makecounter.sh
+++ b/build-aux/makecounter.sh
@@ -2,7 +2,7 @@
 # Generate or update a C file containing an increasing counter
 # variable.
 #
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 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
diff --git a/build-aux/move-if-change b/build-aux/move-if-change
index 93839108fd9..18a720735cd 100755
--- a/build-aux/move-if-change
+++ b/build-aux/move-if-change
@@ -8,7 +8,7 @@ VERSION='2018-03-07 03:47'; # UTC
 # If you change this file with Emacs, please let the write hook
 # do its job.  Otherwise, update this string manually.
 
-# Copyright (C) 2002-2023 Free Software Foundation, Inc.
+# Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
diff --git a/build-aux/msys-to-w32 b/build-aux/msys-to-w32
index 53bc60da55e..5d8eac4cf20 100755
--- a/build-aux/msys-to-w32
+++ b/build-aux/msys-to-w32
@@ -2,7 +2,7 @@
 # Convert a MSYS path list to Windows-native format.
 # Status is zero if successful, nonzero otherwise.
 
-# Copyright (C) 2013-2023 Free Software Foundation, Inc.
+# Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
diff --git a/build-aux/ndk-build-helper-1.mk b/build-aux/ndk-build-helper-1.mk
index 2cde5146301..5681728154c 100644
--- a/build-aux/ndk-build-helper-1.mk
+++ b/build-aux/ndk-build-helper-1.mk
@@ -1,5 +1,5 @@
 # ndk-build-helper-1.mk -- Helper for ndk-build.m4.
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
 # This file is part of GNU Emacs.
 
 # GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/build-aux/ndk-build-helper-2.mk b/build-aux/ndk-build-helper-2.mk
index 186f3aec333..1c2409cfd57 100644
--- a/build-aux/ndk-build-helper-2.mk
+++ b/build-aux/ndk-build-helper-2.mk
@@ -1,5 +1,5 @@
 # ndk-build-helper-2.mk -- Helper for ndk-build.m4.
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
 # This file is part of GNU Emacs.
 
 # GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/build-aux/ndk-build-helper-3.mk b/build-aux/ndk-build-helper-3.mk
index 4d0358d4f77..e360a347bb4 100644
--- a/build-aux/ndk-build-helper-3.mk
+++ b/build-aux/ndk-build-helper-3.mk
@@ -1,5 +1,5 @@
 # ndk-build-helper-3.mk -- Helper for ndk-build.m4.
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
 # This file is part of GNU Emacs.
 
 # GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/build-aux/ndk-build-helper-4.mk b/build-aux/ndk-build-helper-4.mk
index a41679c53af..54f781bdbaa 100644
--- a/build-aux/ndk-build-helper-4.mk
+++ b/build-aux/ndk-build-helper-4.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
 # This file is part of GNU Emacs.
 
 # GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/build-aux/ndk-build-helper.mk b/build-aux/ndk-build-helper.mk
index 05f0af76411..521e1b24ce3 100644
--- a/build-aux/ndk-build-helper.mk
+++ b/build-aux/ndk-build-helper.mk
@@ -1,5 +1,5 @@
 # ndk-build-helper.mk -- Helper for ndk-build.m4.
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
 # This file is part of GNU Emacs.
 
 # GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/build-aux/update-copyright b/build-aux/update-copyright
index cdc3f3b5988..ea3e46fe60f 100755
--- a/build-aux/update-copyright
+++ b/build-aux/update-copyright
@@ -3,7 +3,7 @@
 
 # Update an FSF copyright year list to include the current year.
 
-# Copyright (C) 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2009-2024 Free Software Foundation, Inc.
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -138,7 +138,7 @@
 eval 'exec perl -wSx -0777 -pi "$0" "$@"'
      if 0;
 
-my $VERSION = '2023-06-18.01:14'; # UTC
+my $VERSION = '2024-01-15.18:30'; # UTC
 # The definition above must lie within the first 8 lines in order
 # for the Emacs time-stamp write hook (at end) to update it.
 # If you change this file with Emacs, please let the write hook
@@ -146,6 +146,7 @@ my $VERSION = '2023-06-18.01:14'; # UTC
 
 use strict;
 use warnings;
+use re 'eval';
 
 my $copyright_re = 'Copyright';
 my $circle_c_re = '(?:\([cC]\)|@copyright\{}|\\\\\(co|&copy;|©)';
@@ -169,14 +170,13 @@ if (!$this_year || $this_year !~ m/^\d{4}$/)
 # Unless the file consistently uses "\r\n" as the EOL, use "\n" instead.
 my $eol = /(?:^|[^\r])\n/ ? "\n" : "\r\n";
 
-my $leading;
-my $prefix;
-my $ws_re;
 my $stmt_re;
-while (/(^|\n)(.{0,$prefix_max})$copyright_re/g)
+my $found;
+while (/(^|\n)(.{0,$prefix_max})$copyright_re/cg)
   {
-    $leading = "$1$2";
-    $prefix = $2;
+    my $pos=pos();
+    my $leading = "$1$2";
+    my $prefix = $2;
     if ($prefix =~ /^(\s*\/)\*(\s*)$/)
       {
         $prefix =~ s,/, ,;
@@ -187,7 +187,7 @@ while (/(^|\n)(.{0,$prefix_max})$copyright_re/g)
             $prefix = $prefix_ws;
           }
       }
-    $ws_re = '[ \t\r\f]'; # \s without \n
+    my $ws_re = '[ \t\r\f]'; # \s without \n
     $ws_re =
       "(?:$ws_re*(?:$ws_re|\\n" . quotemeta($prefix) . ")$ws_re*)";
     my $holder_re = $holder;
@@ -198,96 +198,97 @@ while (/(^|\n)(.{0,$prefix_max})$copyright_re/g)
       . "((?:\\d\\d)?\\d\\d)$ws_re$holder_re";
     if (/\G$stmt_remainder_re/)
       {
+        $found = 1;
         $stmt_re =
           quotemeta($leading) . "($copyright_re$stmt_remainder_re)";
-        last;
-      }
-  }
-if (defined $stmt_re)
-  {
-    /$stmt_re/ or die; # Should never die.
-    my $stmt = $1;
-    my $final_year_orig = $2;
 
-    # Handle two-digit year numbers like "98" and "99".
-    my $final_year = $final_year_orig;
-    $final_year <= 99
-      and $final_year += 1900;
+        /$stmt_re/ or die; # Should never die.
+        my $stmt = $1;
+        my $final_year_orig = $2;
 
-    if ($final_year != $this_year)
-      {
-        # Update the year.
-        $stmt =~ s/(^|[^\d])$final_year_orig\b/$1$final_year, $this_year/;
-      }
-    if ($final_year != $this_year || $ENV{'UPDATE_COPYRIGHT_FORCE'})
-      {
-        # Normalize all whitespace including newline-prefix sequences.
-        $stmt =~ s/$ws_re/ /g;
+        # Handle two-digit year numbers like "98" and "99".
+        my $final_year = $final_year_orig;
+        $final_year <= 99
+          and $final_year += 1900;
 
-        # Put spaces after commas.
-        $stmt =~ s/, ?/, /g;
-
-        # Convert 2-digit to 4-digit years.
-        $stmt =~ s/(\b\d\d\b)/19$1/g;
-
-        # Make the use of intervals consistent.
-        if (!$ENV{UPDATE_COPYRIGHT_USE_INTERVALS})
+        if ($final_year != $this_year)
           {
-            $stmt =~ s/(\d{4})$ndash_re(\d{4})/join(', ', $1..$2)/eg;
+            # Update the year.
+            $stmt =~ s/(^|[^\d])$final_year_orig\b/$1$final_year, $this_year/;
           }
-        else
+        if ($final_year != $this_year || $ENV{'UPDATE_COPYRIGHT_FORCE'})
           {
-            my $ndash = ($ARGV =~ /\.tex(i(nfo)?)?$/ ? "--"
-                         : $ARGV =~ /\.(\d[a-z]*|man)$/ ? "\\(en"
-                         : "-");
+            # Normalize all whitespace including newline-prefix sequences.
+            $stmt =~ s/$ws_re/ /g;
 
-            $stmt =~
-              s/
-                (\d{4})
-                (?:
-                  (,\ |$ndash_re)
-                  ((??{
-                    if   ($2 ne ', ') { '\d{4}'; }
-                    elsif (!$3)       { $1 + 1;  }
-                    else              { $3 + 1;  }
-                  }))
-                )+
-              /$1$ndash$3/gx;
+            # Put spaces after commas.
+            $stmt =~ s/, ?/, /g;
 
-            # When it's 2, emit a single range encompassing all year numbers.
-            $ENV{UPDATE_COPYRIGHT_USE_INTERVALS} == 2
-              and $stmt =~ 
s/(^|[^\d])(\d{4})\b.*(?:[^\d])(\d{4})\b/$1$2$ndash$3/;
-          }
+            # Convert 2-digit to 4-digit years.
+            $stmt =~ s/(\b\d\d\b)/19$1/g;
 
-        # Format within margin.
-        my $stmt_wrapped;
-        my $text_margin = $margin - length($prefix);
-        if ($prefix =~ /^(\t+)/)
-          {
-            $text_margin -= length($1) * ($tab_width - 1);
-          }
-        while (length $stmt)
-          {
-            if (($stmt =~ s/^(.{1,$text_margin})(?: |$)//)
-                || ($stmt =~ s/^([\S]+)(?: |$)//))
+            # Make the use of intervals consistent.
+            if (!$ENV{UPDATE_COPYRIGHT_USE_INTERVALS})
               {
-                my $line = $1;
-                $stmt_wrapped .= $stmt_wrapped ? "$eol$prefix" : $leading;
-                $stmt_wrapped .= $line;
+                $stmt =~ s/(\d{4})$ndash_re(\d{4})/join(', ', $1..$2)/eg;
               }
             else
               {
-                # Should be unreachable, but we don't want an infinite
-                # loop if it can be reached.
-                die;
+                my $ndash = ($ARGV =~ /\.tex(i(nfo)?)?$/ ? "--"
+                             : $ARGV =~ /\.(\d[a-z]*|man)$/ ? "\\(en"
+                             : "-");
+
+                $stmt =~
+                  s/
+                    (\d{4})
+                    (?:
+                      (,\ |$ndash_re)
+                      ((??{
+                        if   ($2 ne ', ') { '\d{4}'; }
+                        elsif (!$3)       { $1 + 1;  }
+                        else              { $3 + 1;  }
+                      }))
+                    )+
+                  /$1$ndash$3/gx;
+
+                # When it's 2, emit a single range encompassing all year 
numbers.
+                $ENV{UPDATE_COPYRIGHT_USE_INTERVALS} == 2
+                  and $stmt =~ 
s/(^|[^\d])(\d{4})\b.*(?:[^\d])(\d{4})\b/$1$2$ndash$3/;
               }
-          }
 
-        # Replace the old copyright statement.
-        s/$stmt_re/$stmt_wrapped/g;
+            # Format within margin.
+            my $stmt_wrapped;
+            my $text_margin = $margin - length($prefix);
+            if ($prefix =~ /^(\t+)/)
+              {
+                $text_margin -= length($1) * ($tab_width - 1);
+              }
+            while (length $stmt)
+              {
+                if (($stmt =~ s/^(.{1,$text_margin})(?: |$)//)
+                    || ($stmt =~ s/^([\S]+)(?: |$)//))
+                  {
+                    my $line = $1;
+                    $stmt_wrapped .= $stmt_wrapped ? "$eol$prefix" : $leading;
+                    $stmt_wrapped .= $line;
+                  }
+                else
+                  {
+                    # Should be unreachable, but we don't want an infinite
+                    # loop if it can be reached.
+                    die;
+                  }
+              }
+
+            # Replace the old copyright statement.
+            my $p = pos();
+            s/$stmt_re/$stmt_wrapped/g;
+            pos() = $p;
+          }
       }
   }
-else
+
+if (!$found)
   {
     print STDERR "$ARGV: warning: copyright statement not found\n";
   }
diff --git a/build-aux/update-subdirs b/build-aux/update-subdirs
index 275b2d37cac..6279e8c12ff 100755
--- a/build-aux/update-subdirs
+++ b/build-aux/update-subdirs
@@ -1,7 +1,7 @@
 #!/bin/sh
 # Write into $1/subdirs.el a list of subdirs of directory $1.
 
-# Copyright (C) 1994-1995, 1997, 1999, 2001-2023 Free Software
+# Copyright (C) 1994-1995, 1997, 1999, 2001-2024 Free Software
 # Foundation, Inc.
 
 # This file is part of GNU Emacs.
diff --git a/config.bat b/config.bat
index edea9610803..f63da88303c 100644
--- a/config.bat
+++ b/config.bat
@@ -1,7 +1,7 @@
 @echo off
 rem   ----------------------------------------------------------------------
 rem   Configuration script for MSDOS
-rem   Copyright (C) 1994-1999, 2001-2023 Free Software Foundation, Inc.
+rem   Copyright (C) 1994-1999, 2001-2024 Free Software Foundation, Inc.
 
 rem   This file is part of GNU Emacs.
 
diff --git a/configure.ac b/configure.ac
index 759dcd14d50..fa8b04ec685 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ dnl     autoconf
 dnl in the directory containing this script.
 dnl If you changed any AC_DEFINES, also run autoheader.
 dnl
-dnl Copyright (C) 1994-1996, 1999-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 1994-1996, 1999-2024 Free Software Foundation, Inc.
 dnl
 dnl  This file is part of GNU Emacs.
 dnl
@@ -306,7 +306,7 @@ AC_DEFUN([OPTION_DEFAULT_OFF], [dnl
 
 dnl OPTION_DEFAULT_IFAVAILABLE(NAME, HELP-STRING)
 dnl Create a new --with option that defaults to 'ifavailable',
-dnl unless it is overriden by $with_features being equal to 'no'.
+dnl unless it is overridden by $with_features being equal to 'no'.
 dnl NAME is the base name of the option.  The shell variable with_NAME
 dnl   will be set to either the user's value (if the option is
 dnl   specified; 'yes' for a plain --with-NAME) or to 'ifavailable' (if the
@@ -5149,6 +5149,11 @@ source on this site:
 
   with_native_compilation=no])
 
+if test "$with_features" = "no" \
+   && test "${with_native_compilation}" = "default"; then
+  with_native_compilation=no
+fi
+
 if test "${with_native_compilation}" = "default"; then
     # Check if libgccjit is available.
     AC_CHECK_LIB([gccjit], [gcc_jit_context_acquire],
@@ -7087,14 +7092,11 @@ fi
 
 version=$PACKAGE_VERSION
 
-copyright="Copyright (C) 2023 Free Software Foundation, Inc."
+copyright="Copyright (C) 2024 Free Software Foundation, Inc."
 AC_DEFINE_UNQUOTED([COPYRIGHT], ["$copyright"],
   [Short copyright string for this version of Emacs.])
 AC_SUBST([copyright])
 
-# This is needed for gnulib's printf modules.
-CFLAGS="$CFLAGS -DHAVE_CONFIG_H"
-
 ### Specify what sort of things we'll be editing into Makefile and config.h.
 ### Use configuration here uncanonicalized to avoid exceeding size limits.
 AC_SUBST([version])
@@ -7461,6 +7463,8 @@ case "$opsys" in
 
   mingw32)
    ## Is it any better under MinGW64 to relocate emacs into higher addresses?
+   ## If the values of -image-base are modified, the corresponding
+   ## values of DEFAULT_IMAGE_BASE in w32fns.c should be kept in sync.
    case "$canonical" in
      x86_64-*-*) LD_SWITCH_SYSTEM_TEMACS="-Wl,-stack,0x00800000 
-Wl,-heap,0x00100000 -Wl,-image-base,0x400000000 -Wl,-entry,__start 
-Wl,-Map,./temacs.map" ;;
      *) LD_SWITCH_SYSTEM_TEMACS="-Wl,-stack,0x00800000 -Wl,-heap,0x00100000 
-Wl,-image-base,0x01000000 -Wl,-entry,__start -Wl,-Map,./temacs.map" ;;
diff --git a/cross/Makefile.in b/cross/Makefile.in
index b66025283aa..6f2250fe02f 100644
--- a/cross/Makefile.in
+++ b/cross/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/cross/langinfo.h b/cross/langinfo.h
index b296ba8db80..0edb0082bda 100644
--- a/cross/langinfo.h
+++ b/cross/langinfo.h
@@ -1,6 +1,6 @@
 /* Replacement langinfo.h file for building GNU Emacs on Android.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/cross/ndk-build/Makefile.in b/cross/ndk-build/Makefile.in
index cdf18471ff3..8ba2d356f27 100644
--- a/cross/ndk-build/Makefile.in
+++ b/cross/ndk-build/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/cross/ndk-build/README b/cross/ndk-build/README
index aca2e7230bf..84a131443c4 100644
--- a/cross/ndk-build/README
+++ b/cross/ndk-build/README
@@ -1,6 +1,6 @@
 NDK BUILD SYSTEM IMPLEMENTATION
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Emacs implements ndk-build itself, because the version that comes with
@@ -86,7 +86,7 @@ $(ANDROID_MAKEFILE), the ``Android.mk'' file, for the first 
time.  The
 purpose of this evaluation is to establish a list of packages (or
 modules) provided by the ``Android.mk'' file, and the corresponding
 Makefile targets and compiler and linker flags required to build and
-link to those tagets.
+link to those targets.
 
 Before doing so, build-aux/ndk-build-helper.mk will define several
 variables and functions required by all ``Android.mk'' files.  The
@@ -164,7 +164,7 @@ module_cxx_deps=""
 module_imports=""
 
 which is then evaluated by `configure'.         Once the variable
-`module_name' is set, configure apends the remaining
+`module_name' is set, configure appends the remaining
 $(module_includes), $(module_cflags) and $(module_ldflags) to the
 module's CFLAGS and LIBS variables, and appends the list of Makefile
 targets specified to the variable NDK_BUILD_MODULES.
diff --git a/cross/ndk-build/ndk-build-executable.mk 
b/cross/ndk-build/ndk-build-executable.mk
index 9591c862b18..4f520074c7f 100644
--- a/cross/ndk-build/ndk-build-executable.mk
+++ b/cross/ndk-build/ndk-build-executable.mk
@@ -1,4 +1,4 @@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/cross/ndk-build/ndk-build-shared-library.mk 
b/cross/ndk-build/ndk-build-shared-library.mk
index d60802da1d0..74c6756a0c1 100644
--- a/cross/ndk-build/ndk-build-shared-library.mk
+++ b/cross/ndk-build/ndk-build-shared-library.mk
@@ -1,4 +1,4 @@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/cross/ndk-build/ndk-build-static-library.mk 
b/cross/ndk-build/ndk-build-static-library.mk
index 98afd864ed6..aba4539f6bb 100644
--- a/cross/ndk-build/ndk-build-static-library.mk
+++ b/cross/ndk-build/ndk-build-static-library.mk
@@ -1,4 +1,4 @@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/cross/ndk-build/ndk-build.mk.in b/cross/ndk-build/ndk-build.mk.in
index 57006901721..6c85ff5044e 100644
--- a/cross/ndk-build/ndk-build.mk.in
+++ b/cross/ndk-build/ndk-build.mk.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/cross/ndk-build/ndk-clear-vars.mk 
b/cross/ndk-build/ndk-clear-vars.mk
index 7309b7bb513..0803522f3d4 100644
--- a/cross/ndk-build/ndk-clear-vars.mk
+++ b/cross/ndk-build/ndk-clear-vars.mk
@@ -1,4 +1,4 @@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/cross/ndk-build/ndk-prebuilt-shared-library.mk 
b/cross/ndk-build/ndk-prebuilt-shared-library.mk
index 2a8260f9851..d63ca4a0c76 100644
--- a/cross/ndk-build/ndk-prebuilt-shared-library.mk
+++ b/cross/ndk-build/ndk-prebuilt-shared-library.mk
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/cross/ndk-build/ndk-prebuilt-static-library.mk 
b/cross/ndk-build/ndk-prebuilt-static-library.mk
index 9230f690bb1..94c98435d5f 100644
--- a/cross/ndk-build/ndk-prebuilt-static-library.mk
+++ b/cross/ndk-build/ndk-prebuilt-static-library.mk
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/cross/ndk-build/ndk-resolve.mk b/cross/ndk-build/ndk-resolve.mk
index b29a2c6dc39..d3b398bca62 100644
--- a/cross/ndk-build/ndk-resolve.mk
+++ b/cross/ndk-build/ndk-resolve.mk
@@ -1,4 +1,4 @@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/cross/verbose.mk.android b/cross/verbose.mk.android
index d41d6b6aac0..958cf237c58 100644
--- a/cross/verbose.mk.android
+++ b/cross/verbose.mk.android
@@ -1,7 +1,7 @@
 ### verbose.mk --- Makefile fragment for GNU Emacs during
 ### cross-compilation.
 
-## Copyright (C) 2023 Free Software Foundation, Inc.
+## Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ## This file is part of GNU Emacs.
 
diff --git a/doc/emacs/ChangeLog.1 b/doc/emacs/ChangeLog.1
index 6e20eb942ce..e1de11c5540 100644
--- a/doc/emacs/ChangeLog.1
+++ b/doc/emacs/ChangeLog.1
@@ -1294,7 +1294,7 @@
 
        * display.texi (Visual Line Mode): Fix index entry.
 
-       * buffers.texi (Several Buffers): List Buffer Menu command anmes,
+       * buffers.texi (Several Buffers): List Buffer Menu command names,
        and index the keybindings.  Document tabulated-list-sort.
        (Kill Buffer): Capitalize Buffer Menu.
 
@@ -6443,7 +6443,7 @@
 
 2007-01-01  Richard Stallman  <rms@gnu.org>
 
-       * commands.texi (User Input): Document keys stolen by window mangers.
+       * commands.texi (User Input): Document keys stolen by window managers.
 
 2006-12-31  Richard Stallman  <rms@gnu.org>
 
@@ -10919,7 +10919,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1993-1999, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1993-1999, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/doc/emacs/Makefile.in b/doc/emacs/Makefile.in
index c7415312753..4c51e2277ae 100644
--- a/doc/emacs/Makefile.in
+++ b/doc/emacs/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 1994, 1996-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1996-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/doc/emacs/abbrevs.texi b/doc/emacs/abbrevs.texi
index 6c171d47427..a00837fe7d0 100644
--- a/doc/emacs/abbrevs.texi
+++ b/doc/emacs/abbrevs.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Abbrevs
diff --git a/doc/emacs/ack.texi b/doc/emacs/ack.texi
index 483ea3306a3..62f6382113e 100644
--- a/doc/emacs/ack.texi
+++ b/doc/emacs/ack.texi
@@ -1,6 +1,6 @@
 @c -*- coding: utf-8 -*-
 @c This is part of the Emacs manual.
-@c Copyright (C) 1994--1997, 1999--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1994--1997, 1999--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @c
 @node Acknowledgments
diff --git a/doc/emacs/android.texi b/doc/emacs/android.texi
index 915ba948b93..0ea96d91492 100644
--- a/doc/emacs/android.texi
+++ b/doc/emacs/android.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 2023 Free Software Foundation, Inc.
+@c Copyright (C) 2023--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Android
 @appendix Emacs and Android
@@ -234,7 +234,7 @@ Document Providers}.)
 the (normally read-only) root directory named @file{content} or
 @file{assets}, you may want to access real files by these names if the
 Android installation in use has been customized.  These files will
-conflict with the aformentioned special directories, but can
+conflict with the aforementioned special directories, but can
 nevertheless be accessed by writing their names relative to the
 ``parent'' directory of the root directory, as so illustrated:
 @file{/../content}, @file{/../assets}.
@@ -258,7 +258,7 @@ at startup to symlink the application library directory to 
its
 traditional location within the parent of the app data directory.
 
   If Emacs is reinstalled and the location of the app library
-directory consequentially changes, that symlink will also be updated
+directory consequently changes, that symlink will also be updated
 to point to its new location the next time Emacs is started by the
 system.
 
@@ -340,7 +340,7 @@ to its app data directory (@pxref{Android File
 System}.)@footnote{Except in cases where a ``shared user ID'' is
 specified and other applications signed using the same ``package
 signing key'' are installed, in which case Emacs runs as the same user
-and has access to the same files as each of the aformentioned
+and has access to the same files as each of the aforementioned
 applications.}
 
   Each application is also prohibited from accessing many system
@@ -409,6 +409,24 @@ Startup}) connect the Android system to another computer, 
and run:
 $ adb shell "settings put global settings_enable_monitor_phantom_procs false"
 @end example
 
+@cindex system language settings, Android
+  The ``Languages & Input'' preferences which apply to the operating
+system do not influence the C locale set for programs, but are taken
+into account by Emacs during startup: a locale name is generated from
+the selected language and regional variant and a language environment
+(@pxref{Language Environments}) is selected on that basis, which does
+not overwrite @code{LANG} or other locale-related environment
+variables.  The coding system for language environments set in this
+fashion is @code{utf-8-unix} without exception.
+
+@cindex C locale settings, Android
+  Instead, the @code{LANG} environment variable (@pxref{General
+Variables}) is set to @code{en_US.utf8} when Emacs starts on Android
+5.0 or newer, which induces subprocesses linked against the Android C
+library to print output sensibly.  Earlier versions of Android do not
+implement locales at all, and on that account, the variable is set to
+@code{C}.
+
 @cindex running emacs in the background, android
 @cindex emacs killed, android
 @cindex emacs in the background, android
diff --git a/doc/emacs/anti.texi b/doc/emacs/anti.texi
index b25d8a8e3cc..7abb504632b 100644
--- a/doc/emacs/anti.texi
+++ b/doc/emacs/anti.texi
@@ -1,6 +1,6 @@
 @c -*- coding: utf-8 -*-
 @c This is part of the Emacs manual.
-@c Copyright (C) 2005--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2005--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 
 @node Antinews
diff --git a/doc/emacs/arevert-xtra.texi b/doc/emacs/arevert-xtra.texi
index 9dc1d3b5fb7..621804ced85 100644
--- a/doc/emacs/arevert-xtra.texi
+++ b/doc/emacs/arevert-xtra.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @c
 @c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/back.texi b/doc/emacs/back.texi
index 49b116df72d..ff6905d8b02 100644
--- a/doc/emacs/back.texi
+++ b/doc/emacs/back.texi
@@ -1,6 +1,6 @@
 \input texinfo  @c -*-texinfo-*-
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @c
@@ -78,7 +78,7 @@ And much more!
 Emacs comes with an introductory online tutorial available in many
 languages, and this nineteenth edition of the manual picks up where
 that tutorial ends.  It explains the full range of the power of Emacs,
-now up to @strong[version 27.2,} and contains reference material
+now up to @strong{version 27.2,} and contains reference material
 useful to expert users.  It also includes appendices with specific
 material about X and GTK resources, and with details for users of
 macOS and Microsoft Windows.
diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi
index d41e5f2f16c..b1b1573729a 100644
--- a/doc/emacs/basic.texi
+++ b/doc/emacs/basic.texi
@@ -1,6 +1,6 @@
 @c -*- coding: utf-8 -*-
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Basic
@@ -630,6 +630,21 @@ before they get too long, by inserting newlines.  If you 
prefer, you
 can make Emacs insert a newline automatically when a line gets too
 long, by using Auto Fill mode.  @xref{Filling}.
 
+@cindex continuation lines, visual wrap prefix
+@findex visual-wrap-prefix-mode
+@findex global-visual-wrap-prefix-mode
+  Normally, the first character of each continuation line is
+positioned at the beginning of the screen line where it is displayed.
+The minor mode @code{visual-wrap-prefix-mode} and its global
+(@pxref{Minor Modes}) counterpart
+@code{global-visual-wrap-prefix-mode} arranges that continuation lines
+be prefixed by slightly adjusted versions of the fill prefixes
+(@pxref{Fill Prefix}) of their respective logical lines, so that
+indentation characters or the prefixes of source code comments are
+replicated across every continuation line, and the appearance of such
+comments or indentation is not broken.  These prefixes are only shown
+on display, and does not change the buffer text in any way.
+
   Sometimes, you may need to edit files containing many long logical
 lines, and it may not be practical to break them all up by adding
 newlines.  In that case, you can use Visual Line mode, which enables
diff --git a/doc/emacs/buffers.texi b/doc/emacs/buffers.texi
index b6aafe24b96..d9113a6811a 100644
--- a/doc/emacs/buffers.texi
+++ b/doc/emacs/buffers.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Buffers
@@ -262,12 +262,14 @@ non-@code{nil}.  If you change the option 
@code{view-read-only} to a
 non-@code{nil} value, making the buffer read-only with @kbd{C-x C-q}
 also enables View mode in the buffer (@pxref{View Mode}).
 
+@kindex C-x x r
 @findex rename-buffer
   @kbd{C-x x r} (@code{rename-buffer} changes the name of the current
 buffer.  You specify the new name as a minibuffer argument; there is
 no default.  If you specify a name that is in use for some other
 buffer, an error happens and no renaming is done.
 
+@kindex C-x x u
 @findex rename-uniquely
   @kbd{C-x x u} (@code{rename-uniquely}) renames the current buffer to
 a similar name with a numeric suffix added to make it both different
@@ -282,6 +284,7 @@ buffers with particular names.  (With some of these 
features, such as
 buffer before using the command again, otherwise it will reuse the
 current buffer despite the name change.)
 
+@kindex C-x x i
   The commands @kbd{M-x append-to-buffer} and @kbd{C-x x i}
 (@code{insert-buffer}) can also be used to copy text from one buffer
 to another.  @xref{Accumulating Text}.
@@ -728,7 +731,7 @@ rule or another is easier for you to remember and apply 
quickly.
 @findex icomplete-mode
 @cindex Icomplete mode
 
-  Icomplete global minor mode provides a convenient way to quickly select an
+  Icomplete mode provides a convenient way to quickly select an
 element among the possible completions in a minibuffer.  When enabled, typing
 in the minibuffer continuously displays a list of possible completions that
 match the string you have typed.
@@ -746,9 +749,28 @@ further.  This is typically used when entering a file 
name, where
 @kbd{M-@key{TAB}} can be used a few times to descend in the hierarchy
 of directories.
 
-  To enable Icomplete mode, type @kbd{M-x icomplete-mode}, or customize
-the variable @code{icomplete-mode} to @code{t} (@pxref{Easy
-Customization}).
+  To enable Icomplete mode for the minibuffer, type @kbd{M-x
+icomplete-mode}, or customize the variable @code{icomplete-mode} to
+@code{t} (@pxref{Easy Customization}).
+
+  You can also additionally enable Icomplete mode for @kbd{C-M-i} (the
+command @code{completion-at-point}) by customizing the variable
+@code{icomplete-in-buffer} to @code{t}.  For in-buffer completion, the
+@code{completion-auto-help} variable controls when Icomplete mode's
+display of possible completions appears.  The default value of
+@code{t} means that the display of possible completions appears when
+you first type @kbd{C-M-i}.
+
+  By default, when you press @kbd{C-M-i}, both Icomplete mode's
+in-buffer display of possible completions and the @file{*Completions*}
+buffer appear.  If you are using @code{icomplete-in-buffer}, then you
+may wish to suppress this appearance of the @file{*Completions*}
+buffer.  To do that, add the following to your initialization file
+(@pxref{Init File}):
+
+@example
+(advice-add 'completion-at-point :after #'minibuffer-hide-completions)
+@end example
 
 @findex fido-mode
 @cindex fido mode
diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi
index a2639ce6d3e..38cc0bb67af 100644
--- a/doc/emacs/building.texi
+++ b/doc/emacs/building.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Building
diff --git a/doc/emacs/cal-xtra.texi b/doc/emacs/cal-xtra.texi
index f0341a2817d..49fa2e9547e 100644
--- a/doc/emacs/cal-xtra.texi
+++ b/doc/emacs/cal-xtra.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.  -*- coding: utf-8 -*-
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @c
 @c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/calendar.texi b/doc/emacs/calendar.texi
index 7b5b1b78fc9..7312cfb34c9 100644
--- a/doc/emacs/calendar.texi
+++ b/doc/emacs/calendar.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.  -*- coding: utf-8 -*-
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Calendar/Diary
diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi
index 38e683bd7f5..49810ee7693 100644
--- a/doc/emacs/cmdargs.texi
+++ b/doc/emacs/cmdargs.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Emacs Invocation
@@ -640,6 +640,11 @@ set this in the ``Regional Settings'' Control Panel on 
some versions
 of MS-Windows, and in the ``Language and Region'' System Preference on
 macOS.
 
+When running a GUI session on Android, @env{LANG} is set to a fixed
+value, but the language and locale environment is derived from the
+system's ``Languages & Input'' preferences.  @xref{Android
+Environment}.
+
 The value of the @env{LC_CTYPE} category is
 matched against entries in @code{locale-language-names},
 @code{locale-charset-language-names}, and
diff --git a/doc/emacs/commands.texi b/doc/emacs/commands.texi
index cb924519175..a8f89feed62 100644
--- a/doc/emacs/commands.texi
+++ b/doc/emacs/commands.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @iftex
diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi
index 3be332e087f..4725af0ee5f 100644
--- a/doc/emacs/custom.texi
+++ b/doc/emacs/custom.texi
@@ -1,6 +1,6 @@
 @c -*- coding: utf-8 -*-
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Customization
@@ -188,14 +188,15 @@ find with @kbd{M-x customize-browse}.
 the customization buffer:
 
 @smallexample
-[Hide] Kill Ring Max: 60
+[Hide] Kill Ring Max: Integer (positive or zero): 120
    [State]: STANDARD.
    Maximum length of kill ring before oldest elements are thrown away.
 @end smallexample
 
   The first line shows that the variable is named
 @code{kill-ring-max}, formatted as @samp{Kill Ring Max} for easier
-viewing.  Its value is @samp{120}.  The button labeled @samp{[Hide]},
+viewing, and also shows its expected type: a positive integer or zero.
+The default value is @samp{120}.  The button labeled @samp{[Hide]},
 if activated, hides the variable's value and state; this is useful to
 avoid cluttering up the customization buffer with very long values
 (for this reason, variables that have very long values may start out
@@ -2065,7 +2066,7 @@ C-a} is a way to enter @kbd{Hyper-Control-a}.  
(Unfortunately, there
 is no way to add two modifiers by using @kbd{C-x @@} twice for the
 same character, because the first one goes to work on the @kbd{C-x}.)
 You can similarly enter the Shift, Control, and Meta modifiers by
-using @kbd{C-x @ S}, @kbd{C-x @ c}, and @kbd{C-x @ m}, respectively,
+using @kbd{C-x @@ S}, @kbd{C-x @@ c}, and @kbd{C-x @@ m}, respectively,
 although this is rarely needed.
 
 @node Function Keys
diff --git a/doc/emacs/dired-xtra.texi b/doc/emacs/dired-xtra.texi
index 04b5ed44ed1..12cba1345b9 100644
--- a/doc/emacs/dired-xtra.texi
+++ b/doc/emacs/dired-xtra.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @c
 @c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi
index 87124e962ca..a3a740f9727 100644
--- a/doc/emacs/dired.texi
+++ b/doc/emacs/dired.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Dired
@@ -142,6 +142,10 @@ characters well.  If you have many such files, you may 
consider adding
 special characters and allow Dired to handle them better.  (You can
 also use the @kbd{C-u C-x d} command to add @samp{-b} temporarily.)
 
+@code{dired-listing-switches} can be declared as connection-local
+variable to adjust it to match what a remote system expects
+(@pxref{Connection Variables}).
+
 @vindex dired-switches-in-mode-line
   Dired displays in the mode line an indication of what were the
 switches used to invoke @command{ls}.  By default, Dired will try to
diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi
index d9da4c1335c..6db9e8344c6 100644
--- a/doc/emacs/display.texi
+++ b/doc/emacs/display.texi
@@ -1,6 +1,6 @@
 @c -*- coding: utf-8 -*-
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 
 @c See file emacs.texi for copying conditions.
@@ -1986,6 +1986,7 @@ the fringe indicates truncation at either end of the 
line.  On text
 terminals, this is indicated with @samp{$} signs in the rightmost
 and/or leftmost columns.
 
+@kindex C-x x t
 @vindex truncate-lines
 @findex toggle-truncate-lines
   Horizontal scrolling automatically causes line truncation
diff --git a/doc/emacs/emacs-xtra.texi b/doc/emacs/emacs-xtra.texi
index 066070262a7..442fe952075 100644
--- a/doc/emacs/emacs-xtra.texi
+++ b/doc/emacs/emacs-xtra.texi
@@ -16,7 +16,7 @@
 @copying
 This manual describes specialized features of Emacs.
 
-Copyright @copyright{} 2004--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2004--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi
index e1c55c0719e..7d77f13ab21 100644
--- a/doc/emacs/emacs.texi
+++ b/doc/emacs/emacs.texi
@@ -20,7 +20,7 @@ This is the @cite{GNU Emacs Manual},
 @end ifclear
 updated for Emacs version @value{EMACSVER}.
 
-Copyright @copyright{} 1985--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1985--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/emacs/emerge-xtra.texi b/doc/emacs/emerge-xtra.texi
index 32392dde460..8d6df87b648 100644
--- a/doc/emacs/emerge-xtra.texi
+++ b/doc/emacs/emerge-xtra.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @c
 @c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/entering.texi b/doc/emacs/entering.texi
index c23015ee10e..2dfc11a7b32 100644
--- a/doc/emacs/entering.texi
+++ b/doc/emacs/entering.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @iftex
diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi
index 917e937d32d..b152b7943a2 100644
--- a/doc/emacs/files.texi
+++ b/doc/emacs/files.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Files
@@ -1061,6 +1061,7 @@ revert it automatically if it has changed---provided the 
buffer itself
 is not modified.  (If you have edited the text, it would be wrong to
 discard your changes.)
 
+@kindex C-x x g
 @vindex revert-buffer-quick-short-answers
 @findex revert-buffer-quick
   The @kbd{C-x x g} keystroke is bound to the
@@ -1329,6 +1330,10 @@ directory listing describing the specified file and the 
auto-save file,
 so you can compare their sizes and dates.  If the auto-save file
 is older, @kbd{M-x recover-file} does not offer to read it.
 
+When @kbd{M-x recover-file} asks for confirmation, if you answer with
+@kbd{diff} or @kbd{=}, it shows the diffs between @var{file} and its
+auto-save file @file{#@var{file}#} and reprompts you for confirmation.
+
 @findex recover-session
   If Emacs or the computer crashes, you can recover all the files you
 were editing from their auto save files with the command @kbd{M-x
diff --git a/doc/emacs/fixit.texi b/doc/emacs/fixit.texi
index e31df4865fc..f3c876cf3f7 100644
--- a/doc/emacs/fixit.texi
+++ b/doc/emacs/fixit.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Fixit
@@ -274,6 +274,9 @@ you can control which one is used by customizing the 
variable
 @item M-$
 Check and correct spelling of the word at point (@code{ispell-word}).
 If the region is active, do it for all words in the region instead.
+@item C-u M-$
+If a previous spelling operation was interrupted, continue that
+operation (@code{ispell-continue}).
 @item M-x ispell
 Check and correct spelling of all words in the buffer.  If the region
 is active, do it for all words in the region instead.
@@ -305,12 +308,16 @@ Enable Flyspell mode for comments and strings only.
 
 @kindex M-$
 @findex ispell-word
+@findex ispell-continue
   To check the spelling of the word around or before point, and
 optionally correct it as well, type @kbd{M-$} (@code{ispell-word}).
 If a region is active, @kbd{M-$} checks the spelling of all words
 within the region.  @xref{Mark}.  (When Transient Mark mode is off,
 @kbd{M-$} always acts on the word around or before point, ignoring the
-region; @pxref{Disabled Transient Mark}.)
+region; @pxref{Disabled Transient Mark}.)  When invoked with a prefix
+argument, @kbd{C-u M-$}, this calls @code{ispell-continue}, which
+continues the spelling operation, if any, which was interrupted with
+@kbd{X} or @kbd{C-g}.
 
 @findex ispell
 @findex ispell-buffer
@@ -383,9 +390,9 @@ wildcard.
 
 @item C-g
 @itemx X
-Quit interactive spell-checking, leaving point at the word that was
-being checked.  You can restart checking again afterward with @w{@kbd{C-u
-M-$}}.
+Interrupt the interactive spell-checking, leaving point at the word
+that was being checked.  You can restart checking again afterward with
+@w{@kbd{C-u M-$}}.
 
 @item x
 Quit interactive spell-checking and move point back to where it was
@@ -394,6 +401,19 @@ when you started spell-checking.
 @item q
 Quit interactive spell-checking and kill the spell-checker subprocess.
 
+@item C-r
+Enter recursive-edit (@pxref{Recursive Edit}).  When you exit
+recursive-edit with @kbd{C-M-c}, the interactive spell-checking will
+resume.  This allows you to consult the buffer text without
+interrupting the spell-checking.  Do @emph{not} modify the buffer in
+the recursive editing, and especially don't modify the misspelled
+word, as the edits will be undone when you exit recursive-edit.  If
+you need to edit the misspelled word, use @kbd{r} or @kbd{R} instead,
+or use @kbd{X}, edit the buffer, then resume with @w{@kbd{C-u M-$}}.
+
+@item C-z
+Suspend Emacs or iconify the selected frame.
+
 @item ?
 Show the list of options.
 @end table
diff --git a/doc/emacs/fortran-xtra.texi b/doc/emacs/fortran-xtra.texi
index 8e904cfbd28..5225dfccbd0 100644
--- a/doc/emacs/fortran-xtra.texi
+++ b/doc/emacs/fortran-xtra.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @c
 @c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi
index 1862ed2d5d4..8e6cbeed70b 100644
--- a/doc/emacs/frames.texi
+++ b/doc/emacs/frames.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1985--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Frames
 @chapter Frames and Graphical Displays
diff --git a/doc/emacs/glossary.texi b/doc/emacs/glossary.texi
index e845ea8827a..344e4831f36 100644
--- a/doc/emacs/glossary.texi
+++ b/doc/emacs/glossary.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Glossary
diff --git a/doc/emacs/gnu.texi b/doc/emacs/gnu.texi
index f484e5499a5..f7c77e23f7f 100644
--- a/doc/emacs/gnu.texi
+++ b/doc/emacs/gnu.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1985--1987, 1993, 1995, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993, 1995, 2001--2024 Free Software
 @c Foundation, Inc.
 @c
 @c Permission is granted to anyone to make or distribute verbatim copies
diff --git a/doc/emacs/haiku.texi b/doc/emacs/haiku.texi
index 0bb216c14ae..8b2a12b8223 100644
--- a/doc/emacs/haiku.texi
+++ b/doc/emacs/haiku.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 2021--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2021--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Haiku
 @appendix Emacs and Haiku
@@ -10,7 +10,7 @@ re-implementation of the operating system BeOS.
 
   This appendix describes the peculiarities of using Emacs built with
 the Application Kit, the windowing system indigenous to Haiku.  The
-idiosyncracies illustrated here do not apply to Emacs on Haiku built
+idiosyncrasies illustrated here do not apply to Emacs on Haiku built
 without windowing support, or configured with X11.
 
 @menu
diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi
index 945e12a05d2..99a4173ac29 100644
--- a/doc/emacs/help.texi
+++ b/doc/emacs/help.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Help
@@ -115,6 +115,9 @@ Display a list of commands whose names match @var{topics}
 Display all active key bindings; minor mode bindings first, then those
 of the major mode, then global bindings (@code{describe-bindings}).
 @xref{Misc Help}.
+@item C-h C-q
+Toggle display of a window showing popular commands and their key
+bindings.  @xref{Misc Help}.
 @item C-h c @var{key}
 Show the name of the command that the key sequence @var{key} is bound
 to (@code{describe-key-briefly}).  Here @kbd{c} stands for
@@ -710,6 +713,18 @@ displays the contents of the syntax table, with 
explanations of each
 character's syntax (@pxref{Syntax Tables,, Syntax Tables, elisp, The
 Emacs Lisp Reference Manual}).
 
+@kindex C-h C-q
+@findex help-quick-toggle
+@findex help-quick
+@cindex cheat sheet of popular Emacs commands
+  @kbd{C-h C-q} (@code{help-quick-toggle}) toggles on and off the
+display of a buffer showing the most popular Emacs commands and their
+respective key bindings (a.k.a.@: ``cheat sheet'').  The contents of
+that buffer are created by the command @code{help-quick}.  Each key
+binding shown in this buffer is a button: click on it with
+@kbd{mouse-1} or @kbd{mouse-2} to show the documentation of the
+command bound to that key sequence.
+
 @findex describe-prefix-bindings
   You can get a list of subcommands for a particular prefix key by
 typing @kbd{C-h}, @kbd{?}, or @key{F1}
diff --git a/doc/emacs/indent.texi b/doc/emacs/indent.texi
index 0df973c1dd0..de5f35f6139 100644
--- a/doc/emacs/indent.texi
+++ b/doc/emacs/indent.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Indentation
diff --git a/doc/emacs/input.texi b/doc/emacs/input.texi
index 7f9d37b52de..67679b00e89 100644
--- a/doc/emacs/input.texi
+++ b/doc/emacs/input.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 2023 Free Software Foundation, Inc.
+@c Copyright (C) 2023--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Other Input
 @section Touchscreen Input and Virtual Keyboards
diff --git a/doc/emacs/killing.texi b/doc/emacs/killing.texi
index 4d5c9ecc7b2..9717c02f782 100644
--- a/doc/emacs/killing.texi
+++ b/doc/emacs/killing.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 
diff --git a/doc/emacs/kmacro.texi b/doc/emacs/kmacro.texi
index 05095bc68b8..e30def34475 100644
--- a/doc/emacs/kmacro.texi
+++ b/doc/emacs/kmacro.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Keyboard Macros
diff --git a/doc/emacs/m-x.texi b/doc/emacs/m-x.texi
index 7b366562019..6a88b2019a0 100644
--- a/doc/emacs/m-x.texi
+++ b/doc/emacs/m-x.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node M-x
diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi
index c1927a01eb4..b5f263996cb 100644
--- a/doc/emacs/macos.texi
+++ b/doc/emacs/macos.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 2000--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2000--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Mac OS / GNUstep
 @appendix Emacs and macOS / GNUstep
diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index 0725d889747..d3e06fa697b 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual., Abbrevs, This is part of the Emacs 
manual., Top
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Maintaining
@@ -2683,7 +2683,7 @@ use tags, separate from the @command{etags} facility.
 
 @menu
 * Tag Syntax::          Tag syntax for various types of code and text files.
-* Create Tags Table::   Creating a tags table with @command{etags}.
+* Create Tags Table::   Creating and updating tags tables with @command{etags}.
 * Etags Regexps::       Create arbitrary tags using regular expressions.
 @end menu
 
@@ -2999,6 +2999,38 @@ explanation.  If followed by one or more 
@samp{--language=@var{lang}}
 options, it outputs detailed information about how tags are generated for
 @var{lang}.
 
+@findex etags-regen-mode
+  Instead of creating and updating the tags table by manually invoking
+@command{etags}, you can ask Emacs to do it for you automatically.
+The global minor mode @code{etags-regen-mode}, if enabled, generates
+tags tables automatically as needed, and takes care of updating them
+when you edit any of the source files that contribute tags.  This mode
+uses the current project configuration (@pxref{Projects}) to determine
+which files to submit to @command{etags} for regenerating the tags
+table for the project.  You can customize how this minor mode works
+using the following user options:
+
+@vtable @code
+@item etags-regen-program
+The program to regenerate tags table; defaults to @command{etags}.
+
+@item etags-regen-program-options
+Command-line options to pass to the program which regenerates tags
+tables.
+
+@item etags-regen-ignores
+List of glob patterns which specify files to ignore when regenerating
+tags tables.
+@end vtable
+
+@cindex tags-reset-tags-tables
+  If you select a tags table manually, with @kbd{M-x visit-tags-table}
+(@pxref{Select Tags Table}), @code{etags-regen-mode} effectively
+disables itself: it will no longer automatically create and update
+tags tables, assuming that you prefer managing your tags tables
+manually.  You can cancel this effect of using @code{visit-tags-table}
+by invoking the command @code{tags-reset-tags-tables}.
+
 @node Etags Regexps
 @subsubsection Etags Regexps
 
diff --git a/doc/emacs/mark.texi b/doc/emacs/mark.texi
index 3f1c76c1591..0d705769f55 100644
--- a/doc/emacs/mark.texi
+++ b/doc/emacs/mark.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Mark
diff --git a/doc/emacs/mini.texi b/doc/emacs/mini.texi
index a104cd2bfa1..aa7144610a6 100644
--- a/doc/emacs/mini.texi
+++ b/doc/emacs/mini.texi
@@ -1,6 +1,6 @@
 @c -*- coding: utf-8 -*-
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Minibuffer
@@ -709,7 +709,9 @@ will use just one column.
   The @code{completions-sort} user option controls the order in which
 the completions are sorted in the @samp{*Completions*} buffer.  The
 default is @code{alphabetical}, which sorts in alphabetical order.
-The value @code{nil} disables sorting.  The value can also be a
+The value @code{nil} disables sorting; the value @code{historical}
+sorts alphabetically first, and then rearranges according to the order
+of the candidates in the minibuffer history.  The value can also be a
 function, which will be called with the list of completions, and
 should return the list in the desired order.
 
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index eb197f738f5..7eb28f56826 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1985--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @iftex
 @chapter Miscellaneous Commands
diff --git a/doc/emacs/modes.texi b/doc/emacs/modes.texi
index d2f96af0b55..2776dc72a27 100644
--- a/doc/emacs/modes.texi
+++ b/doc/emacs/modes.texi
@@ -1,6 +1,6 @@
 @c -*- coding: utf-8 -*-
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Modes
diff --git a/doc/emacs/msdos-xtra.texi b/doc/emacs/msdos-xtra.texi
index 11e63be51a0..74bb68d0547 100644
--- a/doc/emacs/msdos-xtra.texi
+++ b/doc/emacs/msdos-xtra.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @c
 @c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/msdos.texi b/doc/emacs/msdos.texi
index 8401a2aa596..861c0d90dc6 100644
--- a/doc/emacs/msdos.texi
+++ b/doc/emacs/msdos.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Microsoft Windows
@@ -1182,12 +1182,23 @@ click-to-focus policy.
 @end ifnottex
 
   On Windows 10 (version 1809 and higher) and Windows 11, Emacs title
-bars and scroll bars will follow the system's Light or Dark mode,
-similar to other programs such as Explorer and Command Prompt.  To
-change the color mode, select @code{Personalization} from
-@w{@code{Windows Settings}}, then
-@w{@code{Colors->Choose your color}} (or @w{@code{Choose your default
-app mode}}); then restart Emacs.
+bars and scroll bars by default follow the system's Light or Dark
+mode, similar to other programs such as Explorer and Command Prompt.
+To change the color mode, select @code{Personalization} from
+@w{@code{Windows Settings}}, then @w{@code{Colors->Choose your color}}
+(or @w{@code{Choose your default app mode}} or @w{@code{Choose your
+mode}}); then restart Emacs.  On Windows 11, you can select separate
+default modes for Windows and for applications.
+
+@vindex w32-follow-system-dark-mode
+  If you don't want Emacs to follow the system's Dark mode setting,
+customize the variable @code{w32-follow-system-dark-mode} to a
+@code{nil} value; then Emacs will use the default Light mode
+regardless of system-wide settings.  Changing the value of this
+variable affects only the Emacs frames created after the change, so
+you should set its value in your init file (@pxref{Init File}), either
+directly or via @kbd{M-x customize-variable}, which lets you save the
+customized value, see @ref{Saving Customizations}.
 
 @ifnottex
 @include msdos-xtra.texi
diff --git a/doc/emacs/mule.texi b/doc/emacs/mule.texi
index 3a4ff5baccf..a16a9ea8f71 100644
--- a/doc/emacs/mule.texi
+++ b/doc/emacs/mule.texi
@@ -1,6 +1,6 @@
 @c -*- coding: utf-8 -*-
 @c This is part of the Emacs manual.
-@c Copyright (C) 1997, 1999--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1997, 1999--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node International
 @chapter International Character Set Support
diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi
index 96ebd35f547..c8f790bab47 100644
--- a/doc/emacs/package.texi
+++ b/doc/emacs/package.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Packages
diff --git a/doc/emacs/picture-xtra.texi b/doc/emacs/picture-xtra.texi
index d155a34951d..1eabd54af11 100644
--- a/doc/emacs/picture-xtra.texi
+++ b/doc/emacs/picture-xtra.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @c
 @c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi
index 3f3801abdb4..1627e7e6cb7 100644
--- a/doc/emacs/programs.texi
+++ b/doc/emacs/programs.texi
@@ -1,6 +1,6 @@
 @c -*- coding: utf-8 -*-
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Programs
diff --git a/doc/emacs/regs.texi b/doc/emacs/regs.texi
index 5e5b7ae2b16..cac5b32c566 100644
--- a/doc/emacs/regs.texi
+++ b/doc/emacs/regs.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Registers
@@ -32,14 +32,58 @@ view-register}:
 Display a description of what register @var{r} contains.
 @end table
 
-@vindex register-preview-delay
+
 @cindex preview of registers
-  All of the commands that prompt for a register will display a
-preview window that lists the existing registers (if there are
-any) after a short delay.  To change the length of the delay,
-customize @code{register-preview-delay}.  To prevent this display, set
-that option to @code{nil}.  You can explicitly request a preview
-window by pressing @kbd{C-h} or @key{F1}.
+@vindex register-use-preview
+  All of the commands that prompt for a register will by default
+display a preview window that lists the existing registers (if there
+are any) and their current values, after a short delay.  This and
+other aspects of prompting for a register can be customized by setting
+the value of @code{register-use-preview}, which can have the following
+values:
+
+@table @code
+@vindex register-preview-delay
+@item traditional
+With this value, which is the default, Emacs behaves like it did in
+all the versions before Emacs 29: it shows a preview of existing registers
+after a delay, and lets you overwrite the values of existing registers
+by typing a single character, the name of the register.  The preview
+appears after the delay determined by the customizable variable
+@code{register-preview-delay}, which specifies the delay in seconds;
+setting it to @code{nil} disables the preview (but you can still
+explicitly request a preview window by pressing @kbd{C-h} or
+@key{F1} when Emacs prompts for a register).
+
+@item t
+This value requests a more flexible preview of existing registers.
+The preview appears immediately when Emacs prompts for a register
+(thus @code{register-preview-delay} has no effect), and the preview
+window provides navigation: by using @kbd{C-n} and @kbd{C-p} (or the
+@kbd{@key{UP}} and @kbd{@key{DOWN}} arrow keys), you can move between
+the registers in the preview window.  To overwrite the value of an
+existing registers in this mode, you need to type @key{RET} after
+selecting the register by navigation or typing its name.
+
+In addition, the registers shown by the preview are filtered according
+to the command that popped the preview: for example, the preview shown
+by @code{insert-register} will only show registers whose values can be
+inserted into the buffer, omitting registers which hold window
+configurations, positions, and other un-insertable values.
+
+@item insist
+This value is like @code{t}, but in addition you can press the same
+key as the name of register one more time to exit the minibuffer,
+instead of pressing @key{RET}.
+
+@item nil
+This value requests behavior similar to @code{traditional}, but the
+preview is shown without delay, and is filtered according to the
+command.
+
+@item never
+This value is like @code{nil}, but it disables the preview.
+@end table
 
   @dfn{Bookmarks} record files and positions in them, so you can
 return to those positions when you look at the file again.  Bookmarks
diff --git a/doc/emacs/rmail.texi b/doc/emacs/rmail.texi
index 382254cc11b..51bd6086ce0 100644
--- a/doc/emacs/rmail.texi
+++ b/doc/emacs/rmail.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Rmail
diff --git a/doc/emacs/screen.texi b/doc/emacs/screen.texi
index 3b910587260..6b09dcb8e0a 100644
--- a/doc/emacs/screen.texi
+++ b/doc/emacs/screen.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Screen
diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi
index 7efd4cc796c..9ba425f2d21 100644
--- a/doc/emacs/search.texi
+++ b/doc/emacs/search.texi
@@ -1,6 +1,6 @@
 @c -*- coding: utf-8 -*-
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Search
diff --git a/doc/emacs/sending.texi b/doc/emacs/sending.texi
index fb566a7f7f4..7d9f4917929 100644
--- a/doc/emacs/sending.texi
+++ b/doc/emacs/sending.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Sending Mail
diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi
index b6a9dd6de53..338bf014208 100644
--- a/doc/emacs/text.texi
+++ b/doc/emacs/text.texi
@@ -1,6 +1,6 @@
 @c -*- coding: utf-8 -*-
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Text
diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi
index 3a43203619b..22042b4c92c 100644
--- a/doc/emacs/trouble.texi
+++ b/doc/emacs/trouble.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @iftex
diff --git a/doc/emacs/vc-xtra.texi b/doc/emacs/vc-xtra.texi
index 3b0471872a2..5008cf2773b 100644
--- a/doc/emacs/vc-xtra.texi
+++ b/doc/emacs/vc-xtra.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @c
 @c This file is included in emacs-xtra.texi when producing the printed
diff --git a/doc/emacs/vc1-xtra.texi b/doc/emacs/vc1-xtra.texi
index 3785e565676..303efa05d82 100644
--- a/doc/emacs/vc1-xtra.texi
+++ b/doc/emacs/vc1-xtra.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @c
 @c This file is included either in vc-xtra.texi (when producing the
diff --git a/doc/emacs/windows.texi b/doc/emacs/windows.texi
index a2946bcada9..ad2225b5922 100644
--- a/doc/emacs/windows.texi
+++ b/doc/emacs/windows.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node Windows
@@ -287,7 +287,7 @@ Delete all windows in the selected frame except the 
selected window
 Delete the selected window and kill the buffer that was showing in it
 (@code{kill-buffer-and-window}).  The last character in this key
 sequence is a zero.
-@item M-x delete-windows-on @key{RET} @var{buffer} @key{RET}
+@item C-x w 0 @key{RET} @var{buffer} @key{RET}
 Delete windows showing the specified @var{buffer}.
 @item C-x ^
 Make selected window taller (@code{enlarge-window}).
diff --git a/doc/emacs/xresources.texi b/doc/emacs/xresources.texi
index ee054430766..bbdb7ee8876 100644
--- a/doc/emacs/xresources.texi
+++ b/doc/emacs/xresources.texi
@@ -1,5 +1,5 @@
 @c This is part of the Emacs manual.
-@c Copyright (C) 1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1987, 1993--1995, 1997, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 @node X Resources
diff --git a/doc/lang/fr/misc/ses-fr.texi b/doc/lang/fr/misc/ses-fr.texi
new file mode 100644
index 00000000000..e1b9cac5fc3
--- /dev/null
+++ b/doc/lang/fr/misc/ses-fr.texi
@@ -0,0 +1,1631 @@
+\input texinfo   @c -*- mode: texinfo; coding: utf-8; -*-
+@c %**start of header
+@setfilename ../../../../info/ses-fr.info
+@documentlanguage fr
+@documentencoding UTF-8
+@settitle @acronym{SES}: Le tableur simple d’Emacs
+@include docstyle.texi
+@setchapternewpage off
+@syncodeindex fn cp
+@syncodeindex vr cp
+@syncodeindex ky cp
+@c %**end of header
+
+@copying
+Ce fichier documente @acronym{SES} : le tableur simple d’Emacs (Simple
+Emacs Spreadsheet).
+
+Copyright @copyright{} 2002--2024 Free Software Foundation, Inc.
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
+and with the Back-Cover Texts as in (a) below.  A copy of the license
+is included in the section entitled ``GNU Free Documentation License.''
+
+(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
+modify this GNU manual.''
+@end quotation
+@end copying
+
+@dircategory Emacs misc features
+@direntry
+* @acronym{SES}-fr: (ses-fr).        Le tableur simple d’Emacs.
+@end direntry
+
+@finalout
+
+@titlepage
+@title @acronym{SES}
+@subtitle Le tableur simple d’Emacs
+@author Jonathan A. Yavner
+@author @email{jyavner@@member.fsf.org}
+
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@contents
+
+@c ===================================================================
+
+@ifnottex
+@node Top
+@comment  node-name,  next,  previous,  up
+@top @acronym{SES}: Simple Emacs Spreadsheet
+
+@display
+@acronym{SES} est mode majeur de GNU Emacs pour éditer des fichiers
+tableur, c.-à-d.@: des fichiers contenant une grille rectangulaire de
+cellules. Les valeurs des cellules sont spécifiées par des formules
+pouvant se référer aux valeurs d’autres cellules.
+@end display
+@end ifnottex
+
+Pour les rapports d’anomalie, utiliser @kbd{M-x report-emacs-bug}.
+
+@insertcopying
+
+@menu
+* Boniment: Sales Pitch.        Pourquoi utiliser @acronym{SES}?
+* Tuto: Quick Tutorial.         Une introduction sommaire
+* Les bases: The Basics.        Les commandes de base du tableur
+* Fonctions avancées: Advanced Features. Vous voulez en savoir plus ?
+* Pour les gourous: For Gurus.  Vous voulez en savoir @emph{encore plus} ?
+* Index: Index.                Index des concepts, fonctions et variables
+* Remerciements: Acknowledgments. Remerciements
+* Licence GNU pour la documentation libre: GNU Free Documentation License. La 
licence de cette documentation.
+@end menu
+
+@c ===================================================================
+
+@node Sales Pitch
+@comment  node-name,  next,  previous,  up
+@chapter Boniment
+@cindex features
+
+@itemize --
+@item Créer et éditer des feuilles de calcul avec un minimum de tracas.
+@item Prise en charge complète du Défaire/Refaire/Sauvegarde auto.
+@item Protection contre les virus enfouis dans les feuilles de calcul.
+@item Les formules de cellule sont directement du code Emacs Lisp.
+@item Fonctions d’impression pour contrôler l’apparence des cellules.
+@item Raccourcis clavier intuitifs : C-o = insérer une ligne, M-o = insérer 
une colonne, etc.
+@item « Débordement » des valeurs de cellule longues dans les cellules vides 
suivantes.
+@item La ligne d’en-tête montre les lettres désignant les colonnes.
+@item Autocomplétion pour la saisie des symboles de cellules nommées lors de 
la saisie des formules.
+@item Couper, copier et coller peut transferer les formules et les fonctions 
d’impression.
+@item Import and export de valeurs séparées par des tabulations, ou de 
formules séparées par des tabulations.
+@item Format de fichier en texte, facile à bidouiller.
+@end itemize
+
+@c ===================================================================
+
+@node Quick Tutorial
+@chapter Tuto
+@cindex introduction
+@cindex tuto
+
+Si vous désirez être rapidement lancé et pensez que vous savez ce que
+vous attendez d’un tableur simple, alors ce chapitre peut être tout ce
+dont vous avez besoin.
+
+Premièrement, visitez un nouveau fichier avec pour extension de nom de
+fichier @file{.ses}.  Emacs vous présente alors une feuille de calcul
+vide contenant une seule cellule.
+
+Commencez par saisir une ligne d’en-tête : @kbd{"Revenu@key{RET}}. Le
+guillemet double @code{"} indique que vous saisissez une cellule
+textuelle, il ne fait pas partie de la valeur de la cellule, et aucun
+guillemet de fermeture n’est nécessaire.
+
+Pour insérer votre première valeur de revenu, vous devez d’abord
+redimensionner la feuille. Appuyer sur la touche @key{TAB} pour
+ajouter une nouvelle cellule et revenez à elle en remontant.
+Saisissez un nombre, tel que @samp{2.23}.  Puis continuer pour ajouter
+quelques valeurs supplémentaires de revenu, par ex. :
+
+@example
+@group
+A
+ Revenu
+   2.23
+   0.02
+  15.76
+  -4.00
+@end group
+@end example
+
+Pour additionner les valeurs entre elles, saisissez une expression
+Lisp :
+
+@example
+(+ A2 A3 A4 A5)
+@end example
+
+Peut-être désirez vous ajouter une cellule à la droite de la cellule
+@samp{A4} pour expliquer pourquoi vous avez une valeur négative.  En
+appuyant sur @kbd{TAB} dans cette cellule vous ajouter entièrement une
+nouvelle colonne @samp{B} où vous pourrez ajouter une telle note.
+
+La colonne est assez étroite par défaut, mais en appuyant sur @kbd{w}
+vous pouvez la redimensionner selon vos besoins.  Faites la de 22
+caractères de large.  Vous pouvez maintenant ajoutez des notes
+descriptives pour chacune des cases, par ex.@: :
+
+@example
+@group
+A       B
+ Revenu
+   2.23  Frais de consultation
+   0.02       Opinion informée
+  15.76         Stand limonade
+     -4          Prêt à Joseph
+  14.01                  Total
+@end group
+@end example
+
+Par défaut, l’impression des valeurs de cellule se fait alignée à
+droite, c’est la raison d’un tel alignement pour les notes dans la
+colonne @samp{B}.  Pour changer cela, vous pouvez saisir une fonction
+d’impression pour la colonne entière, en utilisant par ex. @kbd{M-p
+("%s")}. Le fait que @code{"%s"} soit contenu dans une liste indique à
+@acronym{SES} que l’alignement est à faire à gauche.  Vous pouvez
+l’emporter sur la fonction d’impression de colonne pour l’une
+quelconque de ses cellules en donnant une fonction d’impression par
+cellule avec @kbd{p}.
+
+Vous pouvez nommer une fonction d’impression, et utiliser le nom de la
+fonction à la place de sa définition, de sorte à faciliter la
+modification de l’impression de toutes les cellules utilisant cette
+fonction. Par exemple tapez @kbd{M-x
+ses-define-local-printer@key{ret}}, puis @kbd{note@key{ret}}, puis
+@kbd{("%s")} pour définir une fonction d’impression nommée @code{note}
+dont la définition est @code{("%s")}, puis sur la colonne @samp{B} tapez
+@kbd{M-p note@key{ret}}
+
+@example
+@group
+A       B
+ Revenu
+   2.23 Frais de consultation
+   0.02 Opinion informée
+  15.76 Stand limonade
+     -4 Prêt à Joseph
+  14.01 Total
+@end group
+@end example
+
+Si maintenant vous redéfinissez @code{note} avec pour nouvelle
+définition @kbd{("*%s")} qui ajoute un astérisque @code{*} devant le
+texte, la zone d’impression est modifiée ainsi :
+@example
+@group
+A       B
+ Revenu
+   2.23 *Frais de consultation
+   0.02 *Opinion informée
+  15.76 *Stand limonade
+     -4 *Prêt à Joseph
+  14.01 *Total
+@end group
+@end example
+
+Notez que la cellule @samp{B1} reste affichée vide et n’est pas
+affichée comme @samp{*}. C’est parce que la valeur de la cellule est
+@code{nil}, et que les fonctions d’impression définies à partir d’une
+chaîne de formatage comme @code{"%s"} dans @code{("%s")} impriment
+systématiquement @code{nil} comme une chaîne vide, et tentent
+d’imprimer toute valeur non-@code{nil} en utilisant la fonction
+standarde @code{format} avec la chaîne de formatage, et si cela
+échoue, utilisent la fonction de repli @code{ses-prin1} la place.
+
+Si maintenant Joseph rembourse son prêt, vous pourriez effacer cette
+case ; par ex.@: en positionnant le curseur sur la cellule A5 et en
+appuyant sur @kbd{C-d}.  Si vous faites celle le total imprimé dans la
+cellule A6 affichera @samp{######}.  La raison de cela est la valeur
+dans une cellule vide est typiquement @code{nil} et que l’opérateur
+@code{+} ordinaire échoue à gérer une telle valeur. Au lieu de vider
+la cellule, vous pourriez littéralement saisir @samp{0}, ou supprimer
+entièrement la ligne en utilisant @kbd{C-k}.  Une alternative est
+d’utiliser la fonction spéciale @code{ses+} au lieu du @code{+}
+ordinaire :
+
+@example
+(ses+ A2 A3 A4 A5)
+@end example
+
+Pour rendre une formule robuste au changement de géométrie de la
+feuille, vous pouvez utiliser la macro @code{ses-range} pour faire
+référence à une plage de cellules par ses extrémités, par ex. :
+
+@example
+(apply 'ses+ (ses-range A2 A5))
+@end example
+
+(Le @code{apply} est nécessaire parce que @code{ses-range} produite
+une @emph{liste} de valeurs, ce qui ouvre des possibilités plus
+complexes).
+
+Alternativement vous pouvez utiliser le modificateur @code{!} de
+@code{ses-range} pour retirer les cellules vides de la liste renvoyée,
+ce qui permet d’utiliser @code{+} au lieu de @code{ses+}:
+
+@lisp
+(apply '+ (ses-range A2 A5 !))
+@end lisp
+
+@c ===================================================================
+
+@node The Basics
+@comment  node-name,  next,  previous,  up
+@chapter Les bases
+@cindex commandes de base
+@cindex base, commandes de
+@findex ses-jump
+@findex ses-mark-row
+@findex ses-mark-column
+@findex ses-mark-whole-buffer
+@findex set-mark-command
+@findex keyboard-quit
+
+Pour créer une nouveau tableur, visitez un fichier inexistant dont le
+nom se termine en @file{.ses}.  Par exemple, @kbd{C-x C-f essai.ses
+@key{ret}}.
+
+
+Un @dfn{identificateur de cellule} est un symbole avec une lettre de
+colonne et un numéro de ligne.  La cellule B7 est la 2e column de la
+7e ligne.  Pour les feuilles très larges, il ya deux lettres de
+colonne : la cellule AB7 les la 28e colonne de la 7e ligne. Les
+feuilles encore plus larges ont AAA1, etc.  On se déplace avec les
+commandes ordinaires de déplacement d’Emacs.
+
+@table @kbd
+@item j
+Déplace le point vers la cellule spécifiée par identificateur
+(@code{ses-jump}). À moins que la cellule ne soit une cellule
+renommée, l’identificateur est insensible à la casse. Un argument
+préfixe @math{n} déplace vers la cellule de coordonnées @math{(n\div
+R, n \% C)} pour une feuille de @math{R} ligne et @math{C} colonnes,
+et @samp{A1} étant aux coordonnées @math{(0,0)}. La façon dont
+l’identificateur ou l’argument préfixe de commande sont interprétés
+peut être personnalisée via les variables
+@code{ses-jump-cell-name-function} et @code{ses-jump-prefix-function}.
+@end table
+
+Le Point est toujours sur le bord de gauche d’une cellule, ou à la fin
+de ligne vide. Quand la marque est inactive, la cellule courante est
+soulignée.  Quand la marque est active, la plage est le rectangle de
+cellules mis en vedette (@acronym{SES} utilise toujours le mode de
+marque transitoire).  Faire glisser la souris de @samp{A1} à @samp{A3}
+crée la plage @samp{A1-A2}.  Beaucoup de commandes @acronym{SES}
+opèrent seulement sur une seule cellule, et non sur une plage.
+
+@table @kbd
+@item C-@key{SPC}
+@itemx C-@@
+Règle la marque au point (@code{set-mark-command}).
+
+@item C-g
+Désactive la marque (@code{keyboard-quit}).
+
+@item M-h
+Met en vedette la ligne courante (@code{ses-mark-row}).
+
+@item S-M-h
+Met en vedette la colonne courante (@code{ses-mark-column}).
+
+@item C-x h
+Mettre en vedette toutes les cellules (@code{mark-whole-buffer}).
+@end table
+
+@menu
+* Formules: Formulas.
+* Redimensionner: Resizing.
+* Fonctions d’impression: Printer functions.
+* Effacer des cellules: Clearing cells.
+* Copier/couper/coller: Copy/cut/paste.
+* Personnaliser @acronym{SES}: Customizing @acronym{SES}.
+@end menu
+
+@node Formulas
+@section Formules de cellule
+@cindex formules
+@cindex formules, saisire
+@cindex valeurs
+@cindex valeurs de cellule
+@cindex éditer des cellules
+@findex ses-read-cell
+@findex ses-read-symbole
+@findex ses-edit-cell
+@findex ses-recalculate-cell
+@findex ses-recalculate-all
+
+Pour insérer une valeur dans une cellule, tapez juste une expression
+numérique, un @samp{"texte entre guillemets anglais"}, ou une
+expression Lisp.
+
+@table @kbd
+@item 0..9
+Auto-insérer un nombre (@code{ses-read-cell}).
+
+@item -
+Auto-insérer un nombre négatif (@code{ses-read-cell}).
+
+@item .
+Auto-insérer un nombre décimal (@code{ses-read-cell}).
+
+@item "
+Auto-insérer une chaîne de caractères.  Le guillemet anglais de
+terminaison est inséré automatiquement (@code{ses-read-cell}).
+
+@item (
+Auto-insérer une expression.  La parenthèse de droite est insérée
+automatiquement (@code{ses-read-cell}).  Pour accéder à la valeur
+d’une autre cellule, il suffit d’utiliser son identificateur dans
+votre expression.  Dès que l’autre cellule change, la formule de cette
+cellule-ci est réévaluée.  En tapant l’expression, vous pouvez
+utiliser les raccourcis clavier suivants :
+@table @kbd
+@item M-@key{TAB}
+pour compléter les noms de symboles, et
+@item  C-h C-n
+pour lister les symboles de cellules renommées dans un tampon d’aide.
+@end table
+
+@item ' @r{(apostrophe)}
+Entrer un symbole (@code{ses-read-symbol}).  @acronym{SES} se souvient
+de tous les symboles qui ont été utilisés comme formules, de sorte que
+vous pouvez taper juste le début d’un symbole et utiliser
+@kbd{@key{SPC}}, @kbd{@key{TAB}}, et @kbd{?} pour le compléter.
+@end table
+
+Pour saisire quelque-chose d’autre (par ex., un vecteur), commencer
+avec un chiffre, puis effacer le chiffre et tapez ce que vous désirez.
+
+@table @kbd
+@item @key{RET}
+Édite la formule existante dans la cellule courante (@code{ses-edit-cell}).
+
+@item C-c C-c
+Force le  recalcul de la  cellule ou plage courante 
(@code{ses-recalculate-cell}).
+
+@item C-c C-l
+Recalcule la feuille entière (@code{ses-recalculate-all}).
+@end table
+
+@node Resizing
+@section Redimensionner la feuille
+@cindex redimensionner des feuilles
+@cindex dimensions
+@cindex ligne,  ajout ou suppression
+@cindex colonne, ajout ou suppression
+@cindex ajouter des lignes ou colonnes
+@cindex insérer des lignes ou colonnes
+@cindex enlever des lignes ou colonnes
+@cindex supprimer des lignes ou colonnes
+@findex ses-insert-row
+@findex ses-insert-column
+@findex ses-delete-row
+@findex ses-delete-column
+@findex ses-set-column-width
+@findex ses-forward-or-insert
+@findex ses-append-row-jump-first-column
+
+
+Commande de base :
+
+@table @kbd
+@item C-o
+(@code{ses-insert-row})
+
+@item M-o
+(@code{ses-insert-column})
+
+@item C-k
+(@code{ses-delete-row})
+
+@item M-k
+(@code{ses-delete-column})
+
+@item w
+(@code{ses-set-column-width})
+
+@item @key{TAB}
+Déplace le point sur la prochaine cellule vers la droite, ou insère
+une nouvelle colonne si on est déjà sur la dernière cellule de la
+ligne, ou insère une nouvelle ligne si on est sur la ligne de
+terminaison (@code{ses-forward-or-insert}).
+
+@item C-j
+Insère une nouvelle ligne sous la ligne courante et va à la colonne A
+de cette ligne (@code{ses-append-row-jump-first-column}).
+@end table
+
+En redimensionnant la feuille (à moins que vous ne fassiez que changer
+la largeur d’une colonne) les références de cellule au sein des
+formules sont toutes relocalisées de sorte à continuer à faire
+référence aux mêmes cellules.  Si une formule mentionne B1 et que vous
+insérez une nouvelle première ligne, alors la formule mentionnera B2.
+
+Si vous supprimez une cellule à laquelle une formule fait référence,
+le symbole de cellule est supprimé de la formule, de sorte que
+@code{(+ A1 B1 C1)} après suppression de la troisième colonne devient
+@code{(+ A1 B1)}.  Au cas où cela ne serait pas ce que vous désiriez :
+
+@table @kbd
+@item C-_
+@itemx C-x u
+Défait l’action action précédente (@code{(undo)}).
+@end table
+
+
+@node Printer functions
+@section Fonctions d’impression
+@cindex fonctions d’impression
+@cindex formatage de cellule
+@cindex cellules, formater
+
+Les fonctions d’impression convertissent des valeurs binaires de
+cellule en formes d’impression qu’Emacs affiche à l’écran.
+
+@menu
+* Différents types de fonctions d’impression: Various kinds of printer 
functions.
+* Configurer quelle fonction d’impression s’applique: Configuring what printer 
function applies.
+* Les fonctions d’impression standardes: Standard printer functions.
+* Les fonctions d’impression locales: Local printer functions.
+* Écrire une fonctions d’impression lambda: Writing a lambda printer function.
+@end menu
+
+@node Various kinds of printer functions
+@subsection Différents types de fonctions d’impression
+
+Lorsque on configure quelle fonction d’impression s’applique
+(@pxref{Configuring what printer function applies}), on peut saisir
+une fonction d’impression comme l’une des possibilités suivantes :
+
+@itemize
+@item
+Une chaîne de formatage, telle que @samp{"$%.2f"}.  la chaîne formatée
+résultante est alignée à droite au sein de la cellule
+d’impression. Pour obtenir un alignement à gauche, utilisez des
+parenthèses : @samp{("$%.2f")}.
+@item
+Une fonction d’impression peut aussi être une fonction à un argument
+dont la valeur renvoyée est une chaîne (pour obtenir un alignement à
+droite) ou une liste d’une chaîne (pour obtenir un alignement à
+gauche). Une telle fonction peut à son tour être configurée comme :
+@itemize
+@item
+Une expression lambda, par exemple :
+
+@lisp
+(lambda (x)
+  (cond
+     ((null x) "")
+     ((numberp x) (format "%.2f" x))
+     (t (ses-center-span x ?# 'ses-prin1))))
+@end lisp
+
+Pendant la saisie d’une lambda, vous pouvez utiliser @kbd{M-@key{TAB}}
+pour completer les noms de symboles.
+@item
+Un symbole faisant référence à une fonction d’impression standarde
+(@pxref{Standard printer functions}).
+@item
+Un symbole faisant référence à une fonction d’impression locale
+(@pxref{Local printer functions}).
+@end itemize
+
+
+@end itemize
+
+
+@node Configuring what printer function applies
+@subsection Configurer quelle fonction d’impression s’applique
+
+Chaque cellule a une fonction d’impression.  Si c’est @code{nil},
+alors la fonction d’impression de la colonne de cette cellule est
+utilisée. Et si cela est aussi @code{nil}, alors la fonction
+d’impression par défaut de la feuille est utilisée.
+
+@table @kbd
+@item p
+@findex ses-read-cell-printer
+Saisit une fonction d’impression pour la cellule ou plage courante
+(@code{ses-read-cell-printer}).
+
+@item M-p
+@findex ses-read-column-printer
+Saisit une fonction d’impression pour la colonne courante 
(@code{ses-read-column-printer}).
+
+@item C-c C-p
+@findex ses-read-default-printer
+Saisit la fonction d’impression par défaut de la feuille
+(@code{ses-read-default-printer}).
+@end table
+
+Les commandes @code{ses-read-@var{xxx}-printer} permettent les commandes
+suivantes pendant l’édition:
+
+@table @kbd
+@item @key{arrow-up}
+@itemx @key{arrow-down}
+Pour parcourir l’historique : les commandes
+@code{ses-read-@var{xxx}-printer} ont leur propre historique de
+mini-tampon, il est préchargé avec l’ensemble de toutes les fonctions
+d’impression utilisées dans cette feuille, plus les fonctions
+d’impression standardes (@pxref{Standard printer functions}) et les
+fonctions d’impression locales (@pxref{Local printer functions}).
+@item @key{TAB}
+Pour compléter les symboles de fonctions d’impression locales, et
+@item C-h C-p
+Pour lister les fonctions d’impression locales dans un tampon d’aide.
+@end table
+
+
+@node Standard printer functions
+@subsection Les fonctions d’impression standardes
+
+
+Mise à part @code{ses-prin1}, les autres fonctions d’impression
+standardes ne conviennent que pour les cellules, et non pour les
+colonnes ou comme fonction d’impression par défaut de la feuille,
+parce qu’elles formatent la valeur en utilisant la fonction
+d’impression de colonne (ou par défaut si @code{nil}) et ensuite
+post-traite le résultat, par ex.@: le centre :
+
+@ftable @code
+@item ses-center
+Centre juste.
+
+@item ses-center-span
+Centrer en débordant sur les cellules vides suivantes.
+
+@item ses-dashfill
+Centrer en utilisant des tirets (@samp{-}) au lieu d’espaces.
+
+@item ses-dashfill-span
+Centrer avec tirets et débordement.
+
+@item ses-tildefill-span
+Centrer avec tildes (@samp{~}) et débordement.
+
+@item ses-prin1
+C’est la fonction d’impression de repli, utilisée quand l’appel à la
+fonction d’impression configurée envoie une erreur.
+@end ftable
+
+@node Local printer functions
+@subsection Les fonctions d’impression locales
+
+@findex ses-define-local-printer
+Vous pouvez définir une fonction d’impression locale à la feuille avec
+la commande @code{ses-define-local-printer}.  Par exemple, définissez
+une fonction d’impression @samp{toto} à @code{"%.2f"}, et ensuite
+utilisez le symbole @samp{toto} comme fonction d’impression.  Ensuite,
+si vous rappelez @code{ses-define-local-printer} sur @samp{toto} pour
+le redéfinir comme @code{"%.3f"}, alors toutes les cellules utilisant
+la fonction d’impression @samp{toto} seront re-imprimées conformément.
+
+Il peut arriver que vous désiriez définir ou redéfinir certaines
+fonctions d’impression à chaque fois que vous ouvrez une feuille. Par
+exemple, imaginez que vous désiriez définir/re-définir automatiquement
+une fonction d’impression locale @code{euro} pour afficher un nombre
+comme une somme en euros, par exemple le nombre @code{3.1} serait
+affiché comme @code{3.10@dmn{}@euro{}}. Pour faire cela dans tout
+tampon SES qui n’est pas en lecture seule, vous pouvez ajouter ce
+genre de code à votre fichier d’init @file{.emacs} :
+
+@lisp
+(defun my-ses-mode-hook ()
+  (unless buffer-read-only
+    (ses-define-local-printer
+     'euro
+     (lambda (x)
+       (cond
+        ((null x) "")
+        ((numberp x) (format "%.2f€" x))
+        (t (ses-center-span x ?# 'ses-prin1)))))))
+(add-hook 'ses-mode-hook 'my-ses-mode-hook)
+@end lisp
+
+Si vous remplacez la commande @code{ses-define-local-printer} par la
+fonction @code{ses-define-if-new-local-printer}
+@findex ses-define-if-new-local-printer
+la définition ne se produira que si aucune fonction d’impression de
+même nom n’est déjà définie.
+
+
+@node Writing a lambda printer function
+@subsection Écrire une fonctions d’impression lambda
+
+Vous pouvez écrire une fonction d’impression avec une expression
+lambda prenant un seul argument en deux cas :
+
+@itemize
+@item
+quand vous configurez la fonction d’impression s’appliquant à
+une cellule ou colonne, ou
+@item
+quand vous définissez une fonction d’impression avec la commande
+@code{ses-define-local-printer}.
+@end itemize
+
+En faisant cela, prenez garde à ce que la valeur renvoyée soit une
+chaîne, ou une liste contenant une chaîne, même quand l’argument
+d’entrée a une valeur inattendue. Voici un exemple :
+
+@example
+(lambda (val)
+   (cond
+      ((null val) "")
+      ((and (numberp val) (>= val 0)) (format "%.1f" val))
+      (t (ses-center-span val ?# 'ses-prin1))))
+@end example
+
+Cet exemple fait ceci :
+
+@itemize
+@item
+Quand la cellule est vide (c.-à-d.@: quand @code{val} est @code{nil}),
+imprime une chaîne vide @code{""}
+@item
+Quand la valeur de cellule est un nombre positif ou nul, formate la
+valeur en notation à virgule fixe avec une decimale après la virgule
+@item
+Sinon, gère la valeur comme erronnée en l’imprimant comme une
+s-expression (avec @code{ses-prin1}), centrée et entourée de
+croisillons @code{#} de bourrage.
+@end itemize
+
+Une autre précaution à prendre est d’éviter un débordement de pile à
+cause d’une fonction d’impression se rappelant elle-même sans
+fin. Cette erreur peut se produire quand vous utilisez une fonction
+d’impression locale comme fonction d’impression de colonne, et que
+cette fonction d’impression locale appelle implicitement la fonction
+d’impression de colonne courante, ainsi elle se rappelle elle-même
+récursivement. Imaginez par exemple que vous désirez créer une
+fonction d’impression locale @code{=bourre} qui centre le contenu
+imprimé d’une cellule et l’entoure de signes égal @code{=}, et que
+vous le faites (erronnément) comme cela :
+
+@lisp
+;; CODE ERRONÉ
+(lambda (x)
+  (cond
+   ((null x) "")
+   (t (ses-center x 0 ?=))))
+@end lisp
+
+Comme @code{=bourre} utilise la fonction d’impression standarde
+@code{ses-center} mais sans lui passer exemplicitement une fonction
+d’impression, @code{ses-center} appelle la fonction d’impression de
+colonne courante s’il y en a une, ou la fonction d’impression par
+défaut de la feuille sinon. Aussi, utiliser @code{=bourre} comme
+fonction d’impression de colonne aura pour résultat de causer un
+débordement de pile dans cette colonne sur toute cellule non vide,
+puisque @code{ses-center} rappelle récursivement la fonction qui l'a
+appelé.  @acronym{SES} ne vérifie pas cela ; il vous faut donc faire
+attention.  Par exemple, reécrivez @code{=bourre} ainsi :
+
+@lisp
+(lambda (x)
+  (cond
+   ((null x) "")
+   ((stringp x) (ses-center x 0 ?= " %s "))
+   (t (ses-center-span x ?# 'ses-prin1))))
+@end lisp
+
+Le code ci-dessus est réparé au sens où @code{ses-center} et
+@code{ses-center-span} sont toutes deux appelées avec un dernier
+argument @var{printer} explicite spécifiant la fonction d'impression,
+respectivement @code{" %s "} et @code{'ses-prin1}.
+
+
+Le code ci-dessus applique le bourrage de @code{=} seulement aux
+chaînes ; et aussi il entoure la chaîne par un espace de chaque côté
+avant de bourrer avec des signes @code{=}.  Ainsi la chaîne @samp{Ula}
+s’affichera comme @samp{@w{=== Ula ===}} dans une colonne large de 11
+caractères.  Toute valeur qui n’est ni @code{nil} (c.-à-d.@: une
+cellule vide) ni une chaîne est affichée comme une erreur par l’usage
+de bourrage par des croisillons @code{#}.
+
+@node Clearing cells
+@section Effacer des cellules
+@cindex effacer, commandes
+@findex ses-clear-cell-backward
+@findex ses-clear-cell-forward
+
+Ces commandes règlent à la fois la formule et la fonction d’impression
+à @code{nil} :
+
+@table @kbd
+@item @key{DEL}
+Se deplace à gauche et efface la cellule (@code{ses-clear-cell-backward}).
+
+@item C-d
+Efface la cellule et se déplace à droite (@code{ses-clear-cell-forward}).
+@end table
+
+
+@node Copy/cut/paste
+@section Copier, couper, et coller
+@cindex copier
+@cindex couper
+@cindex coller
+@findex kill-ring-save
+@findex mouse-set-region
+@findex mouse-set-secondary
+@findex ses-kill-override
+@findex yank
+@findex clipboard-yank
+@findex mouse-yank-at-click
+@findex mouse-yank-at-secondary
+@findex ses-yank-pop
+
+Les fonctions de copie opèrent sur des regions rectangulaires de
+cellules.  Vous pouvez coller les copies dans des tampons
+non-@acronym{SES} pour exporter le texte d’impression.
+
+@table @kbd
+@item M-w
+@itemx [copy]
+@itemx [C-insert]
+Copie les cellules en vedette vers l’anneau presse-papier et le
+presse-papier primaire (@code{kill-ring-save}).
+
+@item [drag-mouse-1]
+Marque une region et la copie vers l’anneau presse-papier et le
+presse-papier primaire (@code{mouse-set-region}).
+
+@item [M-drag-mouse-1]
+Marque une region et la copie vers l’anneau presse-papier et le
+presse-papier secondaire (@code{mouse-set-secondary}).
+
+@item C-w
+@itemx [cut]
+@itemx [S-delete]
+Les fonctions couper ne suppriment pas en fait de lignes ou de
+colonnes --- elles les copient et puis les effacent
+(@code{ses-kill-override}).
+
+@item C-y
+@itemx [S-insert]
+Colle à partir de l’anneau presse-papier (@code{yank}).  Les fonctions
+coller se comportent différemment selon le format du texte qu’elles
+insèrent :
+@itemize @bullet
+@item
+Quand on colle des cellules qui ont été coupées ou copiées à partir
+d’un tampon @acronym{SES}, le texte d’impression est ignoré et
+seulement la formule et fonction d’impression jointes sont insérées ;
+les références de cellule de la formule sont relocalisées à moins que
+vous n’utilisiez @kbd{C-u}.
+@item
+Le texte collé écrase un rectangle de cellules dont le coin haut
+gauche est la cellule courante.  Si une partie du rectangle est
+au-délà des bords de la feuille, vous devez confirmer l’augmentation
+de la taille de la feuille.
+@item
+Du texte Non-@acronym{SES} est d’ordinaire inséré comme formule de
+remplacement pour la cellule courante.  Si la formule serait un
+symbole, elle est traitée comme une chaîne à moins que vous
+n’utilisiez @kbd{C-u}.  Les formules collées comprenant des erreurs de
+syntaxe sont toujours traitées comme des chaînes.
+@end itemize
+
+@item [paste]
+Colle à partir du presse-papier primaire ou de l’anneau presse-papier
+(@code{clipboard-yank}).
+
+@item [mouse-2]
+Règle le point et colle à partir du presse-papier primaire
+(@code{mouse-yank-at-click}).
+
+@item [M-mouse-2]
+Règle le point et colle à partir du presse-papier secondaire
+(@code{mouse-yank-secondary}).
+
+@item M-y
+Immédiatement après un coller, vous pouvez remplacer le texte avec un
+élément précédent à partir de l’anneau presse-papier
+(@code{ses-yank-pop}).  Contrairement au yank-pop standard d’Emacs, la
+version de @acronym{SES} utilise @code{undo} pour supprimer l’ancien
+collage.  Est-ce que cela ne fait aucune différence ?
+@end table
+
+@node Customizing @acronym{SES}
+@section Personnaliser @acronym{SES}
+@cindex personnaliser
+@vindex enable-local-eval
+
+Par défaut, une feuille venant d’être créée a 1 ligne et 1 colonne.
+La largeur de colonne est 7 et la fonction d’impression par défaut est
+@samp{"%.7g"}.  Chacune de ces choses peut être personnalisée.  Allez
+voir dans le groupe « ses ».
+
+Après avoir saisi une valeur de cellule, normalement
+@code{forward-char} est appelé, ce qui déplace le point vers la
+cellule suivante à droite, ou à la première cellule à gauche de la
+ligne suivante si la cellule courante est la plus à droite de la
+feuille.  Vous pouvez personnaliser @code{ses-after-entry-functions}
+pour que le déplacement soit vers la gauche ou le haut ou le bas.
+Pour un mouvement diagonal, selectionnez deux fonctions de la liste.
+
+@vindex ses-jump-cell-name-function
+@code{ses-jump-cell-name-function} est une variable personnalisable
+réglée par défaut à la fonction @code{upcase}. Cette fonction est
+appelée quand vous passez un nom de cellule à la commande
+@command{ses-jump} (@kbd{j}), et que ce nom n’est pas le nom d’une
+cellule renommée. Elle change le nom de cellule saisi en celui de la
+cellule vers laquelle sauter. Le réglage par défaut @code{upcase} vous
+permet de saisir le nom de cellule en bas de casse. Un autre usage de
+@code{ses-jump-cell-name-function} pourrait être une
+internationalisation pour convertir des caractères non latins en
+équivalents latins pour nommer la cellule. Au lieu d’un nom de
+cellule, la fonction peut renvoyer des coordonnées de cellule sous la
+forme d’un cons, par exemple @code{(0 . 0)} pour la cellule @code{A1},
+@code{(1 . 0)} pour la cellule @code{A2}, etc.
+
+@vindex ses-jump-prefix-function
+@code{ses-jump-prefix-function} est une variable personnalisable
+réglée par défaut à la fonction @code{ses-jump-prefix}. Cette fonction
+est appelée quand vous donnez un argument préfixe à la commande
+@command{ses-jump} (@kbd{j}). Elle renvoie un nom de cellule ou des
+coordonnées de cellule correspondant à l’argument préfixe. Les
+coordonnées de cellule sont sous la forme d’un cons, par exemple
+@code{(1 . 0)} pour la cellule @code{A2}. Le réglage par défaut
+@code{ses-jump-prefix} numérote les cellules de gauche à droite et
+puis de haut en bas, de sorte que si on suppose une feuille 4×3,
+l’argument préfixe @samp{0} saute à la cellule @samp{A1}, l’argument
+préfixe @samp{2} saute à @samp{C1}, l’argument préfixe @samp{3} saute
+à @samp{A2}, etc.
+
+@vindex ses-mode-hook
+@code{ses-mode-hook} est un crochet de mode normal (une liste de
+fonctions qui s’exécutent quand le mode @acronym{SES} démarre sur un
+tampon).
+
+@vindex safe-functions
+La variable @code{safe-functions} est une liste de fonctions
+potentiellement risquées à traiter comme si elles étaient sûres lors
+de l’analyse des formules et fonctions d’impression.  @xref{Virus
+protection}.  Avant de personnaliser @code{safe-functions},
+réfléchissez à quel point vous faites confiance à la personne qui vous
+suggère cette modification.  La valeur @code{t} désactive toute
+protection anti-virus.  Une valeur donnant une liste-de-fonctions peut
+rendre une feuille « trop bien », mais elle crée aussi des portes
+dérobées dans votre armure anti-virus.  Pour que votre protection
+contre les virus fonctionne, vous devez toujours appuyer sur @kbd{n}
+quand un avertissement contre un virus vous est présenté, à moins que
+vous compreniez ce que le code en question essaie de faire. N’écoutez
+pas ceux qui vous racontent de personnaliser @code{enable-local-eval}
+--- cette variable est pour les gens qui ne portent pas de ceinture de
+sécurité !
+
+
+@c ===================================================================
+
+@node Advanced Features
+@chapter Fonctions avancées
+@cindex avancées, fonctions
+@findex ses-read-header-row
+
+
+@table @kbd
+@item C-c M-C-h
+(@code{ses-set-header-row}).
+@findex ses-set-header-row
+@kindex C-c M-C-h
+La ligne d’en-tête au sommet de la fenêtre @acronym{SES} affiche
+normalement la ligne de colonne pour chaque colonne. Vous pouvez la
+régler pour afficher une copie de l’une des lignes, tell que qu’une
+ligne de titres de colonnes, ainsi cette ligne sera toujours visible.
+Par défaut la commande règle la ligne courante comme en-tête ;
+utiliser C-u pour une invite à désigner la ligne d’en-têre.  Régler la
+ligne d’en-tête à la ligne 0 pour afficher les lettres de colonne de
+nouveau.
+@item [header-line mouse-3]
+Affiche un menu pour régler la ligne courante comme en-tête, ou
+revenir à des lettres de colonne.
+@item M-x ses-rename-cell
+@findex ses-rename-cell
+Renomme une cellule pour passer d'un nom standard du genre de A1 à
+toute chaîne pouvant être un nom valide pour une variable locale (Voir
+aussi @ref{Nonrelocatable references}).
+@item M-x ses-repair-cell-reference-all
+@findex ses-repair-cell-reference-all
+Quand vous interrompez la mise à jour d’une formule de cellule en
+tapant @kbd{C-g}, alors cela peut casser le lien de référence de
+cellule, ce qui compromet la mise à jour automatique de cellule quand
+toute autre cellule dont elle dépend est modifiée. Pour réparer cela,
+utilisez la fonction @code{ses-repair-cell-reference-all}
+@end table
+
+@menu
+* La zone d’impression:  The print area.
+* Plages dans les formules:  Ranges in formulas.
+* Trier par colonne:  Sorting by column.
+* Fonctions de formule standardes:  Standard formula functions.
+* Plus sur l’impression de cellule:  More on cell printing.
+* Import et export:  Import and export.
+* Protection contre les virus:  Virus protection.
+* Feuilles avec détails et synthèse:  Spreadsheets with details and summary.
+@end menu
+
+@node The print area
+@section La zone d’impression
+@cindex zone d’impression
+@cindex impression, zone d’
+@findex widen
+@findex ses-renarrow-buffer
+@findex ses-reprint-all
+
+Un fichier @acronym{SES} consiste en une zone d’impression et une zone
+de données.  Normalement le tampon est réduit de sorte à n’afficher
+que la zone d’impression. La zone d’impression est en lecture seule,
+hormis pour les commandes spéciales de @acronym{SES} ; elle contient
+les valeurs de cellule formatées par les fonctions d’impression.  La
+zone de données enregistre les formules, fonctions d’impression, etc.
+
+@table @kbd
+@item C-x n w
+Affiche à la fois les zones d’impression et de données (@code{widen}).
+
+@item C-c C-n
+Affiche seulement la zone d’impression (@code{ses-renarrow-buffer}).
+
+@item S-C-l
+@itemx M-C-l
+Recrée la zone d’impression en réévaluant pour toutes les cellules sa
+fonction d’impression (@code{ses-reprint-all}).
+@end table
+
+@node Ranges in formulas
+@section Plages dans les formules
+@cindex plages
+@findex ses-insert-plage-click
+@findex ses-insert-plage
+@findex ses-insert-ses-plage-click
+@findex ses-insert-ses-plage
+@vindex de
+@vindex à
+
+Une formule du genre de :
+@lisp
+(+ A1 A2 A3)
+@end lisp
+est la somme de trois cellules spécifiques.  Si vous insérez une
+nouvelle deuxième ligne, la formule devient
+@lisp
+(+ A1 A3 A4)
+@end lisp
+et la nouvelle ligne n’est pas incluse dans la somme.
+
+La macro @code{(ses-range @var{de} @var{à})} s’évalue en une liste des
+valeurs dans un rectangle de cellules.  Si votre formule est
+@lisp
+(apply '+ (ses-range A1 A3))
+@end lisp
+et que vous insérez une nouvelle deuxième ligne, elle devient
+@lisp
+(apply '+ (ses-range A1 A4))
+@end lisp
+et la nouvelle ligne est incluse dans la somme.
+
+Alors que vous saisissez ou éditez une formule dans le minitampon,
+vous pouvez sélectionner une plage dans la feuille (en utilisant la
+souris ou le clavier), et injecter une représentation de cette plage
+dans votre formule. Supposez que vous sélectionnez @samp{A1-C1} :
+
+@table @kbd
+@item [S-mouse-3]
+Insère @samp{A1 B1 C1} (@code{ses-insert-range-click})
+
+@item C-c C-r
+Version clavier (@code{ses-insert-range}).
+
+@item [C-S-mouse-3]
+Insère @samp{(ses-range A1 C1)} (@code{ses-insert-ses-range-click}).
+
+@item C-c C-s
+Version clavier (@code{ses-insert-ses-range}).
+@end table
+
+Si vous supprimez la cellule @var{de} ou @var{à} d’une plage, la
+cellule la plus proche toujours existante est utilisée à la place.  Si
+vous supprimez l’entière plage, le relocalisateur de formule supprime
+le @samp{ses-range} de la formule.
+
+Si vous insérez une nouvelle ligne juste au delà de la fin d’une plage
+à une colonne, ou une nouvelle colonne juste au delà d’une plage à une
+ligne, la nouvelle cellule est incluse dans la plage.  Les nouvelles
+cellules insérées juste avant une plage ne sont pas incluses.
+
+Des fanions peuvent être ajoutés à @code{ses-range} immédiatement
+après la cellule @var{à} .
+@table @code
+@item !
+Les cellules vides de la plage peuvent être enlevées en ajoutant le
+fanion @code{!}. Une cellule vide est une cellule dont la valeur est
+l’un des symboles @code{nil} ou @code{*skip*}. Par exemple
+@code{(ses-range A1 A4 !)} fait la même chose que @code{(list A1 A3)}
+quand les cellules @code{A2} et @code{A4} sont vides.
+@item _
+Les valeurs de cellules vides sont remplacées par l’argument suivant
+le fanion @code{_}, ou @code{0} quand le fanion @code{_} est le
+dernier dans la liste d’arguments. Par exemple @code{(ses-range A1 A4
+_ "vide")} fera la même chose que @code{(list A1 "vide" A3 "vide")}
+quand les cellules @code{A2} et @code{A4} sont vides. Similairement,
+@code{(ses-range A1 A4 _ )} fera la même chose que @code{(list A1 0 A3
+0)}.
+@item >v
+Quand l’ordre a de l’importance, liste les cellules en lisant les
+cellules ligne par ligne de la cellule en haut à gauche vers la
+cellule en bas à droite. Ce fanion est fourni pour être complet car
+c’est déjà l’ordre par défaut.
+@item <v
+Liste les cellules en lisant les cellules ligne par ligne de la
+cellule en haut à droite vers la cellule en bas à gauche.
+@item v>
+Liste les cellules en lisant les cellules colonne par colonne de la
+cellule en haut à gauche vers la cellule en bas à droite.
+@item v<
+Liste les cellules en lisant les cellules colonne par colonne de la
+cellule en haut à droite vers la cellule en bas à gauche.
+@item v
+Un raccourci pour @code{v>}.
+@item ^
+Un raccourci pour @code{^>}.
+@item >
+Un raccourci pour @code{>v}.
+@item <
+Un raccourci pour @code{>^}.
+@item *
+Au lieu de lister les cellules, en fait un vecteur ou une matrice Calc
+(@pxref{Top,,,calc,GNU Emacs Calc Manual}). Si la plage contient
+seulement une ligne ou une colonne un vecteur est fait, sinon une
+matrice est faite.
+@item *2
+Idem que @code{*} à ceci près qu’une matrice est toujours faite même
+quand il y a une seule ligne ou colonne dans la plage.
+@item *1
+Idem que @code{*} à ceci près qu’un vecteur est toujours fait même
+quand il n’y a qu’une ligne ou colonne dans la plage, c.-à-d.@: que la
+matrice correspondante est aplatie.
+@end table
+
+@node Sorting by column
+@section Trier par colonne
+@cindex trier
+@findex ses-sort-column
+@findex ses-sort-column-click
+
+@table @kbd
+@item C-c M-C-s
+Trie les cellules d’une plage en utilisant l’une des colonnes
+(@code{ses-sort-column}).  Les lignes (ou lignes partielles si la
+plage n’inclut pas toutes les colonnes) sont réarrangées de sorte que
+la colonne choisie soit ordonnée.
+
+@item [header-line mouse-2]
+La façon la plus facile de trier est de cliquer sur mouse-2 sur la
+ligne d’en-tête de colonne (@code{ses-sort-column-click}).
+@end table
+
+La comparaison du tri utilise @code{string<}, ce qui fonctionne bien
+pour des nombres alignés à droite ou des chaînes alignées à gauche.
+
+Avec un argument préfixe, trie dans l’ordre descendant.
+
+Les lignes sont déplacées une à la fois, avec relocalisation des
+formules. Ceci fonctionne bien si les formules font référence à
+d’autres cellules dans leur ligne, mais non pas si bien pour des
+formules qui font référence à d’autres lignes dans la plage ou à des
+cellules hors de la plage.
+
+
+@node Standard formula functions
+@section Fonctions de formule standardes
+@cindex fonctions standardes de formule
+@cindex *skip*
+@cindex *error*
+@findex ses-delete-blanks
+@findex ses-average
+@findex ses+
+
+Souvent on désire qu’un calcul exclue les cellules vides.  Voici
+quelques fonctions utiles à appeler dans vos formules :
+
+@table @code
+@item (ses-delete-blanks &rest @var{args})
+Renvoie une liste dont toutes les cellules vides (dont la valeur est
+soit @code{nil} ou @code{'*skip*}) ont été supprimées. L’ordre des
+arguments est inversé. Prière de noter que @code{ses-range} a un
+modificateur @code{!} qui permet de supprimer les cellules vides,
+ainsi il est possible d’écrire :
+@lisp
+(ses-range A1 A5 !)
+@end lisp
+au lieu de
+@lisp
+(apply 'ses-delete-blanks (ses-range A1 A5 <))
+@end lisp
+
+@item (ses+ &rest @var{args})
+Somme des arguments non vides pris en ordre inverse.
+
+@item (ses-average @var{liste})
+Moyenne des éléments non vides de @var{liste}.  Ici la liste est
+passée comme un seul argument, vu que typiquement on la forme avec
+@code{ses-range}.
+@end table
+
+@node More on cell printing
+@section Plus sur l’impression de cellule
+@cindex cellule, plus sur l'impression
+@cindex impression de cellule
+@findex ses-truncate-cell
+@findex ses-recalculate-cell
+
+Valeurs spéciales de cellule :
+@itemize
+@item nil
+s’imprime typiquement de la même façon que "", mais permet que la
+cellule précédente déborde dessus.
+@item '*skip*
+remplace nil quand la cellule précédente déborde effectivement ; rien
+n’est donc imprimée pour cette cellule.
+@item '*error*
+indique que la formule a signalé une erreur au lieu de produire une
+valeur : la cellule imprimée est remplie de croisillons (#).
+@end itemize
+
+Lorsque la fonction d’impression est définie par une chaîne de
+formatage, par ex. @samp{"%.3f"}, @acronym{SES} imprime
+automatiquement @code{nil} comme une chaîne vide, mais si la fonction
+d’impression est définie par une expression lambda, vous devez définir
+explicitement comment @code{nil} est traité, par ex. :
+@example
+(lambda (x)
+  (cond
+   ((null x) "")
+   ((stringp x) (list x))
+   ((numberp x) (format "%.3f" x))
+   (t (ses-prin1 x)))
+@end example
+imprime @code{nil} comme une chaîne vide, aligne à gauche la valeur si
+c’est une chaîne, et si c’est un nombre l’aligne à droite en
+l’imprimant avec trois décimales.
+
+Il n’est pas nécessaire par contre que vous vous souciez de
+@code{'*skip*} dans la définition d’une fonction d’impression, en
+effet aucune fonction d’impression n’est appelée sur @code{'*skip*}.
+
+Si le résultat de la fonction d’impression est trop large pour la
+cellule et que la cellule suivante est @code{nil}, le résultat
+débordera sur la cellule suivante. Les résultats très larges peuvent
+déborder sur plusieurs cellules.  Si le résultat est trop large pour
+l’espace disponible (jusqu'à la fin de la ligne ou la prochaine
+cellule non-@code{nil}), le résultat est tronqué si la valeur de
+cellule est une chaîne, ou remplacé par des croisillons (@samp{#})
+sinon.
+
+@acronym{SES} pourrait être perturbé par des résultats de fonction
+d'impression contenant des sauts de ligne ou des tabulations, aussi
+ces caractères sont remplacés par des points d'interrogation.
+
+@table @kbd
+@item t
+Confine une cellule à sa propre colonne (@code{ses-truncate-cell}).
+Ceci vous permet de déplacer le point sur la cellule de droite qui
+sinon serait couverte par un débordement. Si vous ne modifiez pas la
+cellule de droite, la cellule confinée débordera de nouveau la
+prochaine fois qu’elle sera imprimée.
+
+@item c
+Appliquée à une seule cellule, cette commande affiche dans la zone
+d’écho toute erreur de formule ou erreur d’impression survenue pendant
+le recalcul/la réimpression (@code{ses-recalculate-cell}).  Vous
+pouvez utiliser cela pour défaire l’effet de @kbd{t}.
+@end table
+
+Quand une fonction d’impression signale une erreur, la fonction
+d’impression de repli
+@findex ses-prin1
+@code{ses-prin1} lui est substituée.  Ceci est utile quand votre
+fonction d’impression de colonne est seulement numérique et que vous
+utilisez une chaîne comme valeur de cellule.  Notez que la fonction
+d’impression par défaut standarde est @samp{"%.7g"} qui est numérique
+seulement, ainsi les cellules auxquelles la fonction d’impression par
+défaut standarde s’applique et qui ne sont pas vides et ne contiennent
+pas un nombre utilisent la fonction d’impression de repli
+@code{ses-prin1}, par ex.@: les cellules qui contiennent une chaîne
+font cela.  @kbd{c} sur de telles cellules affiche « Format specifier
+doesn't match argument type ».
+
+
+@node Import and export
+@section Import et export
+@cindex import et export
+@cindex export, et import
+@findex ses-export-tsv
+@findex ses-export-tsf
+
+@table @kbd
+@item x t
+Exporte une plage de cellules comme des valeurs séparées par des
+tabulations (@code{ses-export-tsv}).
+@item x T
+Exporte une plage de cellules comme des formules séparées par des
+tabulations (@code{ses-export-tsf}).
+@end table
+
+Le texte exporté va dans l’anneau presse-papier ; vous pouvez le
+coller dans un autre tampon.  Les colonnes sont séparées par des
+tabulations, les lignes par des sauts de lignes.
+
+Pour importer du texte, utilisez n’importe laquelle des commandes
+coller où le texte à coller contient des tabulations et/ou des sauts de
+lignes.  Les formules importées ne sont pas relocalisées.
+
+@node Virus protection
+@section Protection contre les virus
+@cindex virus protection
+
+À chaque fois une formule ou fonction d’impression est lue d’un
+fichier ou est collée dans la feuille, elle est marquée comme
+« nécessitant une vérification de sécurité ».  Plus tard, quand la
+formule ou la fonction d’impression est évaluée pour la première fois,
+elle est vérifiée comme sûre en utilisant le prédicat @code{unsafep} ;
+si elle s’avère « potentiellement risquée », la formule ou fonction
+d’impression en question est affichée et vous devez appuyer @kbd{Y}
+pour l’approuver ou @kbd{N} pour utiliser un substitut. Le substitut
+signale toujours une erreur.
+
+Les formules ou fonctions d’impression que vous tapez sont
+immédiatement vérifiées quant à leur sûreté. Si elles s’avèrent
+potentiellement risquées et que vous appuyez @kbd{N} pour refuser,
+l’action est annulée et l’ancienne formule ou fonction d’impression
+demeure.
+
+En plus des virus (qui tentent de se recopier dans d’autres
+fichiers), @code{unsafep} peut aussi détecter toutes sortes de chevaux
+de Troie, tels que des feuilles de calcul qui effacent les fichiers,
+envoient des courriels, inondent des sites Web, corrompent vos
+réglages d’Emacs, etc.
+
+Généralement, les formules et fonctions d’impression de feuilles sont
+des choses simples qui n’ont pas besoin de faire des traitements
+exotiques, aussi toute partie potentiellement dangereuse de
+l’environnement Emacs Lisp peut être exclus sans entraver votre style
+comme écrivain de formule.  Lisez la documentation dans
+@file{unsafep.el} pour plus d’information sur la façon dont les formes
+Lisp sont classifiées comme sûres ou risquées.
+
+@node Spreadsheets with details and summary
+@section Feuilles avec détails et synthèse
+@cindex détails et synthèse
+@cindex synthèses, et détails
+
+Une organisation usuelle pour une feuille de calcul est d’avoir un tas
+de lignes de « détail », chacune décrivant possiblement une
+transaction, et ensuite un ensemble de lignes de « synthèse » qui
+affichent chacune des données condensées pour un certain sous-ensemble
+des détails.  @acronym{SES} prend en charge ce type d’organisation via
+la fonction @code{ses-select}.
+
+@table @code
+@item (ses-select @var{de-plage} @var{test} @var{à-plage})
+Renvoie un sous-ensemble de @var{à-plage}.  Pour chaque membre dans
+@var{de-plage} qui est égal à @var{test}, le membre correspondant de
+@var{à-plage} est inclus dans le résultat.
+@end table
+
+Exemple d’utilisation :
+@lisp
+(ses-average (ses-select (ses-range A1 A5) 'Bidochon (ses-range B1 B5)))
+@end lisp
+Ceci calcule la moyenne des valeurs de la colonne @samp{B} pour les
+lignes dont la valeur dans la colonne @samp{A} est le symbole
+@samp{'Bidochon}.
+
+Vous vous demandez peut-être pourquoi les arguments de
+@code{ses-select} ne consistent pas au lieu de @var{à-plage} de
+décalages @var{décalage-à-la-ligne} et @var{décalage-à-la-colonne}
+relativement à @var{de-plage} : spécifier @var{à-plage} explicitement
+assure que la formule est recalculée si l’une quelconque des cellules
+de cette plage est modifiée.
+
+Le fichier @file{etc/ses-example.el} dans la distribution Emacs est un
+exemple d’une feuille organisée en détails-et-synthèse.
+
+
+@c ===================================================================
+
+@node For Gurus
+@chapter Pour les gourous
+@cindex avancées, fonctions
+@cindex fonctions avancées
+
+@menu
+* Mises à jour différées:  Deferred updates.
+* Références non-relocalisables:  Nonrelocatable references.
+* La zone données:  The data area.
+* Variables locales-tampon dans les feuilles: Buffer-local variables in 
spreadsheets.
+* Utilisation de advice-add dans @acronym{SES}: Uses of advice-add in 
@acronym{SES}.
+@end menu
+
+@node Deferred updates
+@section Mises à jour différées
+@cindex différées, mises à jour
+@cindex mises à jour différées
+@vindex run-with-idle-timer
+
+Pour épargner du temps de calcul redondant, les cellules dont le
+recalcul est rendu nécessaire par des changements dans d’autres
+cellules sont ajoutées à un ensemble.  À la fin de la commande, chaque
+cellule de cet ensemble est recalculée une fois.  Ceci peut créer un
+nouvel ensemble de cellules nécessitant un recalcul.  Ce processus est
+répété jusqu'à ce que l’ensemble soit vide ou que des références
+circulaires soient détectées.  Dans les cas extrêmes, et notamment si
+une référence circulaire est en cours de détection, vous pourriez voir
+des messages de progression de la forme « Recalculating... (@var{nnn}
+cells left) ».  Si vous interrompez le calcul avec @kbd{C-g}, la
+feuille demeurera dans un état incohérent, utilisez alors @kbd{C-_} ou
+@kbd{C-c C-l} pour réparer cela.
+
+Pour épargner encore plus de temps en évitant les écritures
+redondantes, les cellules qui sont modifiées sont ajoutées à un
+ensemble au lieu d’être immédiatement écrites dans la zone de
+données. Chaque cellule de cet ensemble est écrite une fois à la fin
+de la commande.  Si vous modifiez un grand nombre de cellules, vous
+pourriez voir un message de progression de la forme
+« Writing... (@var{nnn} cells left) ».  Ces écritures différées de
+cellules ne peuvent pas être interrompues par @kbd{C-g}, alors il vous
+faudra juste attendre.
+
+@acronym{SES} utilise @code{run-with-idle-timer} pour déplacer le
+souligné de cellule quand Emacs fait défiler le tampon à la fin d’une
+commande, et aussi pour @c xxx narrow and underline
+réduire et souligner après visiter un fichier.  Ceci peut être visible
+par une perturbation transitoire après visiter un fichier et certaines
+commandes de défilement.  Vous pouvez continuer à taper sans vous
+inquiéter de cette perturbation.
+
+
+@node Nonrelocatable references
+@section Références non relocalisables
+@cindex non-relocalisables, références
+@cindex références non-relocalisables
+
+@kbd{C-y} relocalise toutes les références de cellule dans une formule
+collée, alors que @kbd{C-u C-y} n’en relocalise aucune.  Et pour les
+cas mélangés ?
+
+La meilleure approche est de renommer les cellules que vous @emph{ne}
+voulez @emph{pas} être relocalisables en utilisant
+@code{ses-rename-cell}.
+@findex ses-rename-cell
+Les cellules qui n’ont pas un style de nom du genre de A1 ne sont pas
+relocalisées au collage. En utilisant cette méthode, les cellules
+concernées ne seront pas relocalisées quelle que soit la formule où
+elles apparaissent. Prière toutefois de noter que dans une formule
+contenant quelque plage @code{(ses-range @var{cell1} @var{cell2})}
+alors dans la formule collée chacune des bornes @var{cell1} et
+@var{cell2} de la plage est relocalisée, ou non, indépendemment, selon
+qu’elle est nommée du genre de @samp{A1} ou renommée.
+
+Une méthode alternative est d’utiliser
+@lisp
+(symbol-value 'B3)
+@end lisp
+pour faire une @dfn{référence absolue}.  Le relocalisateur de formule
+saute par dessus tout ce qui est sous un @code{quote}, aussi cela ne
+sera pas relocalisé quand on le colle ou quand des lignes/colonnes
+sont insérées/supprimées.  Toutefois, @samp{B3} ne sera pas
+enregistrée comme une dépendance de cette cellule, et donc cette
+cellule ne sera pas mise à jour automatiquement quand @samp{B3} est
+modifiée, c’est pourquoi l’usage de @code{ses-rename-cell} est la
+plupart du temps préférable.
+
+Les variables @code{row} et @code{col} sont liées dynamiquement
+pendant l’évaluation d’une formule de cellule. Vous pouvez utiliser
+@lisp
+(ses-cell-value row 0)
+@end lisp
+pour obtenir la valeur de la colonne la plus à gauche de la ligne
+courante. Ce type de dépendance n’est pas non plus enregistré.
+
+
+@node The data area
+@section La zone de données
+@cindex données, zone de
+@cindex zone de données
+@findex ses-reconstruct-all
+
+Commence avec un caractère saut de page (de code ASCII 014 en octal),
+suivi par un ensemble de macros de définition de cellule pour chaque
+ligne, suivi par l’ensemble des définitions de fonctions d’impression
+locales, suivi par les largeurs de colonnes, fonctions d’impression de
+colonne, fonction d’impression par défaut, et ligne d’en-tête. Ensuite
+il y a les paramètres globaux (ID de format fichier, nombre de lignes,
+nombre de colonnes, nombre de fonctions d’impression locales) et les
+variables locales (spécification du mode @acronym{SES} pour le tampon,
+etc.).
+
+Quand un fichier @acronym{SES} est chargé, tout d’abord les paramètres
+globaux sont chargés, puis l’ensemble de la zone de données est
+@code{eval}ué, et finalement les variables locales sont traitées.
+
+Vous pouvez éditer la zone de données, mais n’insérez pas ni ne
+supprimez de sauts de ligne, hormis dans la partie des variables
+locales, en effet @acronym{SES} localise les choses en comptant les
+sauts de ligne. Utilisez @kbd{C-x C-e} à la fin d’une ligne pour
+installer ce que vous avez édité dans les structures de données de la
+feuille (ceci ne met pas à jour la zone d’impression, utilisez, par
+ex., @kbd{C-c C-l} pour cela).
+
+La zone de données est maintenue comme une image des structures de
+données de la feuille stockée dans des variables locales tampon au
+moment du chargement initial de la zone. Si le contenu de la zone de
+données se trouve corrompu par la suite, vous pouvez essayer de
+reconstruire la zone de données à partir des structures de données
+avec :
+
+@table @kbd
+@item C-c M-C-l
+(@code{ses-reconstruct-all}).
+@end table
+
+
+@node Buffer-local variables in spreadsheets
+@section Les variables locales-tampon dans les feuilles de calcul
+@cindex locales-tampon, variables
+@cindex variables locales-tampon
+
+Vous pouvez ajouter des variables locales supplémentaires à la liste
+au bas de la zone de données, telles que des constantes cachées
+auxquelles vous désirez faire référence dans vos formules.
+
+Vous pouvez initialiser la variable @code{ses--symbolic-formulas} pour
+être une liste de symboles (comme une suite de chaînes entre
+parenthèses) à proposer comme complétions pour la commande @kbd{'}.
+Cette liste initiale de complétions sera utilisée à la place de
+l’ensemble effectif des symboles-comme-formules de la feuille.
+
+Pour un exemple de ceci, voir le fichier @file{etc/ses-example.ses}.
+
+Si (pour une raison quelconque) vous désirez que vos formules ou
+fonctions d’impression sauvegardent des données dans des variables,
+vous devez déclarer ces variables comme locales tampon pour éviter un
+avertissement de virus.
+
+Vous pouvez définir des fonctions en en faisant des valeurs pour la
+fausse variable locale @code{eval}.  De telles fonctions peuvent
+ensuite être utilisées dans les formules et comme fonctions
+d’impression, mais d’ordinaire chaque @code{eval} est présenté à
+l’utilisateur pendant le chargement du fichier comme un virus
+potentiel.  Et cela peut devenir gênant.
+
+Vous pouvez définir des fonctions dans votre fichier @file{.emacs}.
+Toute personne pourra encore lire la zone d’impression de votre
+feuille, mais ne pourra pas recalculer ou réimprimer quoi que ce soit
+qui dépende de vos fonctions.  Pour éviter des avertissements contre
+les virus, chaque fonction utilisée dans une formule nécessite
+@lisp
+(put 'le-nom-de-votre-fonction 'safe-function t)
+@end lisp
+
+@node Uses of advice-add in @acronym{SES}
+@section Utilisation de advice-add dans @acronym{SES}
+@findex advice-add
+@findex copy-region-as-kill
+@findex yank
+
+@table @code
+@item copy-region-as-kill
+Quand on copie de la zone d’impression d’une feuille, traite la région
+comme un rectangle et joint pour chaque cellule sa formule et sa
+fonction d’impression comme des propriétés @code{'ses}.
+
+@item yank
+Quand on colle dans la zone d’impression d’une feuille de calcul,
+essaie de coller comme des cellules (si le texte à coller a des
+propriétés @code{'ses}), ensuite comme des formules séparées par des
+tabulations, ensuite (si tout le reste a échoué) comme une seule
+formule pour la cellule courante.
+@end table
+
+@c ===================================================================
+@node Index
+@unnumbered Index
+
+@printindex cp
+
+@c ===================================================================
+
+@node Acknowledgments
+@unnumbered Remerciements
+
+Codé par :
+@quotation
+@c jyavner@@member.fsf.org
+Jonathan Yavner,
+@c monnier@@gnu.org
+Stefan Monnier,
+@c shigeru.fukaya@@gmail.com
+Shigeru Fukaya,
+@c vincent.belaiche@@sourceforge.net
+Vincent Belaïche
+@end quotation
+
+@noindent
+Manuel Texinfo de :
+@quotation
+@c jyavner@@member.fsf.org
+Jonathan Yavner,
+@c brad@@chenla.org
+Brad Collins,
+@c vincent.belaiche@@sourceforge.net
+Vincent Belaïche
+@end quotation
+
+@noindent
+Idées de :
+@quotation
+@c christoph.conrad@@gmx.de
+Christoph Conrad,
+@c cyberbob@@redneck.gacracker.org
+CyberBob,
+@c syver-en@@online.no
+Syver Enstad,
+@c fischman@@zion.bpnetworks.com
+Ami Fischman,
+@c Thomas.Gehrlein@@t-online.de
+Thomas Gehrlein,
+@c c.f.a.johnson@@rogers.com
+Chris F.A. Johnson,
+@c lyusong@@hotmail.com
+Yusong Li,
+@c juri@@jurta.org
+Juri Linkov,
+@c maierh@@myself.com
+Harald Maier,
+@c anash@@san.rr.com
+Alan Nash,
+@c pinard@@iro.umontreal.ca
+François Pinard,
+@c ppinto@@cs.cmu.edu
+Pedro Pinto,
+@c xsteve@@riic.at
+Stefan Reichör,
+@c epameinondas@@gmx.de
+Oliver Scholz,
+@c rms@@gnu.org
+Richard M. Stallman,
+@c teirllm@@dms.auburn.edu
+Luc Teirlinck,
+@c jotto@@pobox.com
+J. Otto Tennant,
+@c jphil@@acs.pagesjaunes.fr
+Jean-Philippe Theberge,
+@c rrandresf@@hotmail.com
+Andrés Ramírez
+@end quotation
+
+@c ===================================================================
+
+@node GNU Free Documentation License
+@appendix GNU Free Documentation License
+@include doclicense.texi
+
+@bye
+@c Local Variables:
+@c ispell-dictionary: "fr"
+@c End:
diff --git a/doc/lispintro/ChangeLog.1 b/doc/lispintro/ChangeLog.1
index 76603b0a5f3..0f9c33f7c88 100644
--- a/doc/lispintro/ChangeLog.1
+++ b/doc/lispintro/ChangeLog.1
@@ -782,7 +782,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/doc/lispintro/Makefile.in b/doc/lispintro/Makefile.in
index 77087e97fac..53fc3b33e64 100644
--- a/doc/lispintro/Makefile.in
+++ b/doc/lispintro/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 1994-1999, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994-1999, 2001-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/doc/lispintro/README b/doc/lispintro/README
index b1b30bcbf49..70a840142b2 100644
--- a/doc/lispintro/README
+++ b/doc/lispintro/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/doc/lispintro/cons-1.eps b/doc/lispintro/cons-1.eps
index e8b5ec78b3f..db8e6e0b774 100644
--- a/doc/lispintro/cons-1.eps
+++ b/doc/lispintro/cons-1.eps
@@ -4,7 +4,7 @@
 %%CreationDate: Wed Mar  8 14:26:58 1995
 %%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
 
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 %
 % This file is part of GNU Emacs.
 %
diff --git a/doc/lispintro/cons-2.eps b/doc/lispintro/cons-2.eps
index 0bb93c83e3b..6be064c519b 100644
--- a/doc/lispintro/cons-2.eps
+++ b/doc/lispintro/cons-2.eps
@@ -4,7 +4,7 @@
 %%CreationDate: Wed Mar  8 14:26:39 1995
 %%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
 
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 %
 % This file is part of GNU Emacs.
 %
diff --git a/doc/lispintro/cons-2a.eps b/doc/lispintro/cons-2a.eps
index 5ca33ac8807..a6fa6d89e5f 100644
--- a/doc/lispintro/cons-2a.eps
+++ b/doc/lispintro/cons-2a.eps
@@ -4,7 +4,7 @@
 %%CreationDate: Tue Mar 14 15:09:30 1995
 %%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
 
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 %
 % This file is part of GNU Emacs.
 %
diff --git a/doc/lispintro/cons-3.eps b/doc/lispintro/cons-3.eps
index bf2a14e7da8..f83d99ab1e3 100644
--- a/doc/lispintro/cons-3.eps
+++ b/doc/lispintro/cons-3.eps
@@ -4,7 +4,7 @@
 %%CreationDate: Wed Mar  8 14:25:41 1995
 %%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
 
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 %
 % This file is part of GNU Emacs.
 %
diff --git a/doc/lispintro/cons-4.eps b/doc/lispintro/cons-4.eps
index bf995906a12..84da01f1f2b 100644
--- a/doc/lispintro/cons-4.eps
+++ b/doc/lispintro/cons-4.eps
@@ -4,7 +4,7 @@
 %%CreationDate: Wed Mar  8 14:25:06 1995
 %%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
 
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 %
 % This file is part of GNU Emacs.
 %
diff --git a/doc/lispintro/cons-5.eps b/doc/lispintro/cons-5.eps
index cd27259ae98..5325f7aa5a3 100644
--- a/doc/lispintro/cons-5.eps
+++ b/doc/lispintro/cons-5.eps
@@ -4,7 +4,7 @@
 %%CreationDate: Wed Mar  8 14:27:28 1995
 %%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
 
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 %
 % This file is part of GNU Emacs.
 %
diff --git a/doc/lispintro/drawers.eps b/doc/lispintro/drawers.eps
index 446bd8c71a7..9162dc96b89 100644
--- a/doc/lispintro/drawers.eps
+++ b/doc/lispintro/drawers.eps
@@ -9,7 +9,7 @@
 %%EndComments
 %%BeginProlog
 
-% Copyright (C) 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 2001-2024 Free Software Foundation, Inc.
 %
 % This file is part of GNU Emacs.
 %
diff --git a/doc/lispintro/emacs-lisp-intro.texi 
b/doc/lispintro/emacs-lisp-intro.texi
index d6627a2a1ca..a06822ce539 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -115,7 +115,7 @@ Edition @value{edition-number}, @value{update-date}
 @sp 1
 Distributed with Emacs version @value{EMACSVER}.
 @sp 1
-Copyright @copyright{} 1990--1995, 1997, 2001--2023 Free Software
+Copyright @copyright{} 1990--1995, 1997, 2001--2024 Free Software
 Foundation, Inc.
 @sp 1
 
@@ -317,7 +317,7 @@ List Processing
 * Evaluation::                  Running a program.
 * Variables::                   Returning a value from a variable.
 * Arguments::                   Passing information to a function.
-* set & setq::                  Setting the value of a variable.
+* setq::                        Setting the value of a variable.
 * Summary::                     The major points.
 * Error Message Exercises::
 
@@ -358,7 +358,6 @@ Arguments
 
 Setting the Value of a Variable
 
-* Using set::                  Setting values.
 * Using setq::                 Setting a quoted value.
 * Counting::                   Using @code{setq} to count.
 
@@ -1060,7 +1059,7 @@ of Lisp.
 * Evaluation::                  Running a program.
 * Variables::                   Returning a value from a variable.
 * Arguments::                   Passing information to a function.
-* set & setq::                  Setting the value of a variable.
+* setq::                        Setting the value of a variable.
 * Summary::                     The major points.
 * Error Message Exercises::
 @end menu
@@ -1782,7 +1781,7 @@ A symbol can have any value attached to it or, to use the 
jargon, we can
 string, @code{"such as this"}; to a list, such as @code{(spruce pine
 oak)}; we can even bind a variable to a function definition.
 
-A symbol can be bound to a value in several ways.  @xref{set & setq, ,
+A symbol can be bound to a value in several ways.  @xref{setq, ,
 Setting the Value of a Variable}, for information about one way to do
 this.
 
@@ -2273,52 +2272,52 @@ When your fill column is 70 and you evaluate the 
expression, the
 message @code{"He saw 38 red foxes leaping."} appears in your echo
 area.
 
-@node set & setq
+@node setq
 @section Setting the Value of a Variable
 @cindex Variable, setting value
 @cindex Setting value of variable
 
 @cindex @samp{bind} defined
-There are several ways by which a variable can be given a value.  One of
-the ways is to use either the function @code{set} or the special form
-@code{setq}.  Another way is to use @code{let} (@pxref{let}).  (The
-jargon for this process is to @dfn{bind} a variable to a value.)
+There are several ways by which a variable can be given a value.
+One of the ways is to use the special form @code{setq}.  Another way
+is to use @code{let} (@pxref{let}).  (The jargon for this process is
+to @dfn{bind} a variable to a value.)
 
-The following sections not only describe how @code{set} and @code{setq}
-work but also illustrate how arguments are passed.
+The following sections not only describe how @code{setq} works but
+also illustrate how arguments are passed.
 
 @menu
-* Using set::                  Setting values.
-* Using setq::                 Setting a quoted value.
+* Using setq::                 Setting variables.
 * Counting::                   Using @code{setq} to count.
 @end menu
 
-@node Using set
-@subsection Using @code{set}
+@node Using setq
+@subsection Using @code{setq}
 @findex set
 
-To set the value of the symbol @code{flowers} to the list @code{'(rose
+To set the value of the symbol @code{flowers} to the list @code{(rose
 violet daisy buttercup)}, evaluate the following expression by
 positioning the cursor after the expression and typing @kbd{C-x C-e}.
 
 @smallexample
-(set 'flowers '(rose violet daisy buttercup))
+(setq flowers '(rose violet daisy buttercup))
 @end smallexample
 
 @noindent
 The list @code{(rose violet daisy buttercup)} will appear in the echo
-area.  This is what is @emph{returned} by the @code{set} function.  As a
-side effect, the symbol @code{flowers} is bound to the list; that is,
-the symbol @code{flowers}, which can be viewed as a variable, is given
-the list as its value.  (This process, by the way, illustrates how a
-side effect to the Lisp interpreter, setting the value, can be the
-primary effect that we humans are interested in.  This is because every
-Lisp function must return a value if it does not get an error, but it
-will only have a side effect if it is designed to have one.)
+area.  This is what is @emph{returned} by the @code{setq} special
+form.  As a side effect, the symbol @code{flowers} is bound to the
+list; that is, the symbol @code{flowers}, which can be viewed as
+a variable, is given the list as its value.  (This process, by the
+way, illustrates how a side effect to the Lisp interpreter, setting
+the value, can be the primary effect that we humans are interested in.
+This is because every Lisp function must return a value if it does not
+get an error, but it will only have a side effect if it is designed to
+have one.)
 
-After evaluating the @code{set} expression, you can evaluate the symbol
-@code{flowers} and it will return the value you just set.  Here is the
-symbol.  Place your cursor after it and type @kbd{C-x C-e}.
+After evaluating the @code{setq} expression, you can evaluate the
+symbol @code{flowers} and it will return the value you just set.
+Here is the symbol.  Place your cursor after it and type @kbd{C-x C-e}.
 
 @smallexample
 flowers
@@ -2336,30 +2335,8 @@ in front of it, what you will see in the echo area is 
the symbol itself,
 'flowers
 @end smallexample
 
-Note also, that when you use @code{set}, you need to quote both
-arguments to @code{set}, unless you want them evaluated.  Since we do
-not want either argument evaluated, neither the variable
-@code{flowers} nor the list @code{(rose violet daisy buttercup)}, both
-are quoted.  (When you use @code{set} without quoting its first
-argument, the first argument is evaluated before anything else is
-done.  If you did this and @code{flowers} did not have a value
-already, you would get an error message that the @samp{Symbol's value
-as variable is void}; on the other hand, if @code{flowers} did return
-a value after it was evaluated, the @code{set} would attempt to set
-the value that was returned.  There are situations where this is the
-right thing for the function to do; but such situations are rare.)
-
-@node Using setq
-@subsection Using @code{setq}
-@findex setq
-
-As a practical matter, you almost always quote the first argument to
-@code{set}.  The combination of @code{set} and a quoted first argument
-is so common that it has its own name: the special form @code{setq}.
-This special form is just like @code{set} except that the first argument
-is quoted automatically, so you don't need to type the quote mark
-yourself.  Also, as an added convenience, @code{setq} permits you to set
-several different variables to different values, all in one expression.
+Also, as an added convenience, @code{setq} permits you to set several
+different variables to different values, all in one expression.
 
 To set the value of the variable @code{carnivores} to the list
 @code{'(lion tiger leopard)} using @code{setq}, the following expression
@@ -2369,18 +2346,6 @@ is used:
 (setq carnivores '(lion tiger leopard))
 @end smallexample
 
-@noindent
-This is exactly the same as using @code{set} except the first argument
-is automatically quoted by @code{setq}.  (The @samp{q} in @code{setq}
-means @code{quote}.)
-
-@need 1250
-With @code{set}, the expression would look like this:
-
-@smallexample
-(set 'carnivores '(lion tiger leopard))
-@end smallexample
-
 Also, @code{setq} can be used to assign different values to
 different variables.  The first argument is bound to the value
 of the second argument, the third argument is bound to the value of the
@@ -2400,14 +2365,14 @@ to the symbol @code{herbivores}:
 not have fit on a page; and humans find it easier to read nicely
 formatted lists.)
 
-Although I have been using the term ``assign'', there is another way of
-thinking about the workings of @code{set} and @code{setq}; and that is to
-say that @code{set} and @code{setq} make the symbol @emph{point} to the
-list.  This latter way of thinking is very common and in forthcoming
-chapters we shall come upon at least one symbol that has ``pointer'' as
-part of its name.  The name is chosen because the symbol has a value,
-specifically a list, attached to it; or, expressed another way,
-the symbol is set to point to the list.
+Although I have been using the term ``assign'', there is another way
+of thinking about the workings of @code{setq}; and that is to say that
+@code{setq} makes the symbol @emph{point} to the list.  This latter
+way of thinking is very common and in forthcoming chapters we shall
+come upon at least one symbol that has ``pointer'' as part of its
+name.  The name is chosen because the symbol has a value, specifically
+a list, attached to it; or, expressed another way, the symbol is set
+to point to the list.
 
 @node Counting
 @subsection Counting
@@ -3591,6 +3556,7 @@ and the two are not intended to refer to the same value.  
The
 * Parts of let Expression::
 * Sample let Expression::
 * Uninitialized let Variables::
+* How let Binds Variables::
 @end menu
 
 @ifnottex
@@ -3598,28 +3564,32 @@ and the two are not intended to refer to the same 
value.  The
 @unnumberedsubsec @code{let} Prevents Confusion
 @end ifnottex
 
+@c FIXME!! lexbind!!
+
 @cindex @samp{local variable} defined
 @cindex @samp{variable, local}, defined
 The @code{let} special form prevents confusion.  @code{let} creates a
 name for a @dfn{local variable} that overshadows any use of the same
-name outside the @code{let} expression.  This is like understanding
-that whenever your host refers to ``the house'', he means his house, not
-yours.  (Symbols used in argument lists work the same way.
+name outside the @code{let} expression (in computer science jargon, we
+call this @dfn{binding} the variable).  This is like understanding
+that in your host's home, whenever he refers to ``the house'', he
+means his house, not yours.  (The symbols used to name function
+arguments are bound as local variables in exactly the same way.
 @xref{defun, , The @code{defun} Macro}.)
 
-Local variables created by a @code{let} expression retain their value
-@emph{only} within the @code{let} expression itself (and within
-expressions called within the @code{let} expression); the local
-variables have no effect outside the @code{let} expression.
-
-Another way to think about @code{let} is that it is like a @code{setq}
-that is temporary and local.  The values set by @code{let} are
-automatically undone when the @code{let} is finished.  The setting
-only affects expressions that are inside the bounds of the @code{let}
-expression.  In computer science jargon, we would say the binding of
-a symbol is visible only in functions called in the @code{let} form;
-in Emacs Lisp, the default scoping is dynamic, not lexical.  (The
-non-default lexical binding is not discussed in this manual.)
+Another way to think about @code{let} is that it defines a special
+region in your code: within the body of the @code{let} expression, the
+variables you've named have their own local meaning.  Outside of the
+@code{let} body, they have other meanings (or they may not be defined
+at all).  This means that inside the @code{let} body, calling
+@code{setq} for a variable named by the @code{let} expression will set
+the value of the @emph{local} variable of that name.  However, outside
+of the @code{let} body (such as when calling a function that was
+defined elsewhere), calling @code{setq} for a variable named by the
+@code{let} expression will @emph{not} affect that local
+variable.@footnote{This describes the behavior of @code{let} when
+using a style called ``lexical binding'' (@pxref{How let Binds
+Variables}).}
 
 @code{let} can create more than one variable at once.  Also,
 @code{let} gives each variable it creates an initial value, either a
@@ -3779,6 +3749,128 @@ number is printed in the message using a @samp{%d} 
rather than a
 @samp{%s}.)  The four variables as a group are put into a list to
 delimit them from the body of the @code{let}.
 
+@node How let Binds Variables
+@subsection How @code{let} Binds Variables
+
+Emacs Lisp supports two different ways of binding variable names to
+their values.  These ways affect the parts of your program where a
+particular binding is valid.  For historical reasons, Emacs Lisp uses
+a form of variable binding called @dfn{dynamic binding} by default.
+However, in this manual we discuss the preferred form of binding,
+called @dfn{lexical binding}, unless otherwise noted (in the future,
+the Emacs maintainers plan to change the default to lexical binding).
+If you have programmed in other languages before, you're likely
+already familiar with how lexical binding behaves.
+
+In order to use lexical binding in a program, you should add this to
+the first line of your Emacs Lisp file:
+
+@example
+;;; -*- lexical-binding: t -*-
+@end example
+
+For more information about this, @pxref{Variable Scoping, , ,
+elisp, The Emacs Lisp Reference Manual}.
+
+@menu
+* Lexical & Dynamic Binding Differences::
+* Lexical vs. Dynamic Binding Example::
+@end menu
+
+@node Lexical & Dynamic Binding Differences
+@unnumberedsubsubsec Differences Between Lexical and Dynamic Binding
+
+@cindex Lexical binding
+@cindex Binding, lexical
+As we discussed before (@pxref{Prevent confusion}), when you create
+local variables with @code{let} under lexical binding, those variables
+are valid only within the body of the @code{let} expression.  In other
+parts of your code, they have other meanings, so if you call a
+function defined elsewhere within the @code{let} body, that function
+would be unable to ``see'' the local variables you've created.  (On
+the other hand, if you call a function that was defined within a
+@code{let} body, that function @emph{would} be able to see---and
+modify---the local variables from that @code{let} expression.)
+
+@cindex Dynamic binding
+@cindex Binding, dynamic
+Under dynamic binding, the rules are different: instead, when you use
+@code{let}, the local variables you've created are valid during
+execution of the @code{let} expression.  This means that, if your
+@code{let} expression calls a function, that function can see these
+local variables, regardless of where the function is defined
+(including in another file entirely).
+
+Another way to think about @code{let} when using dynamic binding is
+that every variable name has a global ``stack'' of bindings, and
+whenever you use that variable's name, it refers to the binding on the
+top of the stack.  (You can imagine this like a stack of papers on
+your desk with the values written on them.)  When you bind a variable
+dynamically with @code{let}, it puts the new binding you've specified
+on the top of the stack, and then executes the @code{let} body.  Once
+the @code{let} body finishes, it takes that binding off of the stack,
+revealing the one it had (if any) before the @code{let} expression.
+
+@node Lexical vs. Dynamic Binding Example
+@unnumberedsubsubsec Example of Lexical vs. Dynamic Binding
+In some cases, both lexical and dynamic binding behave identically.
+However, in other cases, they can change the meaning of your program.
+For example, see what happens in this code under lexical binding:
+
+@example
+;;; -*- lexical-binding: t -*-
+
+(setq x 0)
+
+(defun getx ()
+  x)
+
+(setq x 1)
+
+(let ((x 2))
+  (getx))
+     @result{} 1
+@end example
+
+@noindent
+Here, the result of @code{(getx)} is @code{1}.  Under lexical binding,
+@code{getx} doesn't see the value from our @code{let} expression.
+That's because the body of @code{getx} is outside of the body of our
+@code{let} expression.  Since @code{getx} is defined at the top,
+global level of our code (i.e.@: not inside the body of any @code{let}
+expression), it looks for and finds @code{x} at the global level as
+well.  When executing @code{getx}, the current global value of
+@code{x} is @code{1}, so that's what @code{getx} returns.
+
+If we use dynamic binding instead, the behavior is different:
+
+@example
+;;; -*- lexical-binding: nil -*-
+
+(setq x 0)
+
+(defun getx ()
+  x)
+
+(setq x 1)
+
+(let ((x 2))
+  (getx))
+     @result{} 2
+@end example
+
+@noindent
+Now, the result of @code{(getx)} is @code{2}!  That's because under
+dynamic binding, when executing @code{getx}, the current binding for
+@code{x} at the top of our stack is the one from our @code{let}
+binding.  This time, @code{getx} doesn't see the global value for
+@code{x}, since its binding is below the one from our @code{let}
+expression in the stack of bindings.
+
+(Some variables are also ``special'', and they are always dynamically
+bound even when @code{lexical-binding} is @code{t}.  @xref{defvar, ,
+Initializing a Variable with @code{defvar}}.)
+
 @node if
 @section The @code{if} Special Form
 @findex if
@@ -4471,9 +4563,7 @@ number; it will be printed as the character with that 
@sc{ascii} code.
 The @code{setq} special form sets the value of its first argument to the
 value of the second argument.  The first argument is automatically
 quoted by @code{setq}.  It does the same for succeeding pairs of
-arguments.  Another function, @code{set}, takes only two arguments and
-evaluates both of them before setting the value returned by its first
-argument to the value returned by its second argument.
+arguments.
 
 @item buffer-name
 Without an argument, return the name of the buffer, as a string.
@@ -9136,12 +9226,14 @@ In Emacs Lisp, a variable such as the @code{kill-ring} 
is created and
 given an initial value by using the @code{defvar} special form.  The
 name comes from ``define variable''.
 
-The @code{defvar} special form is similar to @code{setq} in that it sets
-the value of a variable.  It is unlike @code{setq} in two ways: first,
-it only sets the value of the variable if the variable does not already
-have a value.  If the variable already has a value, @code{defvar} does
-not override the existing value.  Second, @code{defvar} has a
-documentation string.
+The @code{defvar} special form is similar to @code{setq} in that it
+sets the value of a variable.  It is unlike @code{setq} in three ways:
+first, it marks the variable as ``special'' so that it is always
+dynamically bound, even when @code{lexical-binding} is @code{t}
+(@pxref{How let Binds Variables}).  Second, it only sets the value of
+the variable if the variable does not already have a value.  If the
+variable already has a value, @code{defvar} does not override the
+existing value.  Third, @code{defvar} has a documentation string.
 
 (There is a related macro, @code{defcustom}, designed for variables
 that people customize.  It has more features than @code{defvar}.
@@ -12882,7 +12974,40 @@ The next line of the @code{forward-paragraph} function 
begins a
 introduced}), in which Emacs binds a total of seven variables:
 @code{opoint}, @code{fill-prefix-regexp}, @code{parstart},
 @code{parsep}, @code{sp-parstart}, @code{start}, and
-@code{found-start}.
+@code{found-start}.  The first part of the @code{let*} expression
+looks like below:
+
+@smallexample
+@group
+(let* ((opoint (point))
+       (fill-prefix-regexp
+        (and fill-prefix (not (equal fill-prefix ""))
+             (not paragraph-ignore-fill-prefix)
+             (regexp-quote fill-prefix)))
+       ;; Remove ^ from paragraph-start and paragraph-sep if they are there.
+       ;; These regexps shouldn't be anchored, because we look for them
+       ;; starting at the left-margin.  This allows paragraph commands to
+       ;; work normally with indented text.
+       ;; This hack will not find problem cases like "whatever\\|^something".
+       (parstart (if (and (not (equal "" paragraph-start))
+                          (equal ?^ (aref paragraph-start 0)))
+                     (substring paragraph-start 1)
+                   paragraph-start))
+       (parsep (if (and (not (equal "" paragraph-separate))
+                        (equal ?^ (aref paragraph-separate 0)))
+                   (substring paragraph-separate 1)
+                 paragraph-separate))
+       (parsep
+        (if fill-prefix-regexp
+            (concat parsep "\\|"
+                    fill-prefix-regexp "[ \t]*$")
+          parsep))
+       ;; This is used for searching.
+       (sp-parstart (concat "^[ \t]*\\(?:" parstart "\\|" parsep "\\)"))
+       start found-start)
+  ...)
+@end group
+@end smallexample
 
 The variable @code{parsep} appears twice, first, to remove instances
 of @samp{^}, and second, to handle fill prefixes.
@@ -13250,6 +13375,10 @@ The last expression when there is no fill prefix is
 @end smallexample
 
 @noindent
+(Note that this code snippet is copied verbatim from the original code,
+so the two extra ending parentheses are matching the previous @code{if}
+and @code{while}.)
+
 This says that if there is no fill prefix and if we are not at the
 end, point should move to the beginning of whatever was found by the
 regular expression search for @code{sp-parstart}.
@@ -14630,7 +14759,7 @@ almost the same code as for the recursive version of
 
 @need 800
 @noindent
-Let's re-use @kbd{C-c =} as a convenient key binding:
+Let's reuse @kbd{C-c =} as a convenient key binding:
 
 @smallexample
 (global-set-key "\C-c=" 'count-words-defun)
@@ -16890,8 +17019,14 @@ remember to look here to remind myself.
 @node Text and Auto-fill
 @section Text and Auto Fill Mode
 
-Now we come to the part that turns on Text mode and
-Auto Fill mode.
+Now we come to the part that turns on Text mode and Auto Fill
+mode@footnote{
+This section suggests settings that are more suitable for writers.
+For programmers, the default mode will be set to the corresponding
+prog-mode automatically based on the type of the file.  And it's
+perfectly fine if you want to keep the fundamental mode as the default
+mode.
+}.
 
 @smallexample
 @group
@@ -16943,21 +17078,26 @@ Here is the line again; how does it work?
 
 @cindex Text Mode turned on
 @smallexample
-(setq major-mode 'text-mode)
+(setq-default major-mode 'text-mode)
 @end smallexample
 
 @noindent
 This line is a short, but complete Emacs Lisp expression.
 
-We are already familiar with @code{setq}.  It sets the following variable,
-@code{major-mode}, to the subsequent value, which is @code{text-mode}.
-The single-quote before @code{text-mode} tells Emacs to deal directly
-with the @code{text-mode} symbol, not with whatever it might stand for.
-@xref{set & setq, , Setting the Value of a Variable},
-for a reminder of how @code{setq} works.
-The main point is that there is no difference between the procedure you
-use to set a value in your @file{.emacs} file and the procedure you use
-anywhere else in Emacs.
+We are already familiar with @code{setq}.  We use a similar macro
+@code{setq-default} to set the following variable,
+@code{major-mode}@footnote{
+We use @code{setq-default} here because @code{text-mode} is
+buffer-local.  If we use @code{setq}, it will only apply to the
+current buffer, whereas using @code{setq-default} will also apply to
+newly created buffers.  This is not recommended for programmers.
+}, to the subsequent value, which is @code{text-mode}.  The
+single-quote before @code{text-mode} tells Emacs to deal directly with
+the @code{text-mode} symbol, not with whatever it might stand for.
+@xref{setq, , Setting the Value of a Variable}, for a reminder of how
+@code{setq} works.  The main point is that there is no difference
+between the procedure you use to set a value in your @file{.emacs}
+file and the procedure you use anywhere else in Emacs.
 
 @need 800
 Here is the next line:
diff --git a/doc/lispintro/lambda-1.eps b/doc/lispintro/lambda-1.eps
index 91a7ce9431f..ecfa25dca49 100644
--- a/doc/lispintro/lambda-1.eps
+++ b/doc/lispintro/lambda-1.eps
@@ -4,7 +4,7 @@
 %%CreationDate: Wed Mar  8 14:31:53 1995
 %%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
 
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 %
 % This file is part of GNU Emacs.
 %
diff --git a/doc/lispintro/lambda-2.eps b/doc/lispintro/lambda-2.eps
index 9dc7f138eda..8f2b2220918 100644
--- a/doc/lispintro/lambda-2.eps
+++ b/doc/lispintro/lambda-2.eps
@@ -4,7 +4,7 @@
 %%CreationDate: Wed Mar  8 14:33:09 1995
 %%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
 
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 %
 % This file is part of GNU Emacs.
 %
diff --git a/doc/lispintro/lambda-3.eps b/doc/lispintro/lambda-3.eps
index b403271c1f3..8929fd294f4 100644
--- a/doc/lispintro/lambda-3.eps
+++ b/doc/lispintro/lambda-3.eps
@@ -4,7 +4,7 @@
 %%CreationDate: Wed Mar  8 14:33:49 1995
 %%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
 
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 %
 % This file is part of GNU Emacs.
 %
diff --git a/doc/lispref/ChangeLog.1 b/doc/lispref/ChangeLog.1
index 95a23e981cc..ee8f418414c 100644
--- a/doc/lispref/ChangeLog.1
+++ b/doc/lispref/ChangeLog.1
@@ -13989,7 +13989,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1998-2023 Free Software Foundation, Inc.
+  Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/doc/lispref/Makefile.in b/doc/lispref/Makefile.in
index 325f23a3c0f..476b8cf8fe6 100644
--- a/doc/lispref/Makefile.in
+++ b/doc/lispref/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 1990-1996, 1998-2023 Free Software Foundation, Inc.
+# Copyright (C) 1990-1996, 1998-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/doc/lispref/README b/doc/lispref/README
index 48bbccd61f9..2fe37630bae 100644
--- a/doc/lispref/README
+++ b/doc/lispref/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.  -*- outline -*-
+Copyright (C) 2001-2024 Free Software Foundation, Inc.  -*- outline -*-
 See the end of the file for license conditions.
 
 
diff --git a/doc/lispref/abbrevs.texi b/doc/lispref/abbrevs.texi
index a9a5f84434d..9b719145584 100644
--- a/doc/lispref/abbrevs.texi
+++ b/doc/lispref/abbrevs.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 1999, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1994, 1999, 2001--2024 Free Software Foundation,
 @c Inc.
 @c See the file elisp.texi for copying conditions.
 @node Abbrevs
diff --git a/doc/lispref/anti.texi b/doc/lispref/anti.texi
index cddf675d336..0cb956eea98 100644
--- a/doc/lispref/anti.texi
+++ b/doc/lispref/anti.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1999, 2002--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1999, 2002--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 
 @c This node must have no pointers.
diff --git a/doc/lispref/back.texi b/doc/lispref/back.texi
index adc3c575f27..19f78d4c567 100644
--- a/doc/lispref/back.texi
+++ b/doc/lispref/back.texi
@@ -1,6 +1,6 @@
 \input texinfo  @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 2001--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2001--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @c
 @c %**start of header
diff --git a/doc/lispref/backups.texi b/doc/lispref/backups.texi
index cba212c634d..8d0f3806646 100644
--- a/doc/lispref/backups.texi
+++ b/doc/lispref/backups.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1999, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1995, 1999, 2001--2024 Free Software Foundation,
 @c Inc.
 @c See the file elisp.texi for copying conditions.
 @node Backups and Auto-Saving
diff --git a/doc/lispref/buffers.texi b/doc/lispref/buffers.texi
index a2d0f5687ba..77f5f09c7bd 100644
--- a/doc/lispref/buffers.texi
+++ b/doc/lispref/buffers.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Buffers
@@ -959,7 +959,7 @@ infinite recursion.
 
 @defun buffer-match-p condition buffer-or-name &rest args
 This function checks if a buffer designated by @code{buffer-or-name}
-satisfies the specified @code{condition}.  Optional arguments
+satisfies the specified @var{condition}.  Optional arguments
 @var{args} are passed to the predicate function in @var{condition}.  A
 valid @var{condition} can be one of the following:
 @itemize @bullet{}
@@ -985,10 +985,15 @@ Satisfied if @emph{any} condition in @var{conds} satisfies
 Satisfied if @emph{all} the conditions in @var{conds} satisfy
 @code{buffer-match-p}, with the same buffer and @code{args}.
 @item derived-mode
-Satisfied if the buffer's major mode derives from @var{expr}.
+Satisfied if the buffer's major mode derives from @var{expr}.  Note
+that this condition might fail to report a match if
+@code{buffer-match-p} is invoked before the major mode of the buffer
+has been established.
 @item major-mode
 Satisfied if the buffer's major mode is equal to @var{expr}.  Prefer
-using @code{derived-mode} instead, when both can work.
+using @code{derived-mode} instead, when both can work.  Note that this
+condition might fail to report a match if @code{buffer-match-p} is
+invoked before the major mode of the buffer has been established.
 @end table
 @item t
 Satisfied by any buffer.  A convenient alternative to @code{""} (empty
@@ -998,7 +1003,7 @@ string) or @code{(and)} (empty conjunction).
 
 @defun match-buffers condition &optional buffer-list &rest args
 This function returns a list of all buffers that satisfy the
-@code{condition}.  If no buffers match, the function returns
+@var{condition}.  If no buffers match, the function returns
 @code{nil}.  The argument @var{condition} is as defined in
 @code{buffer-match-p} above.  By default, all the buffers are
 considered, but this can be restricted via the optional argument
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index f6462a9e50b..6c8d42337d0 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Command Loop
@@ -2151,7 +2151,7 @@ is dismissed (@pxref{Mouse Menus}), Emacs also avoids 
simple
 translation if @code{down-mouse-1} is bound to a keymap, making it a
 prefix key.  In lieu of simple translation, it translates the closing
 @code{touchscreen-end} to a @code{down-mouse-1} event with the
-starting position of the touch sequence, consequentially displaying
+starting position of the touch sequence, consequently displaying
 the mouse menu.
 
 @cindex @code{mouse-1-menu-command}, a symbol property
@@ -2205,7 +2205,7 @@ position of the touchpoint.
 @item (touchscreen-restart-drag @var{posn})
 This event is sent upon the start of a touch sequence resulting in the
 continuation of a ``drag-to-select'' gesture (subject to the
-aformentioned user option) with @var{posn} set to the position list of
+aforementioned user option) with @var{posn} set to the position list of
 the initial @code{touchscreen-begin} event within that touch sequence.
 
 @cindex @code{touchscreen-pinch} event
@@ -2562,23 +2562,27 @@ non-@code{nil}.
 @vindex mouse-wheel-up-event
 @vindex mouse-wheel-down-event
 The @code{wheel-up} and @code{wheel-down} events are generated only on
-some kinds of systems.  On other systems, @code{mouse-4} and
-@code{mouse-5} are used instead.  For portable code, use the variables
-@code{mouse-wheel-up-event}, @code{mouse-wheel-up-alternate-event},
-@code{mouse-wheel-down-event} and
-@code{mouse-wheel-down-alternate-event} defined in @file{mwheel.el} to
-determine what event types to expect from the mouse wheel.
+some kinds of systems.  On other systems, other events like @code{mouse-4} and
+@code{mouse-5} are used instead.  Portable code should handle both
+@code{wheel-up} and @code{wheel-down} events as well as the events
+specified in the variables @code{mouse-wheel-up-event} and
+@code{mouse-wheel-down-event}, defined in @file{mwheel.el}.
+Beware that for historical reasons the @code{mouse-wheel-@emph{up}-event}
+is the variable that holds an event that should be handled similarly to
+@code{wheel-@emph{down}} and vice versa.
 
 @vindex mouse-wheel-left-event
 @vindex mouse-wheel-right-event
-Similarly, some mice can generate @code{mouse-wheel-left-event} and
-@code{mouse-wheel-right-event} and can be used to scroll if
-@code{mouse-wheel-tilt-scroll} is non-@code{nil}.  However, some mice
-also generate other events at the same time as they're generating
-these scroll events which may get in the way.  The way to fix this is
-generally to unbind these events (for instance, @code{mouse-6} or
-@code{mouse-7}, but this is very hardware and operating system
-dependent).
+The same holds for the  horizontal wheel movements which are usually
+represented by @code{wheel-left} and @code{wheel-right} events, but
+for which portable code should also obey the variables
+@code{mouse-wheel-left-event} and @code{mouse-wheel-right-event},
+defined in @file{mwheel.el}.
+However, some mice also generate other events at the same time as
+they're generating these scroll events which may get in the way.
+The way to fix this is generally to unbind these events (for instance,
+@code{mouse-6} or @code{mouse-7}, but this is very hardware and
+operating system dependent).
 
 @cindex @code{pinch} event
 @item (pinch @var{position} @var{dx} @var{dy} @var{scale} @var{angle})
diff --git a/doc/lispref/compile.texi b/doc/lispref/compile.texi
index 0dab03eb7ba..00602198da5 100644
--- a/doc/lispref/compile.texi
+++ b/doc/lispref/compile.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 2001--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1994, 2001--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Byte Compilation
 @chapter Byte Compilation
@@ -35,7 +35,6 @@ variable binding for @code{no-byte-compile} into it, like 
this:
 * Speed of Byte-Code::          An example of speedup from byte compilation.
 * Compilation Functions::       Byte compilation functions.
 * Docs and Compilation::        Dynamic loading of documentation strings.
-* Dynamic Loading::             Dynamic loading of individual functions.
 * Eval During Compile::         Code to be evaluated when you compile.
 * Compiler Errors::             Handling compiler error messages.
 * Byte-Code Objects::           The data type used for byte-compiled functions.
@@ -289,71 +288,6 @@ stands for the name of this file, as a string.  Do not use 
these
 constructs in Lisp source files; they are not designed to be clear to
 humans reading the file.
 
-@node Dynamic Loading
-@section Dynamic Loading of Individual Functions
-
-@cindex dynamic loading of functions
-@cindex lazy loading
-  When you compile a file, you can optionally enable the @dfn{dynamic
-function loading} feature (also known as @dfn{lazy loading}).  With
-dynamic function loading, loading the file doesn't fully read the
-function definitions in the file.  Instead, each function definition
-contains a place-holder which refers to the file.  The first time each
-function is called, it reads the full definition from the file, to
-replace the place-holder.
-
-  The advantage of dynamic function loading is that loading the file
-should become faster.  This is a good thing for a file which contains
-many separate user-callable functions, if using one of them does not
-imply you will probably also use the rest.  A specialized mode which
-provides many keyboard commands often has that usage pattern: a user may
-invoke the mode, but use only a few of the commands it provides.
-
-  The dynamic loading feature has certain disadvantages:
-
-@itemize @bullet
-@item
-If you delete or move the compiled file after loading it, Emacs can no
-longer load the remaining function definitions not already loaded.
-
-@item
-If you alter the compiled file (such as by compiling a new version),
-then trying to load any function not already loaded will usually yield
-nonsense results.
-@end itemize
-
-  These problems will never happen in normal circumstances with
-installed Emacs files.  But they are quite likely to happen with Lisp
-files that you are changing.  The easiest way to prevent these problems
-is to reload the new compiled file immediately after each recompilation.
-
-  @emph{Experience shows that using dynamic function loading provides
-benefits that are hardly measurable, so this feature is deprecated
-since Emacs 27.1.}
-
-  The byte compiler uses the dynamic function loading feature if the
-variable @code{byte-compile-dynamic} is non-@code{nil} at compilation
-time.  Do not set this variable globally, since dynamic loading is
-desirable only for certain files.  Instead, enable the feature for
-specific source files with file-local variable bindings.  For example,
-you could do it by writing this text in the source file's first line:
-
-@example
--*-byte-compile-dynamic: t;-*-
-@end example
-
-@defvar byte-compile-dynamic
-If this is non-@code{nil}, the byte compiler generates compiled files
-that are set up for dynamic function loading.
-@end defvar
-
-@defun fetch-bytecode function
-If @var{function} is a byte-code function object, this immediately
-finishes loading the byte code of @var{function} from its
-byte-compiled file, if it is not fully loaded already.  Otherwise,
-it does nothing.  It always returns @var{function}.
-@end defun
-
 @node Eval During Compile
 @section Evaluation During Compilation
 @cindex eval during compilation
@@ -878,8 +812,7 @@ well.
    You can natively-compile either a single function or macro
 definition, or a whole file of Lisp code, with the
 @code{native-compile} function.  Natively-compiling a file will
-produce both the corresponding @file{.elc} file with byte code and the
-@file{.eln} file with native code.
+produce the @file{.eln} file with native code.
 
 @findex native-comp-limple-mode
 @vindex native-comp-verbose
@@ -971,6 +904,18 @@ compilation subprocesses in parallel, under the control of
 Variables}).
 @end defun
 
+@deffn Command emacs-lisp-native-compile
+This command compiles the file visited by the current buffer into
+native code, if the file was changed since the last time it was
+natively-compiled.
+@end deffn
+
+@deffn Command emacs-lisp-native-compile-and-load
+This command compiles the file visited by the current buffer into
+native code, like @code{emacs-lisp-native-compile}, but it also loads
+the native code when the compilation finishes.
+@end deffn
+
   The following function allows Lisp programs to test whether
 native-compilation is available at runtime.
 
diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index d4bd8c14ae3..0c6895332a0 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -1,6 +1,6 @@
 @c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Control Structures
@@ -729,7 +729,7 @@ has over @code{cl-case}
   ;; symbol
   ('success       (message "Done!"))
   ('would-block   (message "Sorry, can't do it now"))
-  ('read-only     (message "The shmliblick is read-only"))
+  ('read-only     (message "The schmilblick is read-only"))
   ('access-denied (message "You do not have the needed rights"))
 @end group
 @group
@@ -2293,6 +2293,123 @@ should be robust if one does occur.  Note that this 
macro uses
 @code{condition-case-unless-debug} rather than @code{condition-case}.
 @end defmac
 
+Occasionally, we want to catch some errors and record some information
+about the conditions in which they occurred, such as the full
+backtrace, or the current buffer.  This kinds of information is sadly
+not available in the handlers of a @code{condition-case} because the
+stack is unwound before running that handler, so the handler is run in
+the dynamic context of the @code{condition-case} rather than that of
+the place where the error was signaled.  For those circumstances, you
+can use the following form:
+
+@defmac handler-bind handlers body@dots{}
+This special form runs @var{body} and if it executes without error,
+the value it returns becomes the value of the @code{handler-bind}
+form.  In this case, the @code{handler-bind} has no effect.
+
+@var{handlers} should be a list of elements of the form
+@code{(@var{conditions} @var{handler})} where @var{conditions} is an
+error condition name to be handled, or a list of condition names, and
+@var{handler} should be a form whose evaluation should return a function.
+As with @code{condition-case}, condition names are symbols.
+
+Before running @var{body}, @code{handler-bind} evaluates all the
+@var{handler} forms and installs those handlers to be active during
+the evaluation of @var{body}.  When an error is signaled,
+Emacs searches all the active @code{condition-case} and
+@code{handler-bind} forms for a handler that
+specifies one or more of these condition names.  When the innermost
+matching handler is one installed by @code{handler-bind}, the
+@var{handler} function is called with a single argument holding the
+error description.
+
+Contrary to what happens with @code{condition-case}, @var{handler} is
+called in the dynamic context where the error happened.  This means it
+is executed without unbinding any variable bindings or running any
+cleanups of @code{unwind-protect}, so that all those dynamic bindings
+are still in effect.  There is one exception: while running the
+@var{handler} function, all the error handlers between the code that
+signaled the error and the @code{handler-bind} are temporarily
+suspended, meaning that when an error is signaled, Emacs will only
+search the active @code{condition-case} and @code{handler-bind} forms
+that are inside the @var{handler} function or outside of the current
+@code{handler-bind}.  Note also that lexically-bound variables
+(@pxref{Lexical Binding}) are not affected, since they do not have
+dynamic extent.
+
+Like any normal function, @var{handler} can exit non-locally,
+typically via @code{throw}, or it can return normally.
+If @var{handler} returns normally, it means the handler
+@emph{declined} to handle the error and the search for an error
+handler is continued where it left off.
+
+For example, if we wanted to keep a log of all the errors that occur
+during the execution of a particular piece of code together with the
+buffer that's current when the error is signaled, but without
+otherwise affecting the behavior of that code, we can do it with:
+
+@example
+@group
+(handler-bind
+    ((error
+      (lambda (err)
+        (push (cons err (current-buffer)) my-log-of-errors))))
+  @var{body-forms}@dots{})
+@end group
+@end example
+
+This will log only those errors that are not caught internally to
+@var{body-forms}@dots{}, in other words errors that ``escape'' from
+@var{body-forms}@dots{}, and it will not prevent those errors from
+being passed on to surrounding @code{condition-case} handlers (or
+@code{handler-bind} handlers for that matter) since the above handler
+returns normally.
+
+We can also use @code{handler-bind} to replace an error with another,
+as in the code below which turns all errors of type @code{user-error}
+that occur during the execution of @var{body-forms}@dots{} into plain
+@code{error}:
+
+@example
+@group
+(handler-bind
+    ((user-error
+      (lambda (err)
+        (signal 'error (cdr err)))))
+  @var{body-forms}@dots{})
+@end group
+@end example
+
+We can get almost the same result with @code{condition-case}:
+
+@example
+@group
+(condition-case err
+    (progn @var{body-forms}@dots{})
+  (user-error (signal 'error (cdr err))))
+@end group
+@end example
+
+@noindent
+but with the difference that when we (re)signal the new error in
+@code{handler-bind}, the dynamic environment from the original error
+is still active, which means for example that if we enter the debugger
+at this point, it will show us a complete backtrace including the
+point where we signaled the original error:
+
+@example
+@group
+Debugger entered--Lisp error: (error "Oops")
+  signal(error ("Oops"))
+  (closure (t) (err) (signal 'error (cdr err)))((user-error "Oops"))
+  user-error("Oops")
+  @dots{}
+  eval((handler-bind ((user-error (lambda (err) @dots{}
+@end group
+@end example
+
+@end defmac
+
 @node Error Symbols
 @subsubsection Error Symbols and Condition Names
 @cindex error symbol
diff --git a/doc/lispref/customize.texi b/doc/lispref/customize.texi
index 6d5d9e0a2bc..33708d7faaa 100644
--- a/doc/lispref/customize.texi
+++ b/doc/lispref/customize.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1997--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1997--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Customization
 @chapter Customization Settings
diff --git a/doc/lispref/debugging.texi b/doc/lispref/debugging.texi
index 57ed5806855..47851be0f7c 100644
--- a/doc/lispref/debugging.texi
+++ b/doc/lispref/debugging.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1994, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Debugging
@@ -1093,10 +1093,19 @@ argument (@kbd{C-u @key{RET}}) to see the whole call 
tree below a
 function.  Pressing @kbd{@key{RET}} again will collapse back to the
 original state.
 
-Press @kbd{j} or @kbd{mouse-2} to jump to the definition of a function
-at point.  Press @kbd{d} to view a function's documentation.  You can
-save a profile to a file using @kbd{C-x C-w}.  You can compare two
-profiles using @kbd{=}.
+@findex profiler-report-find-entry
+@findex profiler-report-describe-entry
+@findex profiler-find-profile
+@findex profiler-find-profile-other-window
+@findex profiler-report-compare-profile
+Press @kbd{j} (@code{profiler-report-find-entry}) or @kbd{mouse-2} to
+jump to the definition of a function at point.  Press @kbd{d}
+(@code{profiler-report-describe-entry}) to view a function's
+documentation.  You can save a profile to a file using @kbd{C-x C-w}
+(@code{profiler-report-write-profile}) and read a saved profile with
+@w{@kbd{M-x profiler-find-profile}} or @w{@kbd{M-x
+profiler-find-profile-other-window}}.  You can compare two profiles
+using @kbd{=} (@code{profiler-report-compare-profile}).
 
 @c FIXME reversed calltree?
 
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 4dbb4afb20d..10cf5ce89e2 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -1,6 +1,6 @@
 @c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1995, 1998--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Display
 @chapter Emacs Display
@@ -2726,7 +2726,7 @@ Draw a box with lines of width 1, in color @var{color}.
 You can explicitly specify all aspects of the box with a plist on this
 form.  Any element in this plist can be omitted.
 
-The values @var{vwidth} and @var{hwidth} specifies respectively the
+The values of @var{vwidth} and @var{hwidth} specify respectively the
 width of the vertical and horizontal lines to draw; they default to (1
 . 1).  A negative horizontal or vertical width @minus{}@var{n} means
 to draw a line of width @var{n} that occupies the space of the
@@ -2735,16 +2735,16 @@ width. For simplification the width could be specified 
with only a
 single number @var{n} instead of a list, such case is equivalent to
 @code{((abs @var{n}) . @var{n})}.
 
-The value @var{style} specifies whether to draw a 3D box.  If it is
+The value of @var{color} specifies the color to draw with.  The default
+is the background color of the face for 3D boxes and
+@code{flat-button}, and the foreground color of the face for other
+boxes.
+
+The value of @var{style} specifies whether to draw a 3D box.  If it is
 @code{released-button}, the box looks like a 3D button that is not
 being pressed.  If it is @code{pressed-button}, the box looks like a
 3D button that is being pressed.  If it is @code{nil},
 @code{flat-button} or omitted, a plain 2D box is used.
-
-The value @var{color} specifies the color to draw with.  The default
-is the background color of the face for 3D boxes and
-@code{flat-button}, and the foreground color of the face for other
-boxes.
 @end table
 
 @item :inverse-video
diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi
index 7cf7ee51751..03fae67e528 100644
--- a/doc/lispref/edebug.texi
+++ b/doc/lispref/edebug.texi
@@ -1,6 +1,6 @@
 @comment -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1992--1994, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1992--1994, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index c357c8cb35d..cab1622337e 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -99,7 +99,7 @@ This is the @cite{GNU Emacs Lisp Reference Manual}
 @end ifclear
 corresponding to Emacs version @value{EMACSVER}.
 
-Copyright @copyright{} 1990--1996, 1998--2023 Free Software Foundation,
+Copyright @copyright{} 1990--1996, 1998--2024 Free Software Foundation,
 Inc.
 
 @quotation
@@ -653,7 +653,6 @@ Byte Compilation
 * Speed of Byte-Code::      An example of speedup from byte compilation.
 * Compilation Functions::   Byte compilation functions.
 * Docs and Compilation::    Dynamic loading of documentation strings.
-* Dynamic Loading::         Dynamic loading of individual functions.
 * Eval During Compile::     Code to be evaluated when you compile.
 * Compiler Errors::         Handling compiler error messages.
 * Byte-Code Objects::       The data type used for byte-compiled functions.
diff --git a/doc/lispref/errors.texi b/doc/lispref/errors.texi
index 4eafe608302..b51a8844dbf 100644
--- a/doc/lispref/errors.texi
+++ b/doc/lispref/errors.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1993, 1999, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1993, 1999, 2001--2024 Free Software Foundation,
 @c Inc.
 @c See the file elisp.texi for copying conditions.
 @node Standard Errors
diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi
index 8af0ee49d02..b42020f43af 100644
--- a/doc/lispref/eval.texi
+++ b/doc/lispref/eval.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 1998, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1994, 1998, 2001--2024 Free Software Foundation,
 @c Inc.
 @c See the file elisp.texi for copying conditions.
 @node Evaluation
@@ -844,11 +844,24 @@ function body forms, as well as explicit calls in Lisp 
code.
 
 The default value of this variable is 1600.  If you set it to a value
 less than 100, Lisp will reset it to 100 if the given value is
-reached.  Entry to the Lisp debugger increases the value, if there is
-little room left, to make sure the debugger itself has room to
-execute.
+reached.
 @end defopt
 
+@defopt lisp-eval-depth-reserve
+In order to be able to debug infinite recursion errors, when invoking the
+Lisp debugger, Emacs increases temporarily the value of
+@code{max-lisp-eval-depth}, if there is little room left, to make sure
+the debugger itself has room to execute.  The same happens when
+running the handler of a @code{handler-bind}.  @xref{Handling Errors}.
+
+The variable @code{lisp-eval-depth-reserve} bounds the extra depth
+that Emacs can add to @code{max-lisp-eval-depth} for those
+exceptional circumstances.
+
+The default value of this variable is 200.
+@end defopt
+
+
 @defvar values
 The value of this variable is a list of the values returned by all the
 expressions that were read, evaluated, and printed from buffers
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index dc66ea8bc9c..9e7aeeecec8 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Files
@@ -1871,9 +1871,10 @@ multiple names, it continues to exist under the other 
names.  If
 @var{filename} is a symbolic link, @code{delete-file} deletes only the
 symbolic link and not its target.
 
-A suitable kind of @code{file-error} error is signaled if the file
-does not exist, or is not deletable.  (On GNU and other POSIX-like
-systems, a file is deletable if its directory is writable.)
+The command signals a suitable kind of @code{file-error} error if
+@var{filename} cannot be deleted.  (On GNU and other POSIX-like
+systems, a file can be deleted if its directory is writable.)  If the
+file does not exist, this command will not signal any error.
 
 If the optional argument @var{trash} is non-@code{nil} and the
 variable @code{delete-by-moving-to-trash} is non-@code{nil}, this
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index ec6f7fd9462..16c0432da3a 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Frames
@@ -4160,7 +4160,7 @@ code, for it's only meant to abet synchronization between 
the X
 server, owner and requestor.
 @end itemize
 
-  The selection owner responds by tranferring to the requestor a
+  The selection owner responds by transferring to the requestor a
 series of bytes, 16 bit words, or 32 bit words, along with another
 atom identifying the type of those words.  After requesting a
 selection, Emacs then applies its own interpretation of the data
@@ -4514,7 +4514,7 @@ bounds of the selection data in the buffer @var{buf}.
   Selections under such window systems as MS-Windows, Nextstep, Haiku
 and Android are not aligned with those under X@.  Each of these window
 system improvises its own selection mechanism without employing the
-``selection converter'' mechanism illustrated in the preceeding node.
+``selection converter'' mechanism illustrated in the preceding node.
 Only the @code{PRIMARY}, @code{CLIPBOARD}, and @code{SECONDARY}
 selections are generally supported, with the @code{XdndSelection}
 selection that records drag-and-drop data also available under
@@ -4852,7 +4852,7 @@ is the selection data itself (@pxref{Accessing 
Selections}).
 sometimes distinct from those provided by the ICCCM and conforming
 clipboard or primary selection owners.  Frequently, the name of a MIME
 type, such as @code{"text/plain;charset=utf-8"} (with discrepant
-capitalization of the ``utf-8''), is substitued for a standard X
+capitalization of the ``utf-8''), is substituted for a standard X
 selection name such as @code{UTF8_STRING}.
 
 @cindex XDS
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index 2687b112c92..4b34e75f055 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -1,6 +1,6 @@
 @c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Functions
@@ -533,6 +533,40 @@ Instead, use the @code{advertised-calling-convention} 
declaration
 compiler emit a warning message when it compiles Lisp programs which
 use the deprecated calling convention.
 
+@ifnottex
+The @code{(fn)} feature is typically used in the following situations:
+
+@itemize @minus
+@item To spell out arguments and their purposes in a macro or a function.  
Example:
+
+@example
+(defmacro lambda (&rest cdr)
+  "@dots{}
+\(fn ARGS [DOCSTRING] [INTERACTIVE] BODY)"@dots{})
+@end example
+
+@item To provide a more detailed description and names of arguments.  Example:
+
+@example
+(defmacro macroexp--accumulate (var+list &rest body)
+  "@dots{}
+\(fn (VAR LIST) BODY@dots{})"
+  (declare (indent 1))
+  (let ((var (car var+list))
+         (list (cadr var+list))
+@dots{})))
+@end example
+
+@item To better explain the purpose of a @code{defalias}.  Example:
+
+@example
+(defalias 'abbrev-get 'get
+  "@dots{}
+\(fn ABBREV PROP)")
+@end example
+@end itemize
+@end ifnottex
+
 @cindex computed documentation string
 @kindex :documentation
 Documentation strings are usually static, but occasionally it can be
@@ -948,8 +982,8 @@ lists) and call them using @code{funcall} or @code{apply}.  
Functions
 that accept function arguments are often called @dfn{functionals}.
 
   Sometimes, when you call a functional, it is useful to supply a no-op
-function as the argument.  Here are two different kinds of no-op
-function:
+function as the argument.  Here are three different kinds of no-op
+functions:
 
 @defun identity argument
 This function returns @var{argument} and has no side effects.
@@ -2032,9 +2066,10 @@ code) obey the advice and other calls (from C code) do 
not.
 
 @defmac define-advice symbol (where lambda-list &optional name depth) &rest 
body
 This macro defines a piece of advice and adds it to the function named
-@var{symbol}.  The advice is an anonymous function if @var{name} is
-@code{nil} or a function named @code{symbol@@name}.  See
-@code{advice-add} for explanation of other arguments.
+@var{symbol}.  If @var{name} is non-nil, the advice is named
+@code{@var{symbol}@@@var{name}} and installed with the name @var{name}; 
otherwise,
+the advice is anonymous.  See @code{advice-add} for explanation of
+other arguments.
 @end defmac
 
 @defun advice-add symbol where function &optional props
@@ -2043,10 +2078,12 @@ Add the advice @var{function} to the named function 
@var{symbol}.
 (@pxref{Core Advising Primitives}).
 @end defun
 
-@defun advice-remove symbol function
+@deffn Command advice-remove symbol function
 Remove the advice @var{function} from the named function @var{symbol}.
-@var{function} can also be the @code{name} of a piece of advice.
-@end defun
+@var{function} can also be the @code{name} of a piece of advice.  When
+called interactively, prompt for both an advised @var{function} and
+the advice to remove.
+@end deffn
 
 @defun advice-member-p function symbol
 Return non-@code{nil} if the advice @var{function} is already in the named
diff --git a/doc/lispref/hash.texi b/doc/lispref/hash.texi
index 4edc761cfab..4270de664f1 100644
--- a/doc/lispref/hash.texi
+++ b/doc/lispref/hash.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1999, 2001--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1999, 2001--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Hash Tables
 @chapter Hash Tables
@@ -121,32 +121,10 @@ referenced in the hash table are preserved from garbage 
collection.
 @item :size @var{size}
 This specifies a hint for how many associations you plan to store in the
 hash table.  If you know the approximate number, you can make things a
-little more efficient by specifying it this way.  If you specify too
-small a size, the hash table will grow automatically when necessary, but
-doing that takes some extra time.
-
-The default size is 65.
-
-@item :rehash-size @var{rehash-size}
-When you add an association to a hash table and the table is full,
-it grows automatically.  This value specifies how to make the hash table
-larger, at that time.
-
-If @var{rehash-size} is an integer, it should be positive, and the hash
-table grows by adding approximately that much to the nominal size.  If
-@var{rehash-size} is floating point, it had better be greater
-than 1, and the hash table grows by multiplying the old size by
-approximately that number.
-
-The default value is 1.5.
-
-@item :rehash-threshold @var{threshold}
-This specifies the criterion for when the hash table is full (so
-it should be made larger).  The value, @var{threshold}, should be a
-positive floating-point number, no greater than 1.  The hash table is
-full whenever the actual number of entries exceeds the nominal size
-multiplied by an approximation to this value.  The default for
-@var{threshold} is 0.8125.
+little more efficient by specifying it this way but since the hash
+table memory is managed automatically, the gain in speed is rarely
+significant.
+
 @end table
 @end defun
 
@@ -159,7 +137,7 @@ the following specifies a hash table containing the keys
 (a symbol) and @code{300} (a number) respectively.
 
 @example
-#s(hash-table size 30 data (key1 val1 key2 300))
+#s(hash-table data (key1 val1 key2 300))
 @end example
 
 Note, however, that when using this in Emacs Lisp code, it's
@@ -172,12 +150,11 @@ The printed representation for a hash table consists of 
@samp{#s}
 followed by a list beginning with @samp{hash-table}.  The rest of the
 list should consist of zero or more property-value pairs specifying
 the hash table's properties and initial contents.  The properties and
-values are read literally.  Valid property names are @code{size},
-@code{test}, @code{weakness}, @code{rehash-size},
-@code{rehash-threshold}, and @code{data}.  The @code{data} property
+values are read literally.  Valid property names are @code{test},
+@code{weakness} and @code{data}.  The @code{data} property
 should be a list of key-value pairs for the initial contents; the
 other properties have the same meanings as the matching
-@code{make-hash-table} keywords (@code{:size}, @code{:test}, etc.),
+@code{make-hash-table} keywords (@code{:test} and @code{:weakness}),
 described above.
 
 Note that you cannot specify a hash table whose initial contents
@@ -229,6 +206,10 @@ This function calls @var{function} once for each of the 
associations in
 @var{table}.  The function @var{function} should accept two
 arguments---a @var{key} listed in @var{table}, and its associated
 @var{value}.  @code{maphash} returns @code{nil}.
+
+@var{function} is allowed to call @code{puthash} to set a new value
+for @var{key} and @code{remhash} to remove @var{key}, but should not
+add, remove or modify other associations in @var{table}.
 @end defun
 
 @node Defining Hash
@@ -377,14 +358,7 @@ This function returns the @var{weak} value that was 
specified for hash
 table @var{table}.
 @end defun
 
-@defun hash-table-rehash-size table
-This returns the rehash size of @var{table}.
-@end defun
-
-@defun hash-table-rehash-threshold table
-This returns the rehash threshold of @var{table}.
-@end defun
-
 @defun hash-table-size table
-This returns the current nominal size of @var{table}.
+This returns the current allocation size of @var{table}.  Since hash table
+allocation is managed automatically, this is rarely of interest.
 @end defun
diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi
index d5e4e1c31d3..a76bac011b7 100644
--- a/doc/lispref/help.texi
+++ b/doc/lispref/help.texi
@@ -1,6 +1,6 @@
 @c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Documentation
diff --git a/doc/lispref/hooks.texi b/doc/lispref/hooks.texi
index 513146a3c08..9231d7573f9 100644
--- a/doc/lispref/hooks.texi
+++ b/doc/lispref/hooks.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1993, 1998, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1993, 1998, 2001--2024 Free Software Foundation,
 @c Inc.
 @c See the file elisp.texi for copying conditions.
 @node Standard Hooks
diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi
index 1fba683223e..a5480a9bf8a 100644
--- a/doc/lispref/internals.texi
+++ b/doc/lispref/internals.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1993, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1993, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node GNU Emacs Internals
@@ -1374,6 +1374,15 @@ objects between Emacs and the module (@pxref{Module 
Values}).  The
 provides facilities for conversion between basic C data types and the
 corresponding @code{emacs_value} objects.
 
+In the module function's body, do @emph{not} attempt to access
+elements of the @var{args} array beyond the index
+@code{@var{nargs}-1}: memory for the @var{args} array is allocated
+exactly to accommodate @var{nargs} values, and accessing beyond that
+will most probably crash your module.  In particular, if the value of
+@var{nargs} passed to the function at run time is zero, it must not
+access @var{args} at all, as no memory will have been allocated for it
+in that case.
+
 A module function always returns a value.  If the function returns
 normally, the Lisp code which called it will see the Lisp object
 corresponding to the @code{emacs_value} value the function returned.
@@ -2519,7 +2528,6 @@ when the buffer is not current.
 
 @item mode_line_format
 @itemx header_line_format
-@itemx case_fold_search
 @itemx tab_width
 @itemx fill_column
 @itemx left_margin
diff --git a/doc/lispref/intro.texi b/doc/lispref/intro.texi
index cfe5679b643..2062ae64866 100644
--- a/doc/lispref/intro.texi
+++ b/doc/lispref/intro.texi
@@ -1,6 +1,6 @@
 @c -*-coding: utf-8-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 2001--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1994, 2001--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 
 @node Introduction
diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi
index d4b1c4f2b3e..1521b3815f4 100644
--- a/doc/lispref/keymaps.texi
+++ b/doc/lispref/keymaps.texi
@@ -1,6 +1,6 @@
 @c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 1998--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1994, 1998--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Keymaps
 @chapter Keymaps
@@ -491,7 +491,7 @@ useful if there is a command which doesn't exist in the map 
being
 defined, but which should have the @code{repeat-map} property.
 
 If the @code{:exit} list is empty then no commands in the map exit
-@code{repeat-mode}.  Specifying one ore more commands in this list is
+@code{repeat-mode}.  Specifying one or more commands in this list is
 useful if the keymap being defined contains a command that should not
 have the @code{repeat-map} property.
 @end table
diff --git a/doc/lispref/lay-flat.texi b/doc/lispref/lay-flat.texi
index c4262907772..0ff8529eddb 100644
--- a/doc/lispref/lay-flat.texi
+++ b/doc/lispref/lay-flat.texi
@@ -1,6 +1,6 @@
 \input texinfo    @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 2001--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2001--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @c
 @comment %**start of header
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi
index 6a00f2887e7..1409e51c0d4 100644
--- a/doc/lispref/lists.texi
+++ b/doc/lispref/lists.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Lists
diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi
index 125011c780f..75b9d11028a 100644
--- a/doc/lispref/loading.texi
+++ b/doc/lispref/loading.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Loading
@@ -1011,6 +1011,19 @@ If loading the file succeeds but does not provide 
@var{feature},
 @code{require} signals an error about the missing feature.
 @end defun
 
+@defun require-with-check feature &optional filename noerror
+This function works like @code{require}, except if @var{feature} is
+already loaded (i.e.@: is already a member of the list in
+@code{features}, see below).  If @var{feature} is already loaded, this
+function checks if @var{feature} was provided by a file different from
+@var{filename}, and if so, it by default signals an error.  If the
+value of the optional argument @var{noerror} is @code{reload}, the
+function doesn't signal an error, but instead forcibly reloads
+@var{filename}; if @var{noerror} is some other non-@code{nil} value,
+the function emits a warning about @var{feature} being already
+provided by another file.
+@end defun
+
 @defun featurep feature &optional subfeature
 This function returns @code{t} if @var{feature} has been provided in
 the current Emacs session (i.e., if @var{feature} is a member of
diff --git a/doc/lispref/macros.texi b/doc/lispref/macros.texi
index e3961e4bace..659dba17524 100644
--- a/doc/lispref/macros.texi
+++ b/doc/lispref/macros.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1995, 1998, 2001--2024 Free Software Foundation,
 @c Inc.
 @c See the file elisp.texi for copying conditions.
 @node Macros
diff --git a/doc/lispref/maps.texi b/doc/lispref/maps.texi
index 7da704c79b6..6ae98da49c7 100644
--- a/doc/lispref/maps.texi
+++ b/doc/lispref/maps.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1993, 1999, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1993, 1999, 2001--2024 Free Software Foundation,
 @c Inc.
 @c See the file elisp.texi for copying conditions.
 @node Standard Keymaps
diff --git a/doc/lispref/markers.texi b/doc/lispref/markers.texi
index 0b98eee137a..3037790692c 100644
--- a/doc/lispref/markers.texi
+++ b/doc/lispref/markers.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Markers
diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi
index ba7f1ca692e..aa27de72ba0 100644
--- a/doc/lispref/minibuf.texi
+++ b/doc/lispref/minibuf.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Minibuffers
@@ -1564,7 +1564,7 @@ Interactively, or when @var{display} is non-@code{nil}, 
the return
 value is also displayed in the echo area.
 
 The optional arguments @var{foreground} and @var{face} control the
-appearence of the completion candidates in the @file{*Completions*}
+appearance of the completion candidates in the @file{*Completions*}
 buffer.  The candidates are displayed in the specified @var{face} but
 with different colors: if @var{foreground} is non-@code{nil}, the
 foreground color is changed to be the color of the candidate,
@@ -1878,10 +1878,31 @@ The value should be a list of completion styles 
(symbols).
 The value should be a value for @code{completion-cycle-threshold}
 (@pxref{Completion Options,,, emacs, The GNU Emacs Manual}) for this
 category.
+
+@item cycle-sort-function
+The function to sort entries when cycling.
+
+@item display-sort-function
+The function to sort entries in the @file{*Completions*} buffer.
+The possible values are: @code{nil}, which means to use either the
+sorting function from metadata or if that is @code{nil}, fall back to
+@code{completions-sort}; @code{identity}, which means not to sort at
+all, leaving the original order; or any other value out of those used
+in @code{completions-sort} (@pxref{Completion Options,,, emacs, The
+GNU Emacs Manual}).
+
+@item group-function
+The function to group completions.
+
+@item annotation-function
+The function to add annotations to completions.
+
+@item affixation-function
+The function to add prefixes and suffixes to completions.
 @end table
 
 @noindent
-Additional alist entries may be defined in the future.
+See @ref{Programmed Completion}, for a complete list of metadata entries.
 @end defopt
 
 @defvar completion-extra-properties
@@ -1891,6 +1912,12 @@ completion commands.  Its value should be a list of 
property and value
 pairs.  The following properties are supported:
 
 @table @code
+@item :category
+The value should be a symbol describing what kind of text the
+completion function is trying to complete.  If the symbol matches one
+of the keys in @code{completion-category-overrides}, the usual
+completion behavior is overridden.  @xref{Completion Variables}.
+
 @item :annotation-function
 The value should be a function to add annotations in the completions
 buffer.  This function must accept one argument, a completion, and
@@ -1907,6 +1934,15 @@ element of the returned list must be a three-element 
list, the
 completion, a prefix string, and a suffix string.  This function takes
 priority over @code{:annotation-function}.
 
+@item :group-function
+The function to group completions.
+
+@item :display-sort-function
+The function to sort entries in the @file{*Completions*} buffer.
+
+@item :cycle-sort-function
+The function to sort entries when cycling.
+
 @item :exit-function
 The value should be a function to run after performing completion.
 The function should accept two arguments, @var{string} and
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 70a4899b623..1d961249633 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Modes
@@ -809,6 +809,7 @@ modes, rather than those of the current buffer.
 @node Derived Modes
 @subsection Defining Derived Modes
 @cindex derived mode
+@cindex parent mode
 
   The recommended way to define a new major mode is to derive it from an
 existing one using @code{define-derived-mode}.  If there is no closely
@@ -866,6 +867,9 @@ also a special mode (@pxref{Major Mode Conventions}).
 You can also specify @code{nil} for @var{parent}.  This gives the new
 mode no parent.  Then @code{define-derived-mode} behaves as described
 above, but, of course, omits all actions connected with @var{parent}.
+Conversely, you can use @code{derived-mode-set-parent} and
+@code{derived-mode-add-parents}, described below, to explicitly set
+the ancestry of the new mode.
 
 The argument @var{docstring} specifies the documentation string for the
 new mode.  @code{define-derived-mode} adds some general information
@@ -932,6 +936,7 @@ Do not write an @code{interactive} spec in the definition;
 @code{define-derived-mode} does that automatically.
 @end defmac
 
+@cindex ancestry, of major modes
 @defun derived-mode-p modes
 This function returns non-@code{nil} if the current major mode is
 derived from any of the major modes given by the list of symbols
@@ -940,10 +945,28 @@ Instead of a list, @var{modes} can also be a single mode 
symbol.
 
 Furthermore, we still support a deprecated calling convention where the
 @var{modes} were passed as separate arguments.
+
+When examining the parent modes of the current major mode, this
+function takes into consideration the current mode's parents set by
+@code{define-derived-mode}, and also its additional parents set by
+@code{derived-mode-add-parents}, described below.
+@end defun
+
+@defun provided-mode-derived-p mode modes
+This function returns non-@code{nil} if @var{mode} is derived from any
+of the major modes given by the list of symbols in @var{modes}.  Like
+with @code{derived-mode-p}, @var{modes} can also be a single symbol,
+and this function also supports a deprecated calling convention where
+the @var{modes} were passed as separate symbol arguments.
+
+When examining the parent modes of @var{mode}, this function takes
+into consideration the parents of @var{mode} set by
+@code{define-derived-mode}, and also its additional parents set by
+@code{derived-mode-add-parents}, described below.
 @end defun
 
-The graph of major modes is accessed with the following lower-level
-functions:
+The graph of a major mode's ancestry can be accessed and modified with
+the following lower-level functions:
 
 @defun derived-mode-set-parent mode parent
 This function declares that @var{mode} inherits from @code{parent}.
@@ -956,14 +979,19 @@ by reusing @code{parent}.
 This function makes it possible to register additional parents beside
 the one that was used when defining @var{mode}.  This can be used when
 the similarity between @var{mode} and the modes in @var{extra-parents}
-is such that it makes sense to treat it as a child of those
-modes for purposes like applying directory-local variables.
+is such that it makes sense to treat @var{mode} as a child of those
+modes for purposes like applying directory-local variables and other
+mode-specific settings.  The additional parent modes are specified as
+a list of symbols in @var{extra-parents}.  Those additional parent
+modes will be considered as one of the @var{mode}s parents by
+@code{derived-mode-p} and @code{provided-mode-derived-p}.
 @end defun
 
 @defun derived-mode-all-parents mode
 This function returns the list of all the modes in the ancestry of
 @var{mode}, ordered from the most specific to the least specific, and
-starting with @var{mode} itself.
+starting with @var{mode} itself.  This includes the additional parent
+modes, if any, added by calling @code{derived-mode-add-parents}.
 @end defun
 
 
diff --git a/doc/lispref/nonascii.texi b/doc/lispref/nonascii.texi
index c290632a48b..b33082e2b24 100644
--- a/doc/lispref/nonascii.texi
+++ b/doc/lispref/nonascii.texi
@@ -1,6 +1,6 @@
 @c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1998--1999, 2001--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1998--1999, 2001--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Non-ASCII Characters
 @chapter Non-@acronym{ASCII} Characters
diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi
index 071ec0f518d..99b456043b9 100644
--- a/doc/lispref/numbers.texi
+++ b/doc/lispref/numbers.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Numbers
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 17961ffadfa..b8fd5ed4345 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -1,6 +1,6 @@
 @c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Lisp Data Types
@@ -1180,13 +1180,14 @@ character), Emacs automatically assumes that it is 
multibyte.
 
   You can also use hexadecimal escape sequences (@samp{\x@var{n}}) and
 octal escape sequences (@samp{\@var{n}}) in string constants.
-@strong{But beware:} If a string constant contains hexadecimal or
-octal escape sequences, and these escape sequences all specify unibyte
-characters (i.e., less than 256), and there are no other literal
-non-@acronym{ASCII} characters or Unicode-style escape sequences in
-the string, then Emacs automatically assumes that it is a unibyte
-string.  That is to say, it assumes that all non-@acronym{ASCII}
-characters occurring in the string are 8-bit raw bytes.
+@strong{But beware:} If a string constant contains octal escape
+sequences or one- or two-digit hexadecimal escape sequences, and these
+escape sequences all specify unibyte characters (i.e., codepoints less
+than 256), and there are no other literal non-@acronym{ASCII}
+characters or Unicode-style escape sequences in the string, then Emacs
+automatically assumes that it is a unibyte string.  That is to say, it
+assumes that all non-@acronym{ASCII} characters occurring in the
+string are 8-bit raw bytes.
 
   In hexadecimal and octal escape sequences, the escaped character
 code may contain a variable number of digits, so the first subsequent
@@ -1373,8 +1374,7 @@ and contents, like this:
 
 @example
 (make-hash-table)
-     @result{} #s(hash-table size 65 test eql rehash-size 1.5
-                             rehash-threshold 0.8125 data ())
+     @result{} #s(hash-table)
 @end example
 
 @noindent
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index a5ff1005e6b..60ae57d4c1d 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node System Interface
@@ -2945,7 +2945,7 @@ interpreted as icon name.
 
 @item :category @var{category}
 The type of notification this is, a string.  See the
-@uref{https://developer.gnome.org/notification-spec/#categories,
+@url{https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html#categories,
 Desktop Notifications Specification} for a list of standard
 categories.
 
diff --git a/doc/lispref/package.texi b/doc/lispref/package.texi
index 2952e7dfcfc..f75023d4039 100644
--- a/doc/lispref/package.texi
+++ b/doc/lispref/package.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 2010--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2010--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Packaging
 @chapter Preparing Lisp code for distribution
@@ -284,6 +284,15 @@ variable @code{load-file-name} (@pxref{Loading}).  Here is 
an example:
   (expand-file-name file superfrobnicator-base))
 @end smallexample
 
+@cindex @file{.elpaignore} file
+  If your package contains files that you don't wish to distribute to
+users (e.g.@: regression tests), you can add them to an
+@file{.elpaignore} file.  In this file, each line lists a file or a
+wildcard matching files; those files should be ignored when producing
+your package's tarball on ELPA (@pxref{Package Archives}).  (ELPA
+will pass this file to the @command{tar} command via the @option{-X}
+command-line option, when it prepares the package for download.)
+
 @node Package Archives
 @section Creating and Maintaining Package Archives
 @cindex package archive
diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi
index df81a805e67..5d79c4b27f4 100644
--- a/doc/lispref/parsing.texi
+++ b/doc/lispref/parsing.texi
@@ -1,6 +1,6 @@
 @c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 2021--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2021--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Parsing Program Source
 @chapter Parsing Program Source
diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi
index 5ff89e992d9..5e0143c7131 100644
--- a/doc/lispref/positions.texi
+++ b/doc/lispref/positions.texi
@@ -1,6 +1,6 @@
 @c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1995, 1998--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Positions
 @chapter Positions
diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index 887b41d0005..ea3fe738f69 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Processes
@@ -2639,7 +2639,7 @@ and @samp{:capability-command} are supplied, try to 
upgrade to an encrypted
 connection via @acronym{STARTTLS}.  If that fails, retain the
 unencrypted connection.
 @item starttls
-As for @code{nil}, but if @acronym{STARTTLS} fails drop the connection.
+As for @code{nil}, but if @acronym{STARTTLS} fails, drop the connection.
 @item shell
 A shell connection.
 @end table
@@ -2650,9 +2650,9 @@ doing a @samp{plain} connection.
 
 @item :capability-command @var{capability-command}
 Command to query the host capabilities.  This can either be a string
-(which will then be sent verbatim to the server), or a function
-(called with a single parameter; the "greeting" from the server when
-connecting), and should return a string.
+(which will then be sent verbatim to the server) or a function
+(called with a single parameter: the ``greeting'' from the server when
+connecting) that should return a string.
 
 @item :end-of-command @var{regexp}
 @itemx :end-of-capability @var{regexp}
@@ -2661,8 +2661,8 @@ command @var{capability-command}.  The latter defaults to 
the former.
 
 @item :starttls-function @var{function}
 Function of one argument (the response to @var{capability-command}),
-which returns either @code{nil}, or the command to activate @acronym{STARTTLS}
-if supported.
+which returns either @code{nil} or the command to activate
+@acronym{STARTTLS}, if supported.
 
 @item :success @var{regexp}
 Regular expression matching a successful @acronym{STARTTLS} negotiation.
@@ -2690,8 +2690,9 @@ enable automatic queries of @code{auth-source} when
 
 @item :return-list @var{cons-or-nil}
 The return value of this function.  If omitted or @code{nil}, return a
-process object.  Otherwise, a cons of the form @code{(@var{process-object}
-. @var{plist})}, where @var{plist} has keywords:
+process object.  Otherwise, a cons of the form
+@w{@code{(@var{process-object} . @var{plist})}}, where @var{plist} can
+include the following keywords:
 
 @table @code
 @item :greeting @var{string-or-nil}
@@ -2704,11 +2705,12 @@ The connection type: @samp{plain} or @samp{tls}.
 
 @item :shell-command @var{string-or-nil}
 If the connection @code{type} is @code{shell}, this parameter will be
-interpreted as a format-spec string that will be executed to make the
-connection.  The specs available are @samp{%s} for the host name and
-@samp{%p} for the port number.  For instance, if you want to first ssh
-to @samp{gateway} before making a plain connection, then this
-parameter could be something like @samp{ssh gateway nc %s %p}.
+interpreted as a format-spec string (@pxref{Custom Format Strings})
+that will be executed to make the connection.  The specs available are
+@samp{%s} for the host name and @samp{%p} for the port number.  For
+instance, if you want to first ssh to @samp{gateway} before making a
+plain connection, then this parameter's value could be something like
+@samp{ssh gateway nc %s %p}.
 
 @end table
 
diff --git a/doc/lispref/records.texi b/doc/lispref/records.texi
index 287ad869297..34a632a23f3 100644
--- a/doc/lispref/records.texi
+++ b/doc/lispref/records.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 2017--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2017--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Records
 @chapter Records
diff --git a/doc/lispref/searching.texi b/doc/lispref/searching.texi
index cb269fcacc5..2fa7ebc903d 100644
--- a/doc/lispref/searching.texi
+++ b/doc/lispref/searching.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Searching and Matching
@@ -2990,7 +2990,7 @@ values of the variables @code{sentence-end-double-space}
 @section Emacs versus POSIX Regular Expressions
 @cindex POSIX regular expressions
 
-Regular expression syntax varies signficantly among computer programs.
+Regular expression syntax varies significantly among computer programs.
 When writing Elisp code that generates regular expressions for use by other
 programs, it is helpful to know how syntax variants differ.
 To give a feel for the variation, this section discusses how
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index c9c6bb31350..74719d4779f 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Sequences Arrays Vectors
@@ -434,12 +434,44 @@ but their relative order is also preserved:
          (9 . "aaa") (9 . "zzz") (9 . "ppp") (9 . "fff")]
 @end group
 @end example
-
-@xref{Sorting}, for more functions that perform sorting.
-See @code{documentation} in @ref{Accessing Documentation}, for a
-useful example of @code{sort}.
 @end defun
 
+Sometimes, computation of sort keys of list or vector elements is
+expensive, and therefore it is important to perform it the minimum
+number of times.  By contrast, computing the sort keys of elements
+inside the @var{predicate} function passed to @code{sort} will generally
+perform this computation each time @var{predicate} is called with some
+element.  If you can separate the computation of the sort key of an
+element into a function of its own, you can use the following sorting
+function, which guarantees that the key will be computed for each list
+or vector element exactly once.
+
+@cindex decorate-sort-undecorate
+@cindex Schwartzian transform
+@defun sort-on sequence predicate accessor
+This function stably sorts @var{sequence}, which can be a list, a
+vector, a bool-vector, or a string.  It sorts by comparing the sort
+keys of the elements using @var{predicate}.  The comparison function
+@var{predicate} accepts two arguments, the sort keys to compare, and
+should return non-@code{nil} if the element corresponding to the first
+key should sort before the element corresponding to the second key.  The
+function computes a sort key of each element by calling the
+@var{accessor} function on that element; it does so exactly once for
+each element of @var{sequence}.  The @var{accessor} function is called
+with a single argument, an element of @var{sequence}.
+
+This function implements what is known as @dfn{decorate-sort-undecorate}
+paradigm, or the Schwartzian transform.  It basically trades CPU for
+memory, creating a temporary list with the computed sort keys, then
+mapping @code{car} over the result of sorting that temporary list.
+Unlike with @code{sort}, the return value is always a new list; the
+original @var{sequence} is left intact.
+@end defun
+
+@xref{Sorting}, for more functions that perform sorting.  See
+@code{documentation} in @ref{Accessing Documentation}, for a useful
+example of @code{sort}.
+
 @cindex sequence functions in seq
 @cindex seq library
 @cindex sequences, generalized
diff --git a/doc/lispref/streams.texi b/doc/lispref/streams.texi
index 896cf4caab5..86ec82b66a1 100644
--- a/doc/lispref/streams.texi
+++ b/doc/lispref/streams.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1994, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Read and Print
@@ -995,7 +995,7 @@ less natural and is less compact.
 @cindex overrides, in output functions
 @cindex output variables, overriding
 
-The previous section (@pxref{Output Functions}) lists the numerous
+The previous section (@pxref{Output Variables}) lists the numerous
 variables that control how the Emacs Lisp printer formats data for
 outputs.  These are generally available for users to change, but
 sometimes you want to output data in the default format, or override
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index d05b0b36475..4fe94f78cba 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -1,6 +1,6 @@
 @c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Strings and Characters
@@ -43,7 +43,7 @@ integer is a character or not is determined only by how it is 
used.
 Emacs.
 
   A string is a fixed sequence of characters.  It is a type of
-sequence called a @dfn{array}, meaning that its length is fixed and
+sequence called an @dfn{array}, meaning that its length is fixed and
 cannot be altered once it is created (@pxref{Sequences Arrays
 Vectors}).  Unlike in C, Emacs Lisp strings are @emph{not} terminated
 by a distinguished character code.
diff --git a/doc/lispref/symbols.texi b/doc/lispref/symbols.texi
index 1f3b677d7fb..367bd195f16 100644
--- a/doc/lispref/symbols.texi
+++ b/doc/lispref/symbols.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Symbols
@@ -675,7 +675,7 @@ name} (@pxref{Symbol Components}).
 
 It is useful to think of shorthands as @emph{abbreviating} the full
 names of intended symbols.  Despite this, do not confuse shorthands with the
-Abbrev system @pxref{Abbrevs}.
+Abbrev system (@pxref{Abbrevs}).
 
 @cindex namespace etiquette
 Shorthands make Emacs Lisp's @dfn{namespacing etiquette} easier to work
diff --git a/doc/lispref/syntax.texi b/doc/lispref/syntax.texi
index 2a4bd6f1585..83bbd19ca6f 100644
--- a/doc/lispref/syntax.texi
+++ b/doc/lispref/syntax.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Syntax Tables
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 5d05ef18d4f..3d14a5ad8be 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1995, 1998--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Text
 @chapter Text
@@ -2945,7 +2945,10 @@ character.
 
   Copying text between strings and buffers preserves the properties
 along with the characters; this includes such diverse functions as
-@code{substring}, @code{insert}, and @code{buffer-substring}.
+@code{substring}, @code{insert}, and @code{buffer-substring}.  Killing
+and then yanking text (@pxref{The Kill Ring}) also preserves the
+properties, except that some properties are handled specially and
+might be removed when text is yanked; @pxref{Yanking}.
 
 @menu
 * Examining Properties::   Looking at the properties of one character.
@@ -5919,74 +5922,109 @@ Nevertheless, we can define two distinct APIs around 
the
 @cindex JSONRPC application interfaces
 @enumerate
 
-@item A user interface for building JSONRPC applications
+@item An API for building JSONRPC applications
 
 @findex :request-dispatcher
 @findex :notification-dispatcher
 @findex jsonrpc-notify
 @findex jsonrpc-request
 @findex jsonrpc-async-request
-In this scenario, the JSONRPC application selects a concrete subclass
-of @code{jsonrpc-connection}, and proceeds to create objects of that
-subclass using @code{make-instance}.  To initiate a contact to the
-remote endpoint, the JSONRPC application passes this object to the
-functions @code{jsonrpc-notify}, @code{jsonrpc-request}, and/or
-@code{jsonrpc-async-request}.  For handling remotely initiated
-contacts, which generally come in asynchronously, the instantiation
-should include @code{:request-dispatcher} and
-@code{:notification-dispatcher} initargs, which are both functions of
-3 arguments: the connection object; a symbol naming the JSONRPC method
-invoked remotely; and a JSONRPC @code{params} object.
+In this scenario, a new aspiring JSONRPC-based application selects a
+concrete subclass of @code{jsonrpc-connection} that provides the
+transport for the JSONRPC messages to be exchanged between endpoints.
+
+The application creates objects of that subclass using
+@code{make-instance}.  To initiate a contact to a remote endpoint, the
+application passes this object to the functions such as
+@code{jsonrpc-notify}, @code{jsonrpc-request}, or
+@code{jsonrpc-async-request}.
+
+For handling remotely initiated contacts, which generally come in
+asynchronously, the @code{make-instance} instantiation should
+initialize it the @code{:request-dispatcher} and
+@code{:notification-dispatcher} EIEIO keyword arguments.  These are
+both functions of 3 arguments: the connection object; a symbol naming
+the JSONRPC method invoked remotely; and a JSONRPC @code{params}
+object.
 
 @findex jsonrpc-error
 The function passed as @code{:request-dispatcher} is responsible for
 handling the remote endpoint's requests, which expect a reply from the
-local endpoint (in this case, the program you're building).  Inside
-that function, you may either return locally (a normal return) or
-non-locally (an error return).  A local return value must be a Lisp
-object that can be serialized as JSON (@pxref{Parsing JSON}).  This
-determines a success response, and the object is forwarded to the
-server as the JSONRPC @code{result} object.  A non-local return,
-achieved by calling the function @code{jsonrpc-error}, causes an error
-response to be sent to the server.  The details of the accompanying
-JSONRPC @code{error} are filled out with whatever was passed to
+local endpoint (in this case, the application you're building).
+Inside that function, you may either return locally (a regular return)
+or non-locally (throw an error).  Both exits from the request
+dispatcher cause a reply to the remote endpoint's request to be sent
+through the transport.
+
+A regular return determines a success response, and the return value
+must be a Lisp object that can be serialized as JSON (@pxref{Parsing
+JSON}).  The result is forwarded to the server as the JSONRPC
+@code{result} object.  A non-local return, achieved by calling the
+function @code{jsonrpc-error}, causes an error response to be sent to
+the server.  The details of the accompanying JSONRPC @code{error}
+object are filled out with whatever was passed to
 @code{jsonrpc-error}.  A non-local return triggered by an unexpected
 error of any other type also causes an error response to be sent
 (unless you have set @code{debug-on-error}, in which case this calls
 the Lisp debugger, @pxref{Error Debugging}).
 
-@item A inheritance interface for building JSONRPC transport implementations
-
-In this scenario, @code{jsonrpc-connection} is subclassed to implement
+@findex jsonrpc-convert-to-endpoint
+@findex jsonrpc-convert-from-endpoint
+It's possible to use the @code{jsonrpc} library to build applications
+based on transport protocols that can be described as
+``quasi-JSONRPC''.  These are similar, but not quite identical to
+JSONRPC, such as the @uref{https://www.jsonrpc.org/, DAP (Debug
+Adapter Protocol)}.  These protocols also define request, response and
+notification messages but the format is not quite the same as JSONRPC.
+The generic functions @code{jsonrpc-convert-to-endpoint} and
+@code{jsonrpc-convert-from-endpoint} can be customized for converting
+between the internal representation of JSONRPC and whatever the
+endpoint accepts (@pxref{Generic Functions}).
+
+@item An API for building JSONRPC transports
+
+In this scenario, @code{jsonrpc-connection} is sub-classed to implement
 a different underlying transport strategy (for details on how to
 subclass, see @ref{Inheritance,Inheritance,,eieio}.).  Users of the
 application-building interface can then instantiate objects of this
 concrete class (using the @code{make-instance} function) and connect
-to JSONRPC endpoints using that strategy.
+to JSONRPC endpoints using that strategy.  See @ref{Process-based
+JSONRPC connections} for a built-in transport implementation.
 
 This API has mandatory and optional parts.
 
 @findex jsonrpc-connection-send
 To allow its users to initiate JSONRPC contacts (notifications or
-requests) or reply to endpoint requests, the subclass must have an
-implementation of the @code{jsonrpc-connection-send} method.
+requests) or reply to endpoint requests, the new transport
+implementation must equip the @code{jsonrpc-connection-send} generic
+function with a specialization for the the new subclass
+(@pxref{Generic Functions}).  This generic function is called
+automatically by primitives such as @code{jsonrpc-request} and
+@code{jsonrpc-notify}.  The specialization should ensure that the
+message described in the argument list is sent through whatever
+underlying communication mechanism (a.k.a.@: ``wire'') is used by the
+new transport to talk to endpoints.  This ``wire'' may be a network
+socket, a serial interface, an HTTP connection, etc.
 
 @findex jsonrpc-connection-receive
 Likewise, for handling the three types of remote contacts (requests,
 notifications, and responses to local requests), the transport
 implementation must arrange for the function
-@code{jsonrpc-connection-receive} to be called after noticing a new
-JSONRPC message on the wire (whatever that "wire" may be).
+@code{jsonrpc-connection-receive} to be called from Elisp after
+noticing some data on the ``wire'' that can be used to craft a JSONRPC
+(or quasi-JSONRPC) message.
 
 @findex jsonrpc-shutdown
 @findex jsonrpc-running-p
 Finally, and optionally, the @code{jsonrpc-connection} subclass should
-implement the @code{jsonrpc-shutdown} and @code{jsonrpc-running-p}
-methods if these concepts apply to the transport.  If they do, then
-any system resources (e.g.@: processes, timers, etc.) used to listen for
-messages on the wire should be released in @code{jsonrpc-shutdown},
-i.e.@: they should only be needed while @code{jsonrpc-running-p} is
-non-@code{nil}.
+add specializations to the @code{jsonrpc-shutdown} and
+@code{jsonrpc-running-p} generic functions if these concepts apply to
+the transport.  The specialization of @code{jsonrpc-shutdown} should
+ensure the release of any system resources (e.g.@: processes, timers,
+etc.) used to listen for messages on the wire.  The specialization of
+@code{jsonrpc-running-p} should tell if these resources are still
+active or have already been released (via @code{jsonrpc-shutdown} or
+otherwise).
 
 @end enumerate
 
@@ -6205,7 +6243,7 @@ cons it was set to at the time 
@code{prepare-change-group} was called.
 
   If @code{buffer-undo-list} no longer contains that cons, Emacs will
 lose track of any change groups, resulting in an error when the change
-group is cancelled.  To avoid this, do not call any functions which
+group is canceled.  To avoid this, do not call any functions which
 may edit the undo list in such a manner, when a change group is
 active: notably, ``amalgamating'' commands such as @code{delete-char},
 which call @code{undo-auto-amalgamate}.
diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi
index 43cf0da3508..2476603adc1 100644
--- a/doc/lispref/threads.texi
+++ b/doc/lispref/threads.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 2012--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2012--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Threads
 @chapter Threads
diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi
index 4c9dcee37d8..0db9a35ac6f 100644
--- a/doc/lispref/tips.texi
+++ b/doc/lispref/tips.texi
@@ -1,6 +1,6 @@
 @c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1993, 1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1993, 1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Tips
diff --git a/doc/lispref/two-volume-cross-refs.txt 
b/doc/lispref/two-volume-cross-refs.txt
index 741efe3baf8..fa876befa69 100644
--- a/doc/lispref/two-volume-cross-refs.txt
+++ b/doc/lispref/two-volume-cross-refs.txt
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See end for copying conditions.
 
 Two Volume Cross References
diff --git a/doc/lispref/two-volume.make b/doc/lispref/two-volume.make
index c412820748c..793a4425d3b 100644
--- a/doc/lispref/two-volume.make
+++ b/doc/lispref/two-volume.make
@@ -1,4 +1,4 @@
-# Copyright (C) 2007-2023 Free Software Foundation, Inc.
+# Copyright (C) 2007-2024 Free Software Foundation, Inc.
 # See end for copying conditions.
 
 # although it would be nice to use tex rather than pdftex to avoid
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index f575b188fc6..4d61d461deb 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--2024 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Variables
 @chapter Variables
@@ -978,6 +978,7 @@ program is executing, the binding exists.
 
 @cindex lexical binding
 @cindex lexical scope
+@cindex static scope
 @cindex indefinite extent
   For historical reasons, there are two dialects of Emacs Lisp,
 selected via the @code{lexical-binding} buffer-local variable.
@@ -989,6 +990,7 @@ binding can also be accessed from the Lisp debugger.}.  It 
also has
 @dfn{indefinite extent}, meaning that under some circumstances the
 binding can live on even after the binding construct has finished
 executing, by means of objects called @dfn{closures}.
+Lexical scoping is also commonly called @dfn{static scoping}.
 
 @cindex dynamic binding
 @cindex dynamic scope
@@ -2487,9 +2489,10 @@ are unwound.  Example:
 
 @defvar connection-local-default-application
 The default application, a symbol, to be applied in
-@code{with-connection-local-variables}.  It defaults to @code{tramp},
-but you can let-bind it to change the application temporarily
-(@pxref{Local Variables}).
+@code{with-connection-local-variables}, @code{connection-local-p} and
+@code{connection-local-value}.  It defaults to @code{tramp}, but you
+can let-bind it to change the application temporarily (@pxref{Local
+Variables}).
 
 This variable must not be changed globally.
 @end defvar
@@ -2545,6 +2548,22 @@ profile.
 This variable must not be changed globally.
 @end defvar
 
+@defmac connection-local-p symbol &optional application
+This macro returns non-@code{nil} if @var{symbol} has a
+connection-local binding for @var{application}.  If @var{application}
+is @code{nil}, the value of
+@code{connection-local-default-application} is used.
+@end defmac
+
+@defmac connection-local-value symbol &optional application
+This macro returns the connection-local value of @var{symbol} for
+@var{application}.  If @var{application} is @code{nil}, the value of
+@code{connection-local-default-application} is used.
+
+If @var{symbol} does not have a connection-local
+binding, the value is the default binding of the variable.
+@end defmac
+
 @defvar enable-connection-local-variables
 If @code{nil}, connection-local variables are ignored.  This variable
 shall be changed temporarily only in special modes.
@@ -2985,7 +3004,7 @@ meant to be used, here's a small example:
 
 @lisp
 @group
-(define-multisession-variable foo-var 0)
+(define-multisession-variable foo 0)
 (defun my-adder (num)
   (interactive "nAdd number: ")
   (setf (multisession-value foo)
@@ -2995,7 +3014,7 @@ meant to be used, here's a small example:
 @end lisp
 
 @noindent
-This defines the variable @code{foo-var} and binds it to a special
+This defines the variable @code{foo} and binds it to a special
 multisession object which is initialized with the value @samp{0} (if
 the variable doesn't already exist from a previous session).  The
 @code{my-adder} command queries the user for a number, adds this to
@@ -3018,7 +3037,7 @@ specified by @var{package-symbol}.  The combination of
 @var{package-symbol} isn't given, this will default to the first
 ``segment'' of the @var{name} symbol's name, which is the part of its
 name up to and excluding the first @samp{-}.  For instance, if
-@var{name} is @code{foo-var} and @var{package-symbol} isn't given,
+@var{name} is @code{foo} and @var{package-symbol} isn't given,
 @var{package-symbol} will default to @code{foo}.
 
 @cindex synchronized multisession variables
@@ -3026,7 +3045,7 @@ name up to and excluding the first @samp{-}.  For 
instance, if
 Multisession variables can be @dfn{synchronized} if @var{bool} is
 non-@code{nil}.  This means that if there're two concurrent Emacs
 instances running, and the other Emacs changes the multisession
-variable @code{foo-var}, the current Emacs instance will retrieve that
+variable @code{foo}, the current Emacs instance will retrieve that
 modified data when accessing the value.  If @var{synchronized} is
 @code{nil} or missing, this won't happen, and the values in all
 Emacs sessions using the variable will be independent of each other.
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index 22c1b307252..f14e74bc785 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -1,6 +1,6 @@
 @c -*-texinfo-*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
 @c Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
 @node Windows
@@ -2629,11 +2629,15 @@ default value is an empty display action, i.e., 
@w{@code{(nil . nil)}}.
 
 @defopt display-buffer-alist
 The value of this option is an alist mapping conditions to display
-actions.  Each condition is passed to @code{buffer-match-p}, along
-with the buffer name and the @var{action} argument passed to
-@code{display-buffer}.  If it returns a non-@code{nil} value, then
-@code{display-buffer} uses the corresponding display action to display
-the buffer.
+actions.  Each condition is passed to @code{buffer-match-p}
+(@pxref{Buffer List}), along with the buffer name and the @var{action}
+argument passed to @code{display-buffer}.  If it returns a
+non-@code{nil} value, then @code{display-buffer} uses the
+corresponding display action to display the buffer.  Caveat: if you
+use @code{derived-mode} or @code{major-mode} as condition,
+@code{buffer-match-p} could fail to report a match if
+@code{display-buffer} is called before the major mode of the buffer is
+set.
 @end defopt
 
 @defopt display-buffer-base-action
@@ -3268,6 +3272,15 @@ The value specifies an alist of frame parameters to give 
a new frame,
 if one is created.  @code{display-buffer-pop-up-frame} is its one and
 only addressee.
 
+@vindex pop-up-frames@r{, a buffer display action alist entry}
+@item pop-up-frames
+The value controls whether @code{display-buffer} may display buffers
+by making new frames.  It has the same meaning as the
+@code{pop-up-frames} variable and takes precedence over it when present.
+Its main intended purpose is to override a non-nil value of the
+variable for particular buffers which the user prefers to keep
+in the selected frame.
+
 @vindex parent-frame@r{, a buffer display action alist entry}
 @item parent-frame
 The value specifies the parent frame to be used when the buffer is
@@ -3331,6 +3344,16 @@ It is called @emph{after} the buffer is displayed, and 
@emph{before}
 the entries @code{window-height}, @code{window-width} and
 @code{preserve-size} are applied that could resize the window to fit
 it to the inserted contents.
+
+@vindex post-command-select-window@r{, a buffer display action alist entry}
+@item post-command-select-window
+If the value is non-@code{nil}, the buffer displayed by @code{display-buffer}
+is selected after the current command is executed by running the hook
+@code{post-command-hook} (@pxref{Command Overview}).
+If the value is @code{nil}, the buffer selected by such functions as
+@code{pop-to-buffer} is deselected, and the window that was selected
+before calling this function will remain selected regardless of which
+windows were selected afterwards within this command.
 @end table
 
 By convention, the entries @code{window-height}, @code{window-width}
@@ -3441,6 +3464,9 @@ A non-@code{nil} value also means that when 
@code{display-buffer} is
 looking for a window already displaying @var{buffer-or-name}, it can
 search any visible or iconified frame, not just the selected frame.
 
+An entry by the same name in @code{display-buffer}'s @var{alist}
+takes precedence over the variable.
+
 This variable is provided mainly for backward compatibility.  It is
 obeyed by @code{display-buffer} via a special mechanism in
 @code{display-buffer-fallback-action}, which calls the action function
@@ -3512,15 +3538,12 @@ functions it should try instead as, for example:
 
 @item pop-up-frames
 @vindex pop-up-frames@r{, replacement for}
-Instead of customizing this variable to @code{t}, customize
+Instead of customizing this variable to @code{t}, you can customize
 @code{display-buffer-base-action}, for example, as follows:
 
 @example
 @group
-(setopt
- display-buffer-base-action
- '((display-buffer-reuse-window display-buffer-pop-up-frame)
-   (reusable-frames . 0)))
+(setopt display-buffer-base-action '(nil (pop-up-frames . t)))
 @end group
 @end example
 
diff --git a/doc/man/ChangeLog.1 b/doc/man/ChangeLog.1
index 71662625fb9..b34480a98e9 100644
--- a/doc/man/ChangeLog.1
+++ b/doc/man/ChangeLog.1
@@ -176,7 +176,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2007-2023 Free Software Foundation, Inc.
+  Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/doc/man/ebrowse.1 b/doc/man/ebrowse.1
index 4ce96a44852..7b03f50bc30 100644
--- a/doc/man/ebrowse.1
+++ b/doc/man/ebrowse.1
@@ -82,7 +82,7 @@ should give you access to the complete manual.
 was written by Gerd Moellmann.
 .
 .SH COPYING
-Copyright 2008-2023 Free Software Foundation, Inc.
+Copyright 2008-2024 Free Software Foundation, Inc.
 .PP
 Permission is granted to make and distribute verbatim copies of this
 document provided the copyright notice and this permission notice are
diff --git a/doc/man/emacs.1.in b/doc/man/emacs.1.in
index 66b0741c0f9..d7a44fb8475 100644
--- a/doc/man/emacs.1.in
+++ b/doc/man/emacs.1.in
@@ -664,7 +664,7 @@ For detailed credits and acknowledgments, see the GNU Emacs 
manual.
 .
 .
 .SH COPYING
-Copyright 1995, 1999-2023 Free Software Foundation, Inc.
+Copyright 1995, 1999-2024 Free Software Foundation, Inc.
 .PP
 Permission is granted to make and distribute verbatim copies of this
 document provided the copyright notice and this permission notice are
diff --git a/doc/man/emacsclient.1 b/doc/man/emacsclient.1
index 0acf3dd339e..75f38e4e50e 100644
--- a/doc/man/emacsclient.1
+++ b/doc/man/emacsclient.1
@@ -1,5 +1,5 @@
 .\" See section COPYING for conditions for redistribution.
-.TH EMACSCLIENT 1 "2023-10-25" "GNU Emacs" "GNU"
+.TH EMACSCLIENT 1 "2023-12-23" "GNU Emacs" "GNU"
 .\" NAME should be all caps, SECTION should be 1-8, maybe w/ subsection
 .\" other params are allowed: see man(7), man(1)
 .SH NAME
@@ -62,9 +62,11 @@ This option applies only to the next file specified.
 .TP
 .B \-a, \-\-alternate-editor=COMMAND
 If the Emacs server is not running, run the specified shell command instead.
-This can also be specified via the ALTERNATE_EDITOR environment variable.
-If the value of ALTERNATE_EDITOR is the empty string, run "emacs \-\-daemon" to
+If the empty string is specified, run "emacs \-\-daemon" to
 start Emacs in daemon mode, and try to connect to it.
+
+See also the ALTERNATE_EDITOR environment variable, over which this
+option takes precedence.
 .TP
 .B -c, \-\-create-frame
 Create a new frame instead of trying to use the current Emacs frame.
@@ -84,7 +86,11 @@ Lisp expressions.
 .TP
 .B \-f, \-\-server-file=FILENAME
 Use TCP configuration file FILENAME for communication.
-This can also be specified via the EMACS_SERVER_FILE environment variable.
+Relative filenames are relative to "~/.emacs.d/server/" or
+"$XDG_CONFIG_HOME/emacs/server/", and the default is "server".
+
+See also the EMACS_SERVER_FILE environment variable, over which this
+option takes precedence.
 .TP
 .B \-n, \-\-no-wait
 Return immediately without waiting for you to "finish" the buffer in
@@ -114,7 +120,10 @@ side-effect rather than result.
 .TP
 .B \-s, \-\-socket-name=FILENAME
 Use socket named FILENAME for communication.
-This can also be specified via the EMACS_SOCKET_NAME environment variable.
+Relative filenames are relative to "$XDG_RUNTIME_DIR/emacs/" or "$TMPDIR/".
+
+See also the EMACS_SOCKET_NAME environment variable, over which this
+option takes precedence.
 .TP
 .B \-nw, \-t, \-\-tty
 Open a new Emacs frame on the current terminal.
@@ -122,8 +131,11 @@ Open a new Emacs frame on the current terminal.
 .B \-T, \-\-tramp=PREFIX
 Set PREFIX to add to filenames for Emacs to locate files on remote
 machines using TRAMP.  This is mostly useful in combination with using
-the Emacs server over TCP with --server-file.  This can also be
-specified via the EMACSCLIENT_TRAMP environment variable.
+the Emacs server on a remote host (either using TCP with
+--server-file, or a socket forwarded over SSH).
+
+See also the EMACSCLIENT_TRAMP environment variable, over which this
+option takes precedence.
 .TP
 .B \-V, \-\-version
 Print version information and exit.
@@ -133,10 +145,46 @@ Print this usage information message and exit.
 .SH "EXIT STATUS"
 Normally, the exit status is 0.  If emacsclient shuts down due to
 Emacs signaling an error, the exit status is 1.
+.SH ENVIRONMENT
+.TP
+.B ALTERNATE_EDITOR
+If the Emacs server is not running, run the shell command in this
+environment variable instead.  If set to the empty string, run
+"emacs \-\-daemon" to start Emacs in daemon mode, and try to connect
+to it.  Will be overridden by the
+.B \-\-alternate-editor
+option, if present.
+.TP
+.B EMACSCLIENT_TRAMP
+A prefix to add to filenames, intended to allow Emacs to locate files
+on remote machines using TRAMP.  Will be overridden by the
+.B \-\-tramp
+option, if present.
+.TP
+.B EMACS_SERVER_FILE
+Look in this file to discover where to find a TCP Emacs server.
+Relative filenames are relative to "~/.emacs.d/server/" or
+"$XDG_CONFIG_HOME/emacs/server/", and the
+default is "server".  Will be overridden by the
+.B \-\-server-file
+option, if present.
+.TP
+.B EMACS_SOCKET_NAME
+The filename of the socket to use for communication with the Emacs server.
+Relative filenames are relative to "$XDG_RUNTIME_DIR/emacs/" or "$TMPDIR/".
+Will be overridden by the
+.B \-\-socket-name
+option, if present.
 .SH "SEE ALSO"
 The program is documented fully in
 .IR "Using Emacs as a Server"
 available via the Info system.
+
+The XDG_ environment variables are described in detail in the
+.UR 
https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
+XDG Base Directory Specification
+.UE .
+
 .SH AUTHOR
 This manual page was originally written by Stephane Bortzmeyer
 <bortzmeyer@debian.org>, for the Debian GNU/Linux system, but is not
diff --git a/doc/man/etags.1 b/doc/man/etags.1
index 27870b67d70..ba1cd768fc4 100644
--- a/doc/man/etags.1
+++ b/doc/man/etags.1
@@ -290,7 +290,7 @@ Stallman.
 .BR vi ( 1 ).
 
 .SH COPYING
-Copyright 1992, 1999, 2001-2023 Free Software Foundation, Inc.
+Copyright 1992, 1999, 2001-2024 Free Software Foundation, Inc.
 .PP
 Permission is granted to make and distribute verbatim copies of this
 document provided the copyright notice and this permission notice are
diff --git a/doc/misc/ChangeLog.1 b/doc/misc/ChangeLog.1
index 832dbd846a6..03b5037229e 100644
--- a/doc/misc/ChangeLog.1
+++ b/doc/misc/ChangeLog.1
@@ -6011,7 +6011,7 @@
        (RSS Feeds): New section.
        (Built-in table editor): Document M-e and M-a navigate
        inside table field.
-       (Stuck projects): Docment that projects identified as
+       (Stuck projects): Document that projects identified as
        un-stuck will still be searched for stuck sub-projects.
        (Paragraphs): Document centering.
        (Creating timestamps, Agenda commands): Document new
@@ -12111,7 +12111,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1993-1999, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1993-1999, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in
index 1831bbbb73f..2841916dc89 100644
--- a/doc/misc/Makefile.in
+++ b/doc/misc/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 1994, 1996-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1996-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/doc/misc/auth.texi b/doc/misc/auth.texi
index 7b4e8fcfb39..f51a1446170 100644
--- a/doc/misc/auth.texi
+++ b/doc/misc/auth.texi
@@ -9,7 +9,7 @@
 @copying
 This file describes the Emacs auth-source library.
 
-Copyright @copyright{} 2008--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2008--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/autotype.texi b/doc/misc/autotype.texi
index 8617db16ca0..d927816c492 100644
--- a/doc/misc/autotype.texi
+++ b/doc/misc/autotype.texi
@@ -11,7 +11,7 @@
 @c  @cindex autotypist
 
 @copying
-Copyright @copyright{} 1994--1995, 1999, 2001--2023 Free Software
+Copyright @copyright{} 1994--1995, 1999, 2001--2024 Free Software
 Foundation, Inc.
 
 @quotation
diff --git a/doc/misc/bovine.texi b/doc/misc/bovine.texi
index 10b1a1fc654..5cef9ffbb93 100644
--- a/doc/misc/bovine.texi
+++ b/doc/misc/bovine.texi
@@ -24,7 +24,7 @@
 @c %**end of header
 
 @copying
-Copyright @copyright{} 1999--2004, 2012--2023 Free Software Foundation,
+Copyright @copyright{} 1999--2004, 2012--2024 Free Software Foundation,
 Inc.
 
 @quotation
diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi
index c651b007173..dacf1451cc2 100644
--- a/doc/misc/calc.texi
+++ b/doc/misc/calc.texi
@@ -95,7 +95,7 @@ This file documents Calc, the GNU Emacs calculator, included 
with
 GNU Emacs @value{EMACSVER}.
 @end ifnotinfo
 
-Copyright @copyright{} 1990--1991, 2001--2023 Free Software Foundation,
+Copyright @copyright{} 1990--1991, 2001--2024 Free Software Foundation,
 Inc.
 
 @quotation
@@ -10571,6 +10571,22 @@ Non-decimal fractions are entered and displayed as
 @samp{@var{radix}#@var{num}:@var{denom}} (or in the analogous three-part
 form).  The numerator and denominator always use the same radix.
 
+@ifnottex
+Fractions may also be entered with @kbd{@U{2044}} (U+2044 FRACTION
+SLASH) in place of any @kbd{:}.  Precomposed fraction characters from
+@kbd{@U{00BD}} (U+00BD VULGAR FRACTION ONE HALF) through
+@kbd{@U{215E}} (U+215E VULGAR FRACTION SEVEN EIGHTHS) are supported as
+well.  Thus, @samp{2:3}, @samp{2@U{2044}3}, and @samp{@U{2154}} are all
+equivalent.
+@end ifnottex
+@iftex
+Fractions may also be entered with U+2044 FRACTION SLASH in place of
+any @kbd{:}.  Precomposed fraction characters from U+00BD VULGAR
+FRACTION ONE HALF through U+215E VULGAR FRACTION SEVEN EIGHTHS are
+supported as well.
+@end iftex
+
+
 @node Floats
 @section Floats
 
@@ -11954,7 +11970,7 @@ trail pointer in various ways.
 @cindex Retrieving previous results
 The @kbd{t y} (@code{calc-trail-yank}) command reads the selected value in
 the trail and pushes it onto the Calculator stack.  It allows you to
-re-use any previously computed value without retyping.  With a numeric
+reuse any previously computed value without retyping.  With a numeric
 prefix argument @var{n}, it yanks the value @var{n} lines above the current
 trail pointer.
 
diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi
index 8bc19235516..7f299180fc6 100644
--- a/doc/misc/cc-mode.texi
+++ b/doc/misc/cc-mode.texi
@@ -167,7 +167,7 @@ CC Mode
 @copying
 This manual is for CC Mode in Emacs.
 
-Copyright @copyright{} 1995--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1995--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi
index e5a29cbcffb..65a29d955bc 100644
--- a/doc/misc/cl.texi
+++ b/doc/misc/cl.texi
@@ -7,7 +7,7 @@
 @copying
 This file documents the GNU Emacs Common Lisp emulation package.
 
-Copyright @copyright{} 1993, 2001--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1993, 2001--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/dbus.texi b/doc/misc/dbus.texi
index 9dff54ff94a..28ee64d6b89 100644
--- a/doc/misc/dbus.texi
+++ b/doc/misc/dbus.texi
@@ -10,7 +10,7 @@
 @syncodeindex fn cp
 
 @copying
-Copyright @copyright{} 2007--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2007--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/dired-x.texi b/doc/misc/dired-x.texi
index baddf7abc45..4cad016a0f6 100644
--- a/doc/misc/dired-x.texi
+++ b/doc/misc/dired-x.texi
@@ -20,7 +20,7 @@
 @comment %**end of header (This is for running Texinfo on a region.)
 
 @copying
-Copyright @copyright{} 1994--1995, 1999, 2001--2023 Free Software
+Copyright @copyright{} 1994--1995, 1999, 2001--2024 Free Software
 Foundation, Inc.
 
 @quotation
diff --git a/doc/misc/ebrowse.texi b/doc/misc/ebrowse.texi
index b6c9d3dabe4..dca6266d8ae 100644
--- a/doc/misc/ebrowse.texi
+++ b/doc/misc/ebrowse.texi
@@ -11,7 +11,7 @@
 @copying
 This file documents Ebrowse, a C++ class browser for GNU Emacs.
 
-Copyright @copyright{} 2000--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2000--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/ede.texi b/doc/misc/ede.texi
index b4f08b7c4b9..15f7a329803 100644
--- a/doc/misc/ede.texi
+++ b/doc/misc/ede.texi
@@ -6,7 +6,7 @@
 @copying
 This file describes EDE, the Emacs Development Environment.
 
-Copyright @copyright{} 1998--2001, 2004--2005, 2008--2023 Free Software
+Copyright @copyright{} 1998--2001, 2004--2005, 2008--2024 Free Software
 Foundation, Inc.
 
 @quotation
diff --git a/doc/misc/ediff.texi b/doc/misc/ediff.texi
index f3c671635eb..e8ecb218674 100644
--- a/doc/misc/ediff.texi
+++ b/doc/misc/ediff.texi
@@ -26,7 +26,7 @@
 This file documents Ediff, a comprehensive visual interface to Unix diff
 and patch utilities.
 
-Copyright @copyright{} 1995--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1995--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/edt.texi b/doc/misc/edt.texi
index 9146ebdb6d8..1a835f79d7f 100644
--- a/doc/misc/edt.texi
+++ b/doc/misc/edt.texi
@@ -6,7 +6,7 @@
 @copying
 This file documents the EDT emulation package for Emacs.
 
-Copyright @copyright{} 1986, 1992, 1994--1995, 1999--2023 Free Software
+Copyright @copyright{} 1986, 1992, 1994--1995, 1999--2024 Free Software
 Foundation, Inc.
 
 @quotation
diff --git a/doc/misc/efaq-w32.texi b/doc/misc/efaq-w32.texi
index de9354500df..9756345042e 100644
--- a/doc/misc/efaq-w32.texi
+++ b/doc/misc/efaq-w32.texi
@@ -15,7 +15,7 @@ Answers to Frequently asked Questions about using Emacs on 
Microsoft Windows.
 @include emacsver.texi
 
 @copying
-Copyright @copyright{} 2008, 2010--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2008, 2010--2024 Free Software Foundation, Inc.
 
 @quotation
 This list of frequently asked questions about GNU Emacs on MS Windows
diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi
index 70f434d4b99..5b722f9fd77 100644
--- a/doc/misc/efaq.texi
+++ b/doc/misc/efaq.texi
@@ -8,7 +8,7 @@
 @include emacsver.texi
 
 @copying
-Copyright @copyright{} 2001--2023 Free Software Foundation, Inc.@*
+Copyright @copyright{} 2001--2024 Free Software Foundation, Inc.@*
 Copyright @copyright{} 1994--2000 Reuven M. Lerner@*
 Copyright @copyright{} 1992--1993 Steven Byrnes@*
 Copyright @copyright{} 1990--1992 Joseph Brian Wells@*
@@ -3119,16 +3119,18 @@ escape sequences.  It is enabled by default.
 @cindex Fullscreen mode
 
 Run Emacs with the @samp{--maximized} command-line option or put the
-following form in your early init file (@pxref{Early Init File,,,
-emacs, The GNU Emacs Manual}).
+following form at the top of your early init file (@pxref{Early Init
+File,,, emacs, The GNU Emacs Manual}).
 
 @lisp
 (push '(fullscreen . maximized) default-frame-alist)
 @end lisp
 
 Note that while some customizations of @code{default-frame-alist}
-could have undesirable effects when modified in @file{early-init.el},
-it is okay to do it in this particular case.
+could have undesirable effects when modified in the early init file,
+it is okay to do it in this particular case.  Adding it to the top of
+your normal init file will also work, but leads to a visible resizing
+of the window that some find distracting.
 
 @node Emacs in a Linux console
 @section How can I alleviate the limitations of the Linux console?
diff --git a/doc/misc/eglot.texi b/doc/misc/eglot.texi
index 2d6fcb29d3f..85fef6be553 100644
--- a/doc/misc/eglot.texi
+++ b/doc/misc/eglot.texi
@@ -10,7 +10,7 @@
 @copying
 This manual is for Eglot, the Emacs LSP client.
 
-Copyright @copyright{} 2022--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2022--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -138,11 +138,10 @@ Turn on Eglot for your project.
 To start using Eglot for a project, type @kbd{M-x eglot @key{RET}} in
 a buffer visiting any file that belongs to the project.  This starts
 the language server configured for the programming language of that
-buffer, and causes Eglot to start managing all the files of the
-project which use the same programming language.  This includes files
-of a given project that are already visited at the time the
-@code{eglot} command is invoked as well as files visited after this
-invocation.
+buffer, and causes Eglot to start @dfn{managing} file-visiting buffers
+related to that programming language.  This includes files that are
+already visited at the time the @code{eglot} command is invoked, as
+well as any files visited after this invocation.
 
 The notion of a ``project'' used by Eglot is the same Emacs uses
 (@pxref{Projects,,, emacs, GNU Emacs Manual}): in the simplest case,
@@ -405,11 +404,13 @@ commands and variables.
 @section Eglot Features
 @cindex features in buffers supported by Eglot
 
-Once Eglot is enabled in a buffer, it uses LSP and the language-server
-capabilities to activate, enable, and enhance modern IDE features in
-Emacs.  The features themselves are usually provided via other Emacs
-packages.  Here's the list of the main features that Eglot enables and
-provides:
+While Eglot is enabled in a buffer, it is said to be @dfn{managing}
+it, using LSP and the specific capabilities of the language server to
+activate and enhance modern IDE features in Emacs.  Some of these
+features are provided via other Emacs packages, and some via Eglot
+directly (@pxref{Eglot Commands}).
+
+Here's an overview of the main features that Eglot provides:
 
 @itemize @bullet
 @item
@@ -422,10 +423,11 @@ allows major modes to provide extensive help and 
documentation about
 the program identifiers.
 
 @item
-On-the-fly diagnostic annotations with server-suggested fixes, via the
-Flymake package (@pxref{Top,,, flymake, GNU Flymake manual}).  This
-improves and enhances the Flymake diagnostics, replacing the other
-Flymake backends.
+On-the-fly diagnostic annotations, via the Flymake package
+(@pxref{Top,,, flymake, GNU Flymake manual}).  Eglot's Flymake backend
+replaces other Flymake backends while it is managing a buffer, and
+enhances diagnostics with interactive server-suggested fixes
+(so-called @dfn{code actions}, @pxref{Eglot Commands})
 
 @item
 Finding definitions and uses of identifiers, via Xref (@pxref{Xref,,,
@@ -484,9 +486,17 @@ with @kbd{eglot-code-actions}.  @xref{Eglot Commands}.
 
 Not all servers support the full set of LSP capabilities, but most of
 them support enough to enable the basic set of features mentioned
-above.  Conversely, some servers offer capabilities for which no
-equivalent Emacs package exists yet, and so Eglot cannot (yet) expose
-these capabilities to Emacs users.
+above.
+
+Conversely, some servers offer capabilities for which no equivalent
+Emacs package exists yet, and so Eglot cannot (yet) expose these
+capabilities to Emacs users.  However, @xref{Extending Eglot}.
+
+Finally, it's worth noting that, by default, Eglot generally turns on
+all features that it @emph{can} turn on.  It's possible to opt out of
+some features via user options (@pxref{Customizing Eglot}) and a hook
+that runs after Eglot starts managing a buffer (@pxref{Eglot and
+Buffers}).
 
 @node Eglot and Buffers
 @section Buffers, Projects, and Eglot
@@ -694,7 +704,7 @@ requests for the language server to provide editing 
commands for
 correcting, refactoring or beautifying your code.  These commands may
 affect more than one visited file belonging to the project.
 
-The command @code{eglot-code-actions} asks the server if there any
+The command @code{eglot-code-actions} asks the server if there are any
 code actions for any point in the buffer or contained in the active
 region.  If there are, you have the choice to execute one of them via
 the minibuffer.
@@ -826,13 +836,13 @@ in the background.  The value of @code{t} means block 
during the whole
 waiting period.  The value of @code{nil} or @code{0} means don't block at
 all during the waiting period.
 
-@item eglot-events-buffer-size
-This determines the size of the Eglot events buffer.  @xref{Eglot
-Commands, eglot-events-buffer}, for how to display that buffer.  If
-the value is changed, for it to take effect the connection should be
-restarted using @kbd{M-x eglot-reconnect}.
+@item eglot-events-buffer-config
+This configures the size and format of the Eglot events buffer.
+@xref{Eglot Commands, eglot-events-buffer}, for how to access that
+buffer.  If the value is changed, the connection should be restarted
+using @kbd{M-x eglot-reconnect} for the new value to take effect.
 @c FIXME: Shouldn't the defcustom do this by itself using the :set
-@c attribute?
+@c attribute?  Maybe not because reconnecting is a complex task.
 @xref{Troubleshooting Eglot}, for when this could be useful.
 
 @item eglot-autoshutdown
@@ -1097,8 +1107,8 @@ To apply this to Eglot, and assuming you chose the
                                              :fuzzy t)
                            :pylint (:enabled :json-false)))
          :gopls (:usePlaceholders t)))))
- (python-mode . ((indent-tabs-mode . nil)))
- (go-mode     . ((indent-tabs-mode . t))))
+ (python-base-mode . ((indent-tabs-mode . nil)))
+ (go-mode          . ((indent-tabs-mode . t))))
 @end lisp
 
 @noindent
@@ -1113,7 +1123,7 @@ plists are used inside the value of
 This following form may also be used:
 
 @lisp
-((python-mode
+((python-base-mode
   . ((eglot-workspace-configuration
       . (:pylsp (:plugins (:jedi_completion (:include_params t
                                              :fuzzy t)
@@ -1128,7 +1138,7 @@ This following form may also be used:
 @noindent
 This sets up the value of @code{eglot-workspace-configuration}
 separately depending on the major mode of each of that project's
-buffers.  @code{python-mode} buffers will have the variable set to
+buffers.  @code{python-base-mode} buffers will have the variable set to
 @code{(:pylsp (:plugins ...))}.  @code{go-mode} buffers will have the
 variable set to @code{(:gopls (:usePlaceholders t))}.
 
@@ -1139,7 +1149,7 @@ want to set a different option for 
@code{gopls.usePlaceholders} , you
 may use something like:
 
 @lisp
-((python-mode
+((python-base-mode
   . ((eglot-workspace-configuration
       . (:pylsp (:plugins (:jedi_completion (:include_params t
                                              :fuzzy t)
@@ -1222,7 +1232,7 @@ in @ref{Project-specific configuration}.  Here is an 
example:
 @end lisp
 
 Note that the global value of @code{eglot-workspace-configuration} is
-always overriden if a directory-local value is detected.
+always overridden if a directory-local value is detected.
 
 @node JSONRPC objects in Elisp
 @section JSONRPC objects in Elisp
@@ -1395,8 +1405,6 @@ The remainder of the implementation consists of standard 
Elisp
 techniques to loop over arrays, manage buffers and overlays.
 
 @lisp
-(defvar-local eglot-clangd-inactive-region-overlays '())
-
 (cl-defmethod eglot-handle-notification
   (_server (_method (eql textDocument/inactiveRegions))
            &key regions textDocument &allow-other-keys)
@@ -1404,14 +1412,14 @@ techniques to loop over arrays, manage buffers and 
overlays.
                                      (cl-getf textDocument :uri))))
             (buffer (find-buffer-visiting path)))
       (with-current-buffer buffer
-        (mapc #'delete-overlay eglot-clangd-inactive-region-overlays)
+        (remove-overlays nil nil 'inactive-code t)
         (cl-loop
          for r across regions
          for (beg . end) = (eglot-range-region r)
          for ov = (make-overlay beg end)
          do
          (overlay-put ov 'face 'shadow)
-         (push ov eglot-clangd-inactive-region-overlays)))))
+         (overlay-put ov 'inactive-code t)))))
 @end lisp
 
 @end itemize
@@ -1445,12 +1453,14 @@ indicate the problems or at least provide a hint.
 @node Performance
 @section Performance
 @cindex performance problems, with Eglot
-A common and easy-to-fix cause of performance problems is the length
-of the Eglot events buffer because it represent additional work that
-Eglot must do.  After verifying Eglot is operating correctly but
-slowly, try to customize the variable @code{eglot-events-buffer-size}
-(@pxref{Eglot Variables}) to 0.  This will disable any debug logging
-and may speed things up.
+A common and easy-to-fix cause of performance problems in Eglot
+(especially in older versions) is its events buffer, since it
+represents additional work that Eglot must do (@pxref{Eglot Commands,
+eglot-events-buffer}).  If you find Eglot is operating correctly but
+slowly, try to customize the variable
+@code{eglot-events-buffer-config} (@pxref{Eglot Variables}) and set
+its @code{:size} property to 0.  This will disable recording any
+events and may speed things up.
 
 In other situations, the cause of poor performance lies in the
 language server itself.  Servers use aggressive caching and other
diff --git a/doc/misc/eieio.texi b/doc/misc/eieio.texi
index 8838de38f86..02cb51e6fdd 100644
--- a/doc/misc/eieio.texi
+++ b/doc/misc/eieio.texi
@@ -12,7 +12,7 @@
 @copying
 This manual documents EIEIO, an object framework for Emacs Lisp.
 
-Copyright @copyright{} 2007--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2007--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/emacs-gnutls.texi b/doc/misc/emacs-gnutls.texi
index fafb4c11594..c149531a8bd 100644
--- a/doc/misc/emacs-gnutls.texi
+++ b/doc/misc/emacs-gnutls.texi
@@ -9,7 +9,7 @@
 @copying
 This file describes the Emacs GnuTLS integration.
 
-Copyright @copyright{} 2012--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2012--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/emacs-mime.texi b/doc/misc/emacs-mime.texi
index 19ff415bdaf..96a6328cd47 100644
--- a/doc/misc/emacs-mime.texi
+++ b/doc/misc/emacs-mime.texi
@@ -10,7 +10,7 @@
 @copying
 This file documents the Emacs MIME interface functionality.
 
-Copyright @copyright{} 1998--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1998--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/epa.texi b/doc/misc/epa.texi
index 1aeaef8990f..27a9e2b0ebb 100644
--- a/doc/misc/epa.texi
+++ b/doc/misc/epa.texi
@@ -10,7 +10,7 @@
 @copying
 This file describes EasyPG Assistant @value{VERSION}.
 
-Copyright @copyright{} 2007--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2007--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -456,9 +456,9 @@ public key, it does not prompt for a passphrase for the 
buffer save,
 but it will prompt for your passphrase for file reads every now and
 then, depending on the GnuPG Agent cache configuration.
 
-@cindex tempory files created by easypg assistant
+@cindex temporary files created by easypg assistant
 To encrypt and decrypt files as described above EasyPG Assistant under
-certain circumstances uses intermediate tempory files that contain the
+certain circumstances uses intermediate temporary files that contain the
 plain-text contents of the files it processes.  EasyPG Assistant
 creates them below the directory returned by function
 @code{temporary-file-directory} (@pxref{Unique File Names, ,
diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi
index d7260ffa329..f877fb681fe 100644
--- a/doc/misc/erc.texi
+++ b/doc/misc/erc.texi
@@ -12,7 +12,7 @@
 @copying
 This manual is for ERC @value{ERCVER} @value{ERCDIST}.
 
-Copyright @copyright{} 2005--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2005--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -678,6 +678,14 @@ signals an error.  Users defining personal modules in an 
init file
 should @code{(provide 'erc-my-module)} somewhere to placate ERC.
 Dynamically generating modules on the fly is not supported.
 
+Some older built-in modules have a second name along with a second
+minor-mode toggle, which is just a function alias for its primary
+counterpart.  For practical reasons, ERC does not define a
+corresponding variable alias because contending with indirect
+variables complicates bookkeeping tasks, such as persisting module
+state across IRC sessions.  New modules should definitely avoid
+defining aliases without a good reason.
+
 Some packages have been known to autoload a module's definition
 instead of its minor-mode command, which severs the link between the
 library and the module.  This means that enabling the mode by invoking
@@ -918,16 +926,11 @@ In the latter case, if the first nick in the list is 
already in use,
 other nicks are tried in the list order.
 @end defopt
 
-@defopt erc-format-nick-function
-A function to format a nickname for message display
-
-You can set this to @code{erc-format-@@nick} to display user mode prefix
+@defopt erc-show-speaker-membership-status
+A boolean for including a channel member's @dfn{status prefix} in
+their display name when they speak.
 @end defopt
 
-@example
-(setq erc-format-nick-function 'erc-format-@@nick)
-@end example
-
 @defopt erc-nick-uniquifier
 The string to append to the nick if it is already in use.
 @end defopt
@@ -1053,13 +1056,19 @@ acceptable.
 @section Authenticating via SASL
 @cindex SASL
 
-Regardless of the mechanism or the network, you'll likely have to be
-registered before first use.  Please refer to the network's own
+If you've used @acronym{SASL} elsewhere, you can probably skip to the
+examples below.  Otherwise, if you haven't already registered with
+your network, please do so now, referring to the network's own
 instructions for details.  If you're new to IRC and using a bouncer,
-know that you probably won't be needing SASL for the client-to-bouncer
-connection.  To get started, just add @code{sasl} to
-@code{erc-modules} like any other module.  But before that, please
-explore all custom options pertaining to your chosen mechanism.
+know that you probably won't be needing this for the client-to-bouncer
+connection.
+
+When you're ready to get started, add @code{sasl} to
+@code{erc-modules}, like you would any other module.  If unsure which
+@dfn{mechanism} to choose, stick with the default of @samp{PLAIN}.
+Then try @kbd{C-u M-x erc-tls @key{RET}}, and give your account name
+for the @samp{user} parameter and your account password for the
+@samp{server password}.
 
 @defopt erc-sasl-mechanism
 The name of an SASL subprotocol type as a @emph{lowercase} symbol.
@@ -1307,10 +1316,10 @@ settings (@pxref{Sample configuration via Customize}).
 
 (use-package erc
   :config
-  ;; Prefer SASL to NickServ, colorize nicknames, interpret mIRC colors,
-  ;; and list buffers and channel members in separate side panels.
+  ;; Prefer SASL to NickServ, colorize nicknames, and show side panels
+  ;; with joined channels and members
   (setopt erc-modules
-          (seq-union '(sasl nicks irccontrols bufbar nickbar scrolltobottom)
+          (seq-union '(sasl nicks bufbar nickbar scrolltobottom)
                      erc-modules))
 
   :custom
@@ -1318,6 +1327,8 @@ settings (@pxref{Sample configuration via Customize}).
   (erc-inhibit-multiline-input t)
   (erc-send-whitespace-lines t)
   (erc-ask-about-multiline-input t)
+  ;; Scroll all windows to prompt when submitting input.
+  (erc-scrolltobottom-all t)
 
   ;; Reconnect automatically using a fancy strategy.
   (erc-server-reconnect-function #'erc-server-delayed-check-reconnect)
@@ -1401,13 +1412,13 @@ As mentioned, Customize users can accomplish nearly all 
of the above
 via the Customize interface.  Start by running @kbd{M-x
 customize-group @key{RET} erc @key{RET}}, and search for ``Modules''
 with @kbd{C-s modules @key{RET}}.  Toggle open the flyout menu to
-reveal the full ``widget'' panel, a web-form-like interface for ``Erc
-Modules''.  Tick the boxes for @samp{bufbar}, @samp{irccontrols},
-@samp{nickbar}, @samp{nicks}, @samp{sasl}, and @samp{scrolltobottom}.
+reveal the full @dfn{widget} panel, a web-form-like interface for
+``Erc Modules''.  Tick the boxes for @samp{bufbar}, @samp{nickbar},
+@samp{nicks}, @samp{sasl}, and @samp{scrolltobottom}.
 
 Next, search for the phrases ``Erc Ask About Multiline Input'', ``Erc
-Inhibit Mulitline Input'', and ``Erc Send Whitespace Lines''.  These
-are the print names of three Boolean options that control how ERC
+Inhibit Multiline Input'', and ``Erc Send Whitespace Lines''.  These
+are the print names of three boolean options that control how ERC
 treats prompt input containing line breaks.  When visiting each
 option's section, twirl open its triangle icon to reveal its widget
 UI, and click its @samp{[Toggle]} button to set its value to @code{t}.
@@ -1453,12 +1464,19 @@ To make sure you've got this, try quickly customizing 
the option
 @code{erc-interactive-display}, which lives in the @samp{Erc Buffers}
 group (@kbd{M-x customize-group @key{RET} erc-buffers @key{RET}}).  As
 its doc string explains, the option controls where new buffers show up
-when you do @kbd{M-x erc-tls @key{RET}} or issue certain ``slash''
-commands, like @kbd{/JOIN #emacs-beginners @key{RET}}, at ERC's
+when you do @kbd{M-x erc-tls @key{RET}} or issue certain @dfn{slash
+commands}, like @kbd{/JOIN #emacs-beginners @key{RET}}, at ERC's
 prompt.  Change its value to the symbol @code{buffer} by choosing
 @samp{Use current window} (item @kbd{5}) from the option's
 @samp{[Value Menu]}.  Don't forget to save.
 
+If you need more practice, try enabling the boolean option
+@code{erc-scrolltobottom-all}, which lives in the @samp{Erc Display}
+group (@kbd{M-x customize-group @key{RET} erc-display @key{RET}}).
+When enabled, this option tells the @samp{scrolltobottom} module to
+adjust all ERC windows instead of just the one you're currently typing
+in.
+
 Now it's time to set some key bindings for @code{erc-mode-map}, a
 major-mode keymap active in all ERC buffers.  In general, it's best to
 do this part either entirely or in conjunction with some lisp code in
@@ -1535,8 +1553,8 @@ and save your changes.  Next, customize the related option
 @code{erc-track-priority-faces-only} to the @samp{[Value Menu]} choice
 @samp{all}.  Once again, save your changes.
 
-Let's say you'd like to enable a ``local module'' (ERC's version of a
-local minor mode) in a specific channel.  One way to do that is by
+Let's say you'd like to enable a @dfn{local module} (ERC's version of
+a local minor mode) in a specific channel.  One way to do that is by
 running some code to activate the module if the channel's name
 matches.  Try that now by customizing the option @code{erc-join-hook}.
 Add the following in the value field before saving your changes:
@@ -1548,7 +1566,7 @@ Add the following in the value field before saving your 
changes:
     (erc-keep-place-indicator-mode +1)))
 @end lisp
 
-Lastly, if you really want the two ``slash'' commands defined at the
+Lastly, if you really want the two @dfn{slash commands} defined at the
 end of the previous section, you can put them in any file listed in
 @code{erc-startup-file-list}, such as @file{~/.emacs.d/.ercrc.el}.
 Make sure to put @code{(require 'erc-track)} near the top of the file.
@@ -1670,6 +1688,7 @@ with the default backend, netrc, put a line like the 
following in your
 machine irc.example.net login mynick password sEcReT
 @end example
 
+@anchor{auth-source Server Password}
 @subsubheading Server Passwords
 When retrieving passwords to accompany the IRC @samp{PASS} command
 (@pxref{password parameter}), ERC asks auth-source to match the
@@ -1719,10 +1738,7 @@ auth-source experience.  (@xref{SASL}.)
 @subsubheading Default query behavior
 When preparing entries for your backend, it may help to get a feel for
 how ERC and its modules conduct searches, especially when exploring a
-new context, such as channel keys.  (Hint: in such situations, try
-temporarily setting the variable @code{auth-source-debug} to @code{t}
-and checking @file{*Messages*} periodically for insights into how
-auth-source is operating.)  Overall, though, ERC tries to be
+new context, such as channel keys.  Overall, though, ERC tries to be
 consistent in performing queries across various authentication
 contexts.  Here's what to expect with respect to the @samp{host}
 field, which, by default, most heavily influences the fate of a query:
@@ -1806,6 +1822,33 @@ required by certain channels you join.  When modifying a 
traditional
 @samp{user} field (for example, @samp{login "#fsf"}, in netrc's case).
 The actual key goes in the @samp{password} (or @samp{secret}) field.
 
+@anchor{auth-source Troubleshooting}
+@subheading Troubleshooting
+By default, ERC queries @code{auth-source} for channel keys and server
+passwords (@pxref{auth-source Server Password}), as well as other,
+module-specific credentials.  In general, if you're having trouble
+calling @code{auth-source-search} in a custom query function, like
+@code{erc-auth-source-server-function}, try temporarily setting the
+variable @code{auth-source-debug} to @code{t} and checking
+@file{*Messages*} periodically for insights into how
+@code{auth-source} is operating.
+
+If you're using a @acronym{GPG}-encrypted file and find that
+customizing one of the function-valued query options doesn't solve
+your problem, explore options @code{epg-pinentry-mode} and
+@code{epg-debug} in the @code{epg} Custom group (@pxref{GnuPG
+Pinentry,,, epa, EasyPG Assistant}).  Additionally, keep an eye out
+for an @file{*Error*} buffer, which may contain more specific clues
+about your situation.  If you use the libsecrets integration
+(@pxref{Secret Service API,,, auth, Emacs auth-source}) with something
+like GNOME Keyring, you may need to check the ``remember'' box in the
+passphrase popup dialog to avoid being prompted for confirmation every
+time you run ERC.  If it doesn't work at first, try logging out.  And
+when in doubt, try using the Emacs command @code{secrets-show-secrets}
+to browse the @samp{Login} keyring.  There should be a
+@samp{GnuPG/stored-by} entry with a value of @samp{GnuPG Pinentry} or
+similar.
+
 @node display-buffer
 @subsection display-buffer
 @cindex display-buffer
diff --git a/doc/misc/ert.texi b/doc/misc/ert.texi
index f4a072cf2bc..bd2ad495142 100644
--- a/doc/misc/ert.texi
+++ b/doc/misc/ert.texi
@@ -15,7 +15,7 @@
 @end direntry
 
 @copying
-Copyright @copyright{} 2008, 2010--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2008, 2010--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -526,6 +526,7 @@ to find where a test was defined if the test was loaded 
from a file.
 * Tests and Their Environment:: Don't depend on customizations; no side 
effects.
 * Useful Techniques::           Some examples.
 * erts files::                  Files containing many buffer tests.
+* Syntax Highlighting Tests::   Tests for face assignment.
 @end menu
 
 
@@ -942,6 +943,102 @@ non-@code{nil} value, the test will be skipped.
 If you need to use the literal line single line @samp{=-=} in a test
 section, you can quote it with a @samp{\} character.
 
+@node Syntax Highlighting Tests
+@section Syntax Highlighting Tests
+
+Syntax highlighting is normally provided by the Font Lock minor mode
+that assigns face properties to parts of the buffer.  The
+@code{ert-font-lock} package makes it possible to introduce unit tests
+checking face assignment.  Test assertions are included in code-level
+comments directly and can be read either from inline strings or files.
+
+Test assertion parser extracts tests from comment-only lines.  Every
+comment assertion line starts either with a caret (@samp{^}) or an
+arrow (@samp{<-}).  A caret/arrow should be followed immediately by the
+name of a face to be checked.
+
+The test then checks if the first non-assertion column above the caret
+contains a face expected by the assertion:
+
+@example
+var variable = 11;
+//   ^ font-lock-variable-name-face
+//             ^ font-lock-literal-face
+//               ^ font-lock-punctuation-face
+// this is not an assertion, it's just a comment
+//   ^ font-lock-comment-face
+@end example
+
+The arrow means that the first non-empty column of the assertion line
+will be used for the check:
+
+@example
+var variable = 1;
+// <- font-lock-keyword-face
+  11;
+   // <- font-lock-literal-face
+@end example
+
+@findex ert-font-lock-test-string
+
+The @code{ert-font-lock-test-string} function extracts ERT assertions
+from an inline string.  The @code{javascript-mode} symbol below
+specifies the major mode used for comments and font locking:
+
+@lisp
+(ert-deftest test-font-lock-test-string--correct ()
+  (ert-font-lock-test-string
+   "
+var abc = function(d) @{
+// <- font-lock-keyword-face
+//   ^ font-lock-variable-name-face
+    //        ^ font-lock-keyword-face
+    //             ^ font-lock-variable-name-face
+@};
+"
+   'javascript-mode))
+@end lisp
+
+@findex ert-font-lock-test-file
+
+It is also possible to extract test assertions from a file:
+
+@lisp
+(ert-deftest test-font-lock-test-file--correct ()
+  (ert-font-lock-test-file
+   (ert-resource-file "correct.js")
+   'javascript-mode))
+@end lisp
+
+@findex ert-font-lock-deftest
+
+The @code{ert-font-lock-deftest} macro simplifies inline test
+definition:
+
+@lisp
+(ert-font-lock-deftest test-macro-test--inline
+    emacs-lisp-mode
+  "
+(defun fun ())
+;; ^ font-lock-keyword-face
+;;      ^ font-lock-function-name-face")
+@end lisp
+
+@findex ert-font-lock-deftest-file
+
+The @code{ert-font-lock-deftest-file} macro reads assertions from a
+file:
+
+@lisp
+(ert-font-lock-deftest-file test-macro-test--file
+    "Test reading correct assertions from a file"
+  javascript-mode
+  "correct.js")
+@end lisp
+
+The @code{ert-font-lock-deftest} and @code{ert-font-lock-deftest-file}
+macros accept the same keyword parameters as @code{ert-deftest} i.e.,
+@code{:tag} and @code{:expected-result}.
 
 @node How to Debug Tests
 @chapter How to Debug Tests
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index e8aa8cdc6a3..da5e1ef1d03 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -10,7 +10,7 @@
 @copying
 This manual is for Eshell, the Emacs shell.
 
-Copyright @copyright{} 1999--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1999--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -624,9 +624,11 @@ each argument as a string, separated by a space.
 
 @item env
 @cmindex env
-Prints the current environment variables.  Unlike in Bash, this
-command does not yet support running commands with a modified
-environment.
+With no arguments, print the current environment variables.  If you
+pass arguments to this command, then @command{env} will execute the
+arguments as a command.  If you pass any initial arguments of the form
+@samp{@var{var}=@var{value}}, @command{env} will first set @var{var}
+to @var{value} before running the command.
 
 @item eshell-debug
 @cmindex eshell-debug
@@ -1237,11 +1239,20 @@ command containing @code{foo}.  The n-th argument of 
the last command
 beginning with @code{foo} is accessible by @code{!foo:n}.
 
 @vindex eshell-history-file-name
-The history ring is loaded from a file at the start of every session,
-and written back to the file at the end of every session.  The file path
-is specified in @code{eshell-history-file-name}.  Unlike other shells,
-such as Bash, Eshell can not be configured to keep a history ring of a
-different size than that of the history file.
+@vindex eshell-history-append
+The history is loaded to the history ring from the file
+@code{eshell-history-file-name} at the start of every session, and
+saved to that file at the end of every session.  The default history
+saving behavior is to overwrite the history file with the whole
+history ring of the session.  If @code{eshell-history-append} is
+non-@code{nil}, the history will instead be saved by appending new
+entries from the session to the history file, which could prevent
+potential history loss with multiple Eshell sessions.  Unlike other
+shells, such as Bash, Eshell cannot currently be configured to control
+the size of the history file.  In particular, when
+@code{eshell-history-append} is non-@code{nil}, the size of the file
+will keep increasing, and the recommended way to truncate the file is
+to run the @samp{history -w} command in an Eshell session.
 
 Since the default buffer navigation and searching key-bindings are
 still present in the Eshell buffer, the commands for history
diff --git a/doc/misc/eudc.texi b/doc/misc/eudc.texi
index d82dec971cd..615ab76c326 100644
--- a/doc/misc/eudc.texi
+++ b/doc/misc/eudc.texi
@@ -14,7 +14,7 @@ This file documents EUDC version 1.40.0.
 EUDC is the Emacs Unified Directory Client, a common interface to
 directory servers and contact information.
 
-Copyright @copyright{} 1998, 2000--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1998, 2000--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/eww.texi b/doc/misc/eww.texi
index abd498824c5..5e69b11d347 100644
--- a/doc/misc/eww.texi
+++ b/doc/misc/eww.texi
@@ -8,7 +8,7 @@
 @copying
 This file documents the GNU Emacs Web Wowser (EWW) package.
 
-Copyright @copyright{} 2014--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2014--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/flymake.texi b/doc/misc/flymake.texi
index e0cb79aa546..84a74a9d6ab 100644
--- a/doc/misc/flymake.texi
+++ b/doc/misc/flymake.texi
@@ -13,7 +13,7 @@
 @copying
 This manual is for GNU Flymake (version @value{VERSION}, @value{UPDATED}).
 
-Copyright @copyright{} 2004--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2004--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/forms.texi b/doc/misc/forms.texi
index a7bc49c7dfd..e0221d90fd9 100644
--- a/doc/misc/forms.texi
+++ b/doc/misc/forms.texi
@@ -20,7 +20,7 @@
 @copying
 This file documents Forms mode, a form-editing major mode for GNU Emacs.
 
-Copyright @copyright{} 1989, 1997, 2001--2023 Free Software Foundation,
+Copyright @copyright{} 1989, 1997, 2001--2024 Free Software Foundation,
 Inc.
 
 @quotation
diff --git a/doc/misc/gnus-faq.texi b/doc/misc/gnus-faq.texi
index eb416fe47d6..33c9f3bea81 100644
--- a/doc/misc/gnus-faq.texi
+++ b/doc/misc/gnus-faq.texi
@@ -1,7 +1,7 @@
 @c \input texinfo @c -*-texinfo-*-
 @c Uncomment 1st line before texing this file alone.
 @c %**start of header
-@c Copyright (C) 1995--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1995--2024 Free Software Foundation, Inc.
 @c
 @c @setfilename gnus-faq.info
 @c @settitle Frequently Asked Questions
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 586e4b94ba1..08554d0d9b9 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -8,7 +8,7 @@
 @syncodeindex pg cp
 
 @copying
-Copyright @copyright{} 1995--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1995--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -5832,7 +5832,7 @@ message to the mailing list, and include the original 
message
 @kindex S v @r{(Summary)}
 @findex gnus-summary-very-wide-reply
 Mail a very wide reply to the author of the current article
-(@code{gnus-summary-wide-reply}).  A @dfn{very wide reply} is a reply
+(@code{gnus-summary-very-wide-reply}).  A @dfn{very wide reply} is a reply
 that goes out to all people listed in the @code{To}, @code{From} (or
 @code{Reply-To}) and @code{Cc} headers in all the process/prefixed
 articles.  This command uses the process/prefix convention.
@@ -5868,15 +5868,23 @@ original message but ignore the @code{Reply-To} field
 @findex gnus-summary-mail-forward
 @c @icon{gnus-summary-mail-forward}
 Forward the current article to some other person
-(@code{gnus-summary-mail-forward}).  If no prefix is given, the message
-is forwarded according to the value of (@code{message-forward-as-mime})
-and (@code{message-forward-show-mml}); if the prefix is 1, decode the
-message and forward directly inline; if the prefix is 2, forward message
-as an rfc822 @acronym{MIME} section; if the prefix is 3, decode message and
-forward as an rfc822 @acronym{MIME} section; if the prefix is 4, forward 
message
-directly inline; otherwise, the message is forwarded as no prefix given
-but use the flipped value of (@code{message-forward-as-mime}).  By
-default, the forwarded message is inlined into the mail.
+(@code{gnus-summary-mail-forward}).  If no prefix is given, the
+message is forwarded according to the value of
+(@code{message-forward-as-mime}) and
+(@code{message-forward-show-mml}); if the prefix is 1, decode the
+message and forward directly inline; if the prefix is 2, forward
+message as an rfc822 @acronym{MIME} section; if the prefix is 3,
+decode message and forward as an rfc822 @acronym{MIME} section; if the
+prefix is 4, forward message directly inline; otherwise, the message
+is forwarded as no prefix given but use the negated value of
+(@code{message-forward-as-mime}).  By default, the forwarded message
+is inlined into the mail.
+
+Which headers from the original message are included in the forwarded
+message is determined by options specific to @code{message-mode},
+@pxref{Forwarding,,, message}.  In addition, this command can be given
+the symbolic prefix @samp{a}, using @kbd{M-i a}, to include most original
+headers.
 
 @item S m
 @itemx m
@@ -6235,13 +6243,6 @@ Presumably, you want to use the demon for sending due 
delayed articles.
 Just don't forget to set that up :-)
 @end table
 
-When delaying an article with @kbd{C-c C-j}, Message mode will
-automatically add a @code{"Date"} header with the current time.  In
-many cases you probably want the @code{"Date"} header to reflect the
-time the message is sent instead.  To do this, you have to delete
-@code{Date} from @code{message-draft-headers}.
-
-
 @node Marking Articles
 @section Marking Articles
 @cindex article marking
@@ -19805,7 +19806,7 @@ locally stored articles.
 @chapter Scoring
 @cindex scoring
 
-Other people use @dfn{kill files} (@pxref{Kill Files}, but we here at
+Other people use @dfn{kill files} (@pxref{Kill Files}), but we here at
 Gnus Towers like scoring better than killing, so we'd rather switch
 than fight.  Scoring and score files processing are more powerful and
 faster than processing of kill files.  Scoring also does something
diff --git a/doc/misc/htmlfontify.texi b/doc/misc/htmlfontify.texi
index fa45f9361ab..258c743ac8f 100644
--- a/doc/misc/htmlfontify.texi
+++ b/doc/misc/htmlfontify.texi
@@ -10,7 +10,7 @@
 This manual documents Htmlfontify, a source code -> crosslinked +
 formatted + syntax colorized html transformer.
 
-Copyright @copyright{} 2002--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2002--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/idlwave.texi b/doc/misc/idlwave.texi
index 5577105ab2b..782812169ca 100644
--- a/doc/misc/idlwave.texi
+++ b/doc/misc/idlwave.texi
@@ -23,7 +23,7 @@ Emacs, and interacting with an IDL shell run as a subprocess.
 This is edition @value{EDITION} of the IDLWAVE User Manual for IDLWAVE
 @value{VERSION}.
 
-Copyright @copyright{} 1999--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1999--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/ido.texi b/doc/misc/ido.texi
index dca92f00069..ad293f41c2f 100644
--- a/doc/misc/ido.texi
+++ b/doc/misc/ido.texi
@@ -7,7 +7,7 @@
 @copying
 This file documents the Ido package for GNU Emacs.
 
-Copyright @copyright{} 2013--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2013--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/info.texi b/doc/misc/info.texi
index ba00dbcf2bd..01c7f614e7d 100644
--- a/doc/misc/info.texi
+++ b/doc/misc/info.texi
@@ -15,7 +15,7 @@
 This file describes how to use Info, the menu-driven GNU
 documentation system.
 
-Copyright @copyright{} 1989, 1992, 1996--2023 Free Software Foundation,
+Copyright @copyright{} 1989, 1992, 1996--2024 Free Software Foundation,
 Inc.
 
 @quotation
@@ -1148,6 +1148,7 @@ move between menu items.
 @section @kbd{M-n} creates a new independent Info buffer in Emacs
 
 @kindex M-n @r{(Info mode)}
+@kindex C-x x n
 @findex clone-buffer
 @cindex multiple Info buffers
   If you are reading Info in Emacs, you can select a new independent
diff --git a/doc/misc/mairix-el.texi b/doc/misc/mairix-el.texi
index 12016bee387..024d7bb038a 100644
--- a/doc/misc/mairix-el.texi
+++ b/doc/misc/mairix-el.texi
@@ -5,7 +5,7 @@
 @include docstyle.texi
 
 @copying
-Copyright @copyright{} 2008--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2008--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/message.texi b/doc/misc/message.texi
index 8064af53fc6..d881244c735 100644
--- a/doc/misc/message.texi
+++ b/doc/misc/message.texi
@@ -9,7 +9,7 @@
 @copying
 This file documents Message, the Emacs message composition mode.
 
-Copyright @copyright{} 1996--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1996--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/mh-e.texi b/doc/misc/mh-e.texi
index 75788f18f03..3e98a14ecfc 100644
--- a/doc/misc/mh-e.texi
+++ b/doc/misc/mh-e.texi
@@ -25,7 +25,7 @@
 This is version @value{VERSION}@value{EDITION} of @cite{The MH-E
 Manual}, last updated @value{UPDATED}.
 
-Copyright @copyright{} 1995, 2001--2003, 2005--2023 Free Software
+Copyright @copyright{} 1995, 2001--2003, 2005--2024 Free Software
 Foundation, Inc.
 
 @c This dual license has been agreed upon by the FSF.
diff --git a/doc/misc/modus-themes.org b/doc/misc/modus-themes.org
index 5a53426dfee..45f96778203 100644
--- a/doc/misc/modus-themes.org
+++ b/doc/misc/modus-themes.org
@@ -52,7 +52,7 @@ Current development target is {{{development-version}}}.
 :custom_id: h:b14c3fcb-13dd-4144-9d92-2c58b3ed16d3
 :end:
 
-Copyright (C) 2020-2023  Free Software Foundation, Inc.
+Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 #+begin_quote
 Permission is granted to copy, distribute and/or modify this document
@@ -90,7 +90,7 @@ The Modus themes consist of eight themes, divided into four 
subgroups.
   are variants of the two main themes.  They slightly tone down the
   intensity of the background and provide a bit more color variety.
   ~modus-operandi-tinted~ has a set of base tones that are shades of
-  light ochre (earthly colors), while ~modus-vivendi-tinted~ gives a
+  light ocher (earthly colors), while ~modus-vivendi-tinted~ gives a
   night sky impression.
 
 - Deuteranopia themes :: ~modus-operandi-deuteranopia~ and its
@@ -2518,7 +2518,7 @@ manual, here is what Protesilaos uses:
         ;; Add a nuanced background as well.
         (bg-prompt bg-magenta-nuanced)
         (fg-prompt magenta-cooler)
-        ;; Tweak some more constructs for stylistic constistency.
+        ;; Tweak some more constructs for stylistic consistency.
         (name blue-warmer)
         (identifier magenta-faint)
         (keybind magenta-cooler)
@@ -2717,7 +2717,7 @@ For a more elaborate design, it is better to inspect the 
source code of
 [[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Use theme colors in code with 
modus-themes-with-colors]].
 
 #+findex: modus-themes-get-color-value
-The fuction ~modus-themes-get-color-value~ can be called from Lisp to
+The function ~modus-themes-get-color-value~ can be called from Lisp to
 return the value of a color from the active Modus theme palette.  It
 takea a =COLOR= argument and an optional =OVERRIDES=.
 
@@ -2886,7 +2886,7 @@ above:
 The reason we no longer provide this option is because it depends on a
 non-~nil~ value for ~x-underline-at-descent-line~.  That variable
 affects ALL underlines, including those of links.  The effect is
-intrusive and looks awkard in prose.
+intrusive and looks awkward in prose.
 
 As such, the Modus themes no longer provide that option but instead
 offer this piece of documentation to make the user fully aware of the
@@ -3229,7 +3229,7 @@ specification of that variable looks like this:
 
 With the exception of ~org-verbatim~ and ~org-code~ faces, everything else
 uses the corresponding type of emphasis: a bold typographic weight, or
-italicised, underlined, and struck through text.
+italicized, underlined, and struck through text.
 
 The best way for users to add some extra attributes, such as a
 foreground color, is to define their own faces and assign them to the
@@ -4396,7 +4396,7 @@ advanced customization options of the themes.
 [[#h:f4651d55-8c07-46aa-b52b-bed1e53463bb][Advanced customization]].
 
 In the following example, we are assuming that the user wants to (i)
-re-use color variables provided by the themes, (ii) be able to retain
+reuse color variables provided by the themes, (ii) be able to retain
 their tweaks while switching between ~modus-operandi~ and ~modus-vivendi~,
 and (iii) have the option to highlight either the foreground of the
 parentheses or the background as well.
@@ -4416,7 +4416,7 @@ Then we can update our preference with this:
 (setq my-highlight-parentheses-use-background nil)
 #+end_src
 
-To re-use colors from the themes, we must wrap our code in the
+To reuse colors from the themes, we must wrap our code in the
 ~modus-themes-with-colors~ macro.  Our implementation must interface with
 the variables ~highlight-parentheses-background-colors~ and/or
 ~highlight-parentheses-colors~.
@@ -5026,7 +5026,7 @@ more effective than trying to do the same with either red 
or blue (the
 latter is the least effective in that regard).
 
 When we need to work with several colors, it is always better to have
-sufficient manoeuvring space, especially since we cannot pick arbitrary
+sufficient maneuvering space, especially since we cannot pick arbitrary
 colors but only those that satisfy the accessibility objectives of the
 themes.
 
@@ -5080,7 +5080,7 @@ each of the three channels of light (red, green, blue).  
For example:
 : xrandr --output LVDS1 --brightness 1.0 --gamma 0.76:0.75:0.68
 
 Typography is another variable.  Some font families are blurry at small
-point sizes.  Others may have a regular weight that is lighter (thiner)
+point sizes.  Others may have a regular weight that is lighter (thinner)
 than that of their peers which may, under certain circumstances, cause a
 halo effect around each glyph.
 
@@ -5132,7 +5132,7 @@ it is already understood that one must follow the 
indicator or headline
 to view its contents and (ii) underlining everything would make the
 interface virtually unusable.
 
-Again, one must exercise judgement in order to avoid discrimination,
+Again, one must exercise judgment in order to avoid discrimination,
 where "discrimination" refers to:
 
 + The treatment of substantially different magnitudes as if they were of
@@ -5206,7 +5206,7 @@ the themes, which is partially fleshed out in this manual.
 
 With regard to the artistic aspect (where "art" qua skill may amount to
 an imprecise science), there is no hard-and-fast rule in effect as it
-requires one to exercize discretion and make decisions based on
+requires one to exercise discretion and make decisions based on
 context-dependent information or constraints.  As is true with most
 things in life, when in doubt, do not cling on to the letter of the law
 but try to understand its spirit.
diff --git a/doc/misc/newsticker.texi b/doc/misc/newsticker.texi
index 4a0311cad42..a2ceedf7399 100644
--- a/doc/misc/newsticker.texi
+++ b/doc/misc/newsticker.texi
@@ -15,7 +15,7 @@ This manual documents Newsticker, a feed reader for Emacs.  It
 corresponds to Emacs version @value{EMACSVER}.
 
 @noindent
-Copyright @copyright{} 2004--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2004--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/nxml-mode.texi b/doc/misc/nxml-mode.texi
index a19c6a8db6b..90a8858fcbf 100644
--- a/doc/misc/nxml-mode.texi
+++ b/doc/misc/nxml-mode.texi
@@ -9,7 +9,7 @@
 This manual documents nXML mode, an Emacs major mode for editing
 XML with RELAX NG support.
 
-Copyright @copyright{} 2007--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2007--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/octave-mode.texi b/doc/misc/octave-mode.texi
index bdeaf31cdc0..437aac35292 100644
--- a/doc/misc/octave-mode.texi
+++ b/doc/misc/octave-mode.texi
@@ -6,7 +6,7 @@
 @c %**end of header
 
 @copying
-Copyright @copyright{} 1996--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1996--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/org-setup.org b/doc/misc/org-setup.org
index e6ace716077..50fdd57bd8a 100644
--- a/doc/misc/org-setup.org
+++ b/doc/misc/org-setup.org
@@ -1,6 +1,6 @@
 # SETUPFILE for Org manual
 
-# Copyright (C) 2021-2023 Free Software Foundation, Inc.
+# Copyright (C) 2021-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/doc/misc/org.org b/doc/misc/org.org
index 6ca14c851b0..05ab5b36ca0 100644
--- a/doc/misc/org.org
+++ b/doc/misc/org.org
@@ -4606,7 +4606,7 @@ checked.
 #+cindex: statistics, for checkboxes
 #+cindex: checkbox statistics
 #+cindex: @samp{COOKIE_DATA}, property
-#+vindex: org-hierarchical-checkbox-statistics
+#+vindex: org-checkbox-hierarchical-statistics
 The =[2/4]= and =[1/3]= in the first and second line are cookies
 indicating how many checkboxes present in this entry have been checked
 off, and the total number of checkboxes present.  This can give you an
@@ -4614,7 +4614,7 @@ idea on how many checkboxes remain, even without opening 
a folded
 entry.  The cookies can be placed into a headline or into (the first
 line of) a plain list item.  Each cookie covers checkboxes of direct
 children structurally below the headline/item on which the cookie
-appears[fn:: Set the variable ~org-hierarchical-checkbox-statistics~
+appears[fn:: Set the variable ~org-checkbox-hierarchical-statistics~
 if you want such cookies to count all checkboxes below the cookie, not
 just those belonging to direct children.].  You have to insert the
 cookie yourself by typing either =[/]= or =[%]=.  With =[/]= you get
@@ -22315,7 +22315,7 @@ that are mentioned in the manual.  For a more complete 
list, use
 
 This manual is for Org version {{{version}}}.
 
-Copyright \copy 2004--2023 Free Software Foundation, Inc.
+Copyright \copy 2004--2024 Free Software Foundation, Inc.
 
 #+begin_quote
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/pcl-cvs.texi b/doc/misc/pcl-cvs.texi
index b64eaf2667e..e1504b08a3a 100644
--- a/doc/misc/pcl-cvs.texi
+++ b/doc/misc/pcl-cvs.texi
@@ -7,7 +7,7 @@
 @c %**end of header
 
 @copying
-Copyright @copyright{} 1991--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1991--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/pgg.texi b/doc/misc/pgg.texi
index ea69499a140..9cb7b937fff 100644
--- a/doc/misc/pgg.texi
+++ b/doc/misc/pgg.texi
@@ -10,7 +10,7 @@
 This file describes PGG @value{VERSION}, an Emacs interface to various
 PGP implementations.
 
-Copyright @copyright{} 2001, 2003--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2001, 2003--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/rcirc.texi b/doc/misc/rcirc.texi
index 6b10d1ab2a4..9ae4bb4a17c 100644
--- a/doc/misc/rcirc.texi
+++ b/doc/misc/rcirc.texi
@@ -6,7 +6,7 @@
 @c %**end of header
 
 @copying
-Copyright @copyright{} 2006--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2006--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -929,6 +929,7 @@ Manual}, for details.
 @cindex date time
 @cindex format time stamp
 @vindex rcirc-time-format
+@vindex rcirc-log-time-format
 
 @code{rcirc-time-format} is the format used for the time stamp.  Here's
 how to include the date in the time stamp:
@@ -937,6 +938,9 @@ how to include the date in the time stamp:
 (setopt rcirc-time-format "%Y-%m-%d %H:%M ")
 @end example
 
+For log files, a different time format can be specified using the
+@code{rcirc-log-time-format} user option.
+
 @findex rcirc-when
 If you don't wish to use verbose time formatting all the time, you can
 use the @code{rcirc-when} command to display a complete timestamp for
diff --git a/doc/misc/reftex.texi b/doc/misc/reftex.texi
index 72c4283aa46..5adc616e798 100644
--- a/doc/misc/reftex.texi
+++ b/doc/misc/reftex.texi
@@ -45,7 +45,7 @@ This manual documents @RefTeX{} (version @value{VERSION}), a 
package
 to do labels, references, citations and indices for LaTeX documents
 with Emacs.
 
-Copyright @copyright{} 1997--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1997--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/remember.texi b/doc/misc/remember.texi
index 03bc4a0e868..dabd2e6b161 100644
--- a/doc/misc/remember.texi
+++ b/doc/misc/remember.texi
@@ -10,7 +10,7 @@
 @copying
 This manual is for Remember Mode, as distributed with Emacs @value{EMACSVER}.
 
-Copyright @copyright{} 2001, 2004--2005, 2007--2023 Free Software
+Copyright @copyright{} 2001, 2004--2005, 2007--2024 Free Software
 Foundation, Inc.
 
 @quotation
diff --git a/doc/misc/sasl.texi b/doc/misc/sasl.texi
index 89d32b8e916..7abee48e8d8 100644
--- a/doc/misc/sasl.texi
+++ b/doc/misc/sasl.texi
@@ -9,7 +9,7 @@
 @copying
 This file describes the Emacs SASL library, version @value{VERSION}.
 
-Copyright @copyright{} 2000, 2004--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2000, 2004--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/sc.texi b/doc/misc/sc.texi
index 9bf7c36b481..5176797cde8 100644
--- a/doc/misc/sc.texi
+++ b/doc/misc/sc.texi
@@ -15,7 +15,7 @@
 This document describes Supercite, an Emacs package for citing and
 attributing replies to mail and news messages.
 
-Copyright @copyright{} 1993, 2001--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1993, 2001--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/sem-user.texi b/doc/misc/sem-user.texi
index d7995550e2a..a00c91207ad 100644
--- a/doc/misc/sem-user.texi
+++ b/doc/misc/sem-user.texi
@@ -1,5 +1,5 @@
 @c This is part of the Semantic manual.
-@c Copyright (C) 1999--2005, 2007, 2009--2023 Free Software Foundation,
+@c Copyright (C) 1999--2005, 2007, 2009--2024 Free Software Foundation,
 @c Inc.
 @c See file semantic.texi for copying conditions.
 
diff --git a/doc/misc/semantic.texi b/doc/misc/semantic.texi
index af3619a75a6..f6cabed6ea6 100644
--- a/doc/misc/semantic.texi
+++ b/doc/misc/semantic.texi
@@ -25,7 +25,7 @@
 @copying
 This manual documents the Semantic library and utilities.
 
-Copyright @copyright{} 1999--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1999--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/ses.texi b/doc/misc/ses.texi
index cfca9c25ebb..8500a0f08c4 100644
--- a/doc/misc/ses.texi
+++ b/doc/misc/ses.texi
@@ -12,7 +12,7 @@
 @copying
 This file documents @acronym{SES}: the Simple Emacs Spreadsheet.
 
-Copyright @copyright{} 2002--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2002--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -91,8 +91,8 @@ To report bugs, use @kbd{M-x report-emacs-bug}.
 @item Printer functions for control of cell appearance.
 @item Intuitive keystroke commands: C-o = insert row, M-o = insert column, etc.
 @item ``Spillover'' of lengthy cell values into following blank cells.
-@item Header line shows column letters or a selected row.
-@item Completing-read for entering symbols as cell values.
+@item Header line shows column letters.
+@item Completing-read for entering symbols of named cells when editing 
formulas.
 @item Cut, copy, and paste can transfer formulas and printer functions.
 @item Import and export of tab-separated values or tab-separated formulas.
 @item Plaintext, easily-hacked file format.
@@ -109,12 +109,12 @@ If you want to get started quickly and think that you 
know what to
 expect from a simple spreadsheet, this chapter may be all that you
 need.
 
-First, visit a new file with the @file{.ses} extension.
+First, visit a new file with the @file{.ses} file name extension.
 Emacs presents you with an empty spreadsheet containing a single cell.
 
-Begin by inserting a headline: @kbd{"Income"@key{RET}}.  The double
-quotes indicate that this is a text cell.  (Notice that Emacs
-automatically inserts the closing quotation mark.)
+Begin by inserting a headline: @kbd{"Income@key{RET}}.  The double
+quotes indicate that you are editing a text cell, it is not part of
+the cell value, and no closing quotation mark is needed.
 
 To insert your first income value, you must first resize the
 spreadsheet.  Press @key{TAB} to add a new cell and navigate back up
@@ -138,9 +138,10 @@ To add up the values, enter a Lisp expression:
 (+ A2 A3 A4 A5)
 @end example
 
-Perhaps you want to add a cell to the right of cell A4 to explain
-why you have a negative entry.  Pressing @kbd{TAB} in that cell
-adds an entire new column @samp{B}, where you can add such a note.
+Perhaps you want to add a cell to the right of cell @samp{A4} to
+explain why you have a negative entry.  Pressing @kbd{TAB} in that
+cell adds an entire new column @samp{B}, where you can add such a
+note.
 
 The column is fairly narrow by default, but pressing @kbd{w} allows
 you to resize it as needed.  Make it 20 characters wide.  You can
@@ -158,19 +159,24 @@ A       B
 @end group
 @end example
 
-By default, the labels in column B are right-justified.  To change
-that, you can enter a printer function for the whole column, using
-e.g., @kbd{M-p ("%s")}.  You can override a column's printer function
-in any individual cell using @kbd{p}.
+By default, the cell value print-out is right aligned, that is the
+reason for such an alignment for the notes in column @samp{B}.  To
+change that, you can enter a printer function for the whole column,
+using e.g., @kbd{M-p ("%s")}. Enclosing @code{"%s"} into a list tells
+@acronym{SES} to align left.  You can override a column's printer
+function in any individual cell using @kbd{p}.
+
+@c TODO : propagate extra explanation from the French version.
 
 If Joe pays back his loan, you might blank that entry; e.g., by
-positioning the cursor in cell A5 and pressing @kbd{C-d} twice.
-If you do that, the total cell will display @samp{######}.  That is
-because the regular @code{+} operator does not handle a range that
-contains some empty cells.  Instead of emptying the cell, you could
-enter a literal @samp{0}, or delete the entire row using @kbd{C-k}.
-An alternative is to use the special function @code{ses+} instead of
-the regular @code{+}:
+positioning the cursor in cell A5 and pressing @kbd{C-d}.  If you do
+that, the total printed out in cell A6 will display @samp{######}.
+That is because the value in an empty cell is typically @code{nil},
+and the regular @code{+} operator fails to handle a range that
+contains that value.  Instead of emptying the cell, you could enter a
+literal @samp{0}, or delete the entire row using @kbd{C-k}.  An
+alternative is to use the special function @code{ses+} instead of the
+regular @code{+}:
 
 @example
 (ses+ A2 A3 A4 A5)
@@ -195,6 +201,11 @@ remove blank cells from the returned list, which enables 
using
 (apply '+ (ses-range A2 A5 !))
 @end lisp
 
+Actually, both options are not exactly equivalent as the former makes
+the summing in reversed order of argument, and the latter in the same
+order. You can also reverse the order of arguments returned by
+@code{ses-range} with the @code{<} modifier.
+
 @c ===================================================================
 
 @node The Basics
@@ -209,7 +220,7 @@ remove blank cells from the returned list, which enables 
using
 @findex keyboard-quit
 
 To create a new spreadsheet, visit a nonexistent file whose name ends
-with ".ses".  For example, @kbd{C-x C-f test.ses @key{RET}}.
+with @file{.ses}.  For example, @kbd{C-x C-f test.ses @key{RET}}.
 
 
 A @dfn{cell identifier} is a symbol with a column letter and a row
@@ -224,18 +235,18 @@ Moves point to cell, specified by identifier 
(@code{ses-jump}). Unless
 the cell is a renamed cell, the identifier is case-insensitive. A
 prefix argument @math{n} move to cell with coordinates @math{(n\div R,
 n \% C)} for a spreadsheet of @math{R} rows and @math{C} columns, and
-A1 being of coordinates @math{(0,0)}. The way the identifier or the
-command prefix argument are interpreted can be customized through
+@samp{A1} being of coordinates @math{(0,0)}. The way the identifier or
+the command prefix argument are interpreted can be customized through
 variables @code{ses-jump-cell-name-function} and
 @code{ses-jump-prefix-function}.
 @end table
 
 Point is always at the left edge of a cell, or at the empty endline.
 When mark is inactive, the current cell is underlined.  When mark is
-active, the range is the highlighted rectangle of cells (@acronym{SES} always
-uses transient mark mode).  Drag the mouse from A1 to A3 to create the
-range A1-A2.  Many @acronym{SES} commands operate only on single cells, not
-ranges.
+active, the range is the highlighted rectangle of cells (@acronym{SES}
+always uses transient mark mode).  Drag the mouse from @samp{A1} to
+@samp{A3} to create the range @samp{A1-A2}.  Many @acronym{SES}
+commands operate only on single cells, not ranges.
 
 @table @kbd
 @item C-@key{SPC}
@@ -288,11 +299,11 @@ Self-insert a digit (@code{ses-read-cell}).
 Self-insert a negative number (@code{ses-read-cell}).
 
 @item .
-Self-insert a fractional number (@code{ses-read-cell}).
+Self-insert a decimal number (@code{ses-read-cell}).
 
 @item "
-Self-insert a quoted string.  The ending double-quote
-is inserted for you (@code{ses-read-cell}).
+Self-insert a string.  The ending double-quote is inserted for you
+(@code{ses-read-cell}).
 
 @item (
 Self-insert an expression.  The right-parenthesis is inserted for you
@@ -308,9 +319,10 @@ to list the named cells symbols in a help buffer.
 @end table
 
 @item ' @r{(apostrophe)}
-Enter a symbol (ses-read-symbol).  @acronym{SES} remembers all symbols that 
have
-been used as formulas, so you can type just the beginning of a symbol
-and use @kbd{@key{SPC}}, @kbd{@key{TAB}}, and @kbd{?} to complete it.
+Enter a symbol (@code{ses-read-symbol}).  @acronym{SES} remembers all
+symbols that have been used as formulas, so you can type just the
+beginning of a symbol and use @kbd{@key{SPC}}, @kbd{@key{TAB}}, and
+@kbd{?} to complete it.
 @end table
 
 To enter something else (e.g., a vector), begin with a digit, then
@@ -421,8 +433,8 @@ string is right-aligned within the print cell.  To get 
left-alignment,
 use parentheses: @samp{("$%.2f")}.
 @item
 A printer can also be a one-argument function, the result of which is
-a string (right-aligned) or list of one string (left-aligned). Such a
-function can be in turn configured as:
+a string (to get right alignment) or list of one string (to get left
+alignment). Such a function can be in turn configured as:
 @itemize
 @item
 A lambda expression, for instance:
@@ -495,7 +507,7 @@ To list the local printers in a help buffer.
 Except for @code{ses-prin1}, the other standard printers are suitable
 only for cells, not columns or default, because they format the value
 using the column-printer (or default-printer if @code{nil}) and then
-center the result:
+post-process the result, eg.@: center it:
 
 @ftable @code
 @item ses-center
@@ -505,13 +517,13 @@ Just centering.
 Centering with spill-over to following blank cells.
 
 @item ses-dashfill
-Centering using dashes (-) instead of spaces.
+Centering using dashes (@samp{-}) instead of spaces.
 
 @item ses-dashfill-span
 Centering with dashes and spill-over.
 
 @item ses-tildefill-span
-Centering with tildes (~) and spill-over.
+Centering with tildes (@samp{~}) and spill-over.
 
 @item ses-prin1
 This is the fallback printer, used when calling the configured printer
@@ -545,9 +557,9 @@ you can add some code like this to your @file{.emacs} init 
file:
      'euro
      (lambda (x)
        (cond
-       ((null x) "")
-       ((numberp x) (format "%.2f€" x))
-       (t (ses-center-span x ?# 'ses-prin1)))))))
+        ((null x) "")
+        ((numberp x) (format "%.2f€" x))
+        (t (ses-center-span x ?# 'ses-prin1)))))))
 (add-hook 'ses-mode-hook 'my-ses-mode-hook)
 @end lisp
 
@@ -599,29 +611,31 @@ s-expression (using @code{ses-prin1}), centered and 
surrounded by
 @code{#} filling.
 @end itemize
 
-Another precaution to take is to avoid stack overflow due to a
-printer function calling itself indefinitely.  This mistake can
-happen when you use a local printer as a column printer,
-and this local printer implicitly calls the current column printer, so it
-will call itself recursively.  Imagine for instance that you want to
-create some local printer @code{=fill} that would center the content
-of a cell and surround it by equal signs @code{=}, and you do it this
+Another precaution to take is to avoid stack overflow due to a printer
+function calling itself indefinitely.  This mistake can happen when
+you use a local printer as a column printer, and this local printer
+implicitly calls the current column printer, so it will call itself
+recursively.  Imagine for instance that you want to create some local
+printer @code{=fill} that would center the content of a cell and
+surround it by equal signs @code{=}, and you do it (errounously) this
 way:
 
 @lisp
+;; ERRONEOUS CODE
 (lambda (x)
   (cond
    ((null x) "")
    (t (ses-center x 0 ?=))))
 @end lisp
 
-Because @code{=fill} uses the standard printer @code{ses-center} without
-explicitly passing any printer to it, @code{ses-center} will call the
-current column printer if any, or the spreadsheet default printer
-otherwise.  So using @code{=fill} as a column printer will result in a
-stack overflow in this column.  SES does not check for that;
-you just have to be careful.  For instance, re-write @code{=fill} like
-this:
+Because @code{=fill} uses the standard printer @code{ses-center}
+without explicitly passing any printer to it, @code{ses-center} will
+call the current column printer if any, or the spreadsheet default
+printer otherwise.  So using @code{=fill} as a column printer will
+result in a stack overflow in this column on any non empty cell as
+@code{ses-center} will recursively recall the function that has called
+it.  @acronym{SES} does not check for that; you just have to be
+careful.  For instance, re-write @code{=fill} like this:
 
 @lisp
 (lambda (x)
@@ -631,11 +645,17 @@ this:
    (t (ses-center-span x ?# 'ses-prin1))))
 @end lisp
 
+The code above is fixed as @code{ses-center} and
+@code{ses-center-span} are both called with an explicit last
+@var{printer} argument, respectively @code{" %s "} and
+@code{'ses-prin1}.
+
 The code above applies the @code{=} filling only to strings; it also
 surrounds the string by one space on each side before filling with
-@code{=} signs.  So the string @samp{Foo} will be displayed like @samp{@w{===
-Foo ===}} in an 11 character wide column.  Anything other than an empty cell
-or a non-string is displayed as an error by using @code{#} filling.
+@code{=} signs.  So the string @samp{Foo} will be displayed like
+@samp{@w{=== Foo ===}} in an 11 character wide column.  Any value that
+is neither @code{nil} (ie.@: an empty cell) nor a string is displayed
+as an error by using @code{#} filling.
 
 @node Clearing cells
 @section Clearing cells
@@ -647,7 +667,7 @@ These commands set both formula and printer to @code{nil}:
 
 @table @kbd
 @item @key{DEL}
-Clear cell and move left (@code{ses-clear-cell-backward}).
+Move left and clear cell  (@code{ses-clear-cell-backward}).
 
 @item C-d
 Clear cell and move right (@code{ses-clear-cell-forward}).
@@ -699,9 +719,10 @@ Paste from kill ring (@code{yank}).  The paste functions 
behave
 differently depending on the format of the text being inserted:
 @itemize @bullet
 @item
-When pasting cells that were cut from a @acronym{SES} buffer, the print text is
-ignored and only the attached formula and printer are inserted; cell
-references in the formula are relocated unless you use @kbd{C-u}.
+When pasting cells that were cut or copied from a @acronym{SES}
+buffer, the print text is ignored and only the attached formula and
+printer are inserted; cell references in the formula are relocated
+unless you use @kbd{C-u}.
 @item
 The pasted text overwrites a rectangle of cells whose top left corner
 is the current cell.  If part of the rectangle is beyond the edges of
@@ -738,8 +759,11 @@ By default, a newly-created spreadsheet has 1 row and 1 
column.  The
 column width is 7 and the default printer is @samp{"%.7g"}.  Each of these
 can be customized.  Look in group ``ses''.
 
-After entering a cell value, point normally moves right to the next
-cell.  You can customize @code{ses-after-entry-functions} to move left or
+After entering a cell value, normally, @code{forward-char} is called,
+which moves point right to the next cell@c TODO propagate extra
+                                        @c explanation from the French
+                                        @c version.
+.  You can customize @code{ses-after-entry-functions} to move left or
 up or down.  For diagonal movement, select two functions from the
 list.
 
@@ -747,6 +771,7 @@ list.
 @code{ses-jump-cell-name-function} is a customizable variable by
 default set to the @code{upcase} function. This function is called
 when you pass a cell name to the @command{ses-jump} command (@kbd{j}),
+@c TODO : propagate extra explanation from the French version.
 it changes the entered cell name to that where to jump. The default
 setting @code{upcase} allows you to enter the cell name in low
 case. Another use of @code{ses-jump-cell-name-function} could be some
@@ -763,8 +788,9 @@ when you give a prefix argument to the @command{ses-jump} 
command
 the prefix argument. Cell coordinates are in the form of a cons, for
 instance @code{(1 . 0)} for cell @code{A2}. The default setting
 @code{ses-jump-prefix} will number cells left to right and then top
-down, so assuming a 4x3 spreadsheet prefix argument 0 jumps to cell
-A1, prefix argument 2 jumps to C1, prefix argument 3 jumps to A2, etc.
+down, so assuming a 4x3 spreadsheet prefix argument @samp{0} jumps to
+cell @samp{A1}, prefix argument @samp{2} jumps to @samp{C1}, prefix
+argument @samp{3} jumps to @samp{A2}, etc.
 
 @vindex ses-mode-hook
 @code{ses-mode-hook} is a normal mode hook (list of functions to
@@ -813,7 +839,7 @@ Rename a cell from a standard A1-like name to any string 
that can be a
 valid local variable name (See also @ref{Nonrelocatable references}).
 @item M-x ses-repair-cell-reference-all
 @findex ses-repair-cell-reference-all
-When you interrupt a cell formula update by clicking @kbd{C-g}, then
+When you interrupt a cell formula update by typing @kbd{C-g}, then
 the cell reference link may be broken, which will jeopardize automatic
 cell update when any other cell on which it depends is changed. To
 repair that use function @code{ses-repair-cell-reference-all}
@@ -891,17 +917,17 @@ and the new row is included in the sum.
 While entering or editing a formula in the minibuffer, you can select
 a range in the spreadsheet (using mouse or keyboard), then paste a
 representation of that range into your formula.  Suppose you select
-A1-C1:
+@samp{A1-C1}:
 
 @table @kbd
 @item [S-mouse-3]
-Inserts "A1 B1 C1" @code{(ses-insert-range-click})
+Inserts @samp{A1 B1 C1} (@code{ses-insert-range-click})
 
 @item C-c C-r
 Keyboard version (@code{ses-insert-range}).
 
 @item [C-S-mouse-3]
-Inserts "(ses-range A1 C1)" (@code{ses-insert-ses-range-click}).
+Inserts @samp{(ses-range A1 C1)} (@code{ses-insert-ses-range-click}).
 
 @item C-c C-s
 Keyboard version (@code{ses-insert-ses-range}).
@@ -909,7 +935,8 @@ Keyboard version (@code{ses-insert-ses-range}).
 
 If you delete the @var{from} or @var{to} cell for a range, the nearest
 still-existing cell is used instead.  If you delete the entire range,
-the formula relocator will delete the ses-range from the formula.
+the formula relocator will delete the @samp{ses-range} from the
+formula.
 
 If you insert a new row just beyond the end of a one-column range, or
 a new column just beyond a one-row range, the new cell is included in
@@ -1018,7 +1045,7 @@ instead of
 @end lisp
 
 @item (ses+ &rest @var{args})
-Sum of non-blank arguments.
+Sum of non-blank arguments taken in reverse order.
 
 @item (ses-average @var{list})
 Average of non-blank elements in @var{list}.  Here the list is passed
@@ -1033,13 +1060,15 @@ as a single argument, since you'll probably use it with 
@code{ses-range}.
 
 Special cell values:
 @itemize
-@item nil prints the same as "", but allows previous cell to spill over.
+@item nil prints typically the same as "", but allows previous cell to spill 
over.
 @item '*skip* replaces nil when the previous cell actually does spill over;
 nothing is printed for it.
 @item '*error* indicates that the formula signaled an error instead of
 producing a value: the print cell is filled with hash marks (#).
 @end itemize
 
+@c TODO propagate extra explanation from the French version.
+
 If the result from the printer function is too wide for the cell and
 the following cell is @code{nil}, the result will spill over into the
 following cell.  Very wide results can spill over several cells.  If
@@ -1066,12 +1095,14 @@ this to undo the effect of @kbd{t}.
 
 When a printer function signals an error, the fallback printer
 @findex ses-prin1
-@code{ses-prin1} is substituted.  This is useful when your column printer
-is numeric-only and you use a string as a cell value.  Note that the
-standard default printer is @samp{"%.7g"} which is numeric-only, so cells
-that are empty of contain strings will use the fallback printer.
-@kbd{c} on such cells will display ``Format specifier doesn't match
-argument type''.
+@code{ses-prin1} is substituted.  This is useful when your printer is
+numeric-only and you use a string as a cell value.  Note that the
+standard default printer is @samp{"%.7g"} which is numeric-only, so
+cells for which the standard default printer applies, and that are not
+empty and do not contain a number will use the fallback printer
+@code{ses-prin1}, for instance cells that contain strings will do
+that.  @kbd{c} on such cells will display ``Format specifier doesn't
+match argument type''.
 
 
 @node Import and export
@@ -1103,11 +1134,11 @@ the spreadsheet, it receives a ``needs safety check'' 
marking.  Later,
 when the formula or printer is evaluated for the first time, it is
 checked for safety using the @code{unsafep} predicate; if found to be
 ``possibly unsafe'', the questionable formula or printer is displayed
-and you must press Y to approve it or N to use a substitute.  The
-substitute always signals an error.
+and you must press @kbd{Y} to approve it or @kbd{N} to use a
+substitute.  The substitute always signals an error.
 
 Formulas or printers that you type in are checked immediately for
-safety.  If found to be possibly unsafe and you press N to disapprove,
+safety.  If found to be possibly unsafe and you press @kbd{N} to disapprove,
 the action is canceled and the old formula or printer will remain.
 
 Besides viruses (which try to copy themselves to other files),
@@ -1143,13 +1174,15 @@ Example of use:
 @lisp
 (ses-average (ses-select (ses-range A1 A5) 'Smith (ses-range B1 B5)))
 @end lisp
-This computes the average of the B column values for those rows whose
-A column value is the symbol 'Smith.
+This computes the average of the @samp{B} column values for those rows
+whose @samp{A} column value is the symbol @samp{'Smith}.
 
 Arguably one could specify only @var{fromrange} plus
 @var{to-row-offset} and @var{to-column-offset}.  The @var{torange} is
 stated explicitly to ensure that the formula will be recalculated if
 any cell in either range is changed.
+@c TODO reword this paragraph more clearly as in the French version
+
 
 File @file{etc/ses-example.el} in the Emacs distribution is an example of a
 details-and-summary spreadsheet.
@@ -1179,12 +1212,13 @@ To save time by avoiding redundant computations, cells 
that need
 recalculation due to changes in other cells are added to a set.  At
 the end of the command, each cell in the set is recalculated once.
 This can create a new set of cells that need recalculation.  The
-process is repeated until either the set is empty or it stops changing
-(due to circular references among the cells).  In extreme cases, you
-might see progress messages of the form ``Recalculating... (@var{nnn}
-cells left)''.  If you interrupt the calculation using @kbd{C-g}, the
-spreadsheet will be left in an inconsistent state, so use @kbd{C-_} or
-@kbd{C-c C-l} to fix it.
+process is repeated until either the set is empty or a circular
+references are detected.  In extreme cases, and notably if a circular
+cell reference is under detection, you might see progress messages of
+the form ``Recalculating... (@var{nnn} cells left)''.  If you
+interrupt the calculation using @kbd{C-g}, the spreadsheet will be
+left in an inconsistent state, so use @kbd{C-_} or @kbd{C-c C-l} to
+fix it.
 
 To save even more time by avoiding redundant writes, cells that have
 changes are added to a set instead of being written immediately to the
@@ -1194,11 +1228,12 @@ progress message of the form ``Writing... (@var{nnn} 
cells left)''.
 These deferred cell-writes cannot be interrupted by @kbd{C-g}, so
 you'll just have to wait.
 
-@acronym{SES} uses @code{run-with-idle-timer} to move the cell underline when
-Emacs will be scrolling the buffer after the end of a command, and
-also to narrow and underline after @kbd{C-x C-v}.  This is visible as
-a momentary glitch after C-x C-v and certain scrolling commands.  You
-can type ahead without worrying about the glitch.
+@acronym{SES} uses @code{run-with-idle-timer} to move the cell
+underline when Emacs will be scrolling the buffer after the end of a
+command, and also to narrow and underline after visiting a file.  This
+may be visible as a momentary glitch after visiting and certain
+scrolling commands.  You can type ahead without worrying about the
+glitch.
 
 
 @node Nonrelocatable references
@@ -1210,8 +1245,8 @@ can type ahead without worrying about the glitch.
 @kbd{C-u C-y} relocates none of the cell-references.  What about mixed
 cases?
 
-The best way is to rename cells that you do not want to be relocatable
-by using @code{ses-rename-cell}.
+The best way is to rename cells that you do @emph{not} want to be
+relocatable by using @code{ses-rename-cell}.
 @findex ses-rename-cell
 Cells that do not have an A1-like name style are not relocated on
 yank. Using this method, the concerned cells won't be relocated
@@ -1219,7 +1254,7 @@ whatever formula they appear in. Please note however that 
when a
 formula contains some range @code{(ses-range @var{cell1} @var{cell2})}
 then in the yanked formula each range bound @var{cell1} and
 @var{cell2} are relocated, or not, independently, depending on whether
-they are A1-like or renamed.
+they are @samp{A1}-like or renamed.
 
 An alternative method is to use
 @lisp
@@ -1227,9 +1262,9 @@ An alternative method is to use
 @end lisp
 to make an @dfn{absolute reference}.  The formula relocator skips over
 quoted things, so this will not be relocated when pasted or when
-rows/columns are inserted/deleted.  However, B3 will not be recorded
-as a dependency of this cell, so this cell will not be updated
-automatically when B3 is changed, this is why using
+rows/columns are inserted/deleted.  However, @samp{B3} will not be
+recorded as a dependency of this cell, so this cell will not be
+updated automatically when @samp{B3} is changed, this is why using
 @code{ses-rename-cell} is most of the time preferable.
 
 The variables @code{row} and @code{col} are dynamically bound while a
@@ -1246,12 +1281,13 @@ kind of dependency is also not recorded.
 @cindex data area
 @findex ses-reconstruct-all
 
-Begins with an 014 character, followed by sets of cell-definition
-macros for each row, followed by the set of local printer
-definitions, followed by column-widths, column-printers,
-default-printer, and header-row.  Then there's the global parameters
-(file-format ID, row count, column count, local printer count) and the
-local variables (specifying @acronym{SES} mode for the buffer, etc.).
+Begins with an form feed character (whose ASCII code is 014 in octal
+notation), followed by sets of cell-definition macros for each row,
+followed by the set of local printer definitions, followed by
+column-widths, column-printers, default-printer, and header-row.  Then
+there's the global parameters (file-format ID, row count, column
+count, local printer count) and the local variables (specifying
+@acronym{SES} mode for the buffer, etc.).
 
 When a @acronym{SES} file is loaded, first the global parameters are
 loaded, then the entire data area is @code{eval}ed, and finally the local
@@ -1263,10 +1299,10 @@ counting newlines.  Use @kbd{C-x C-e} at the end of a 
line to install
 your edits into the spreadsheet data structures (this does not update
 the print area, use, e.g., @kbd{C-c C-l} for that).
 
-The data area is maintained as an image of spreadsheet data
-structures that area stored in buffer-local variables.  If the data
-area gets messed up, you can try reconstructing the data area from the
-data structures:
+The data area is maintained as an image of spreadsheet data structures
+as stored in buffer-local variables from initially loading the area.
+If the data area gets messed up in the sequel, you can try
+reconstructing the data area from the data structures:
 
 @table @kbd
 @item C-c M-C-l
@@ -1283,7 +1319,7 @@ You can add additional local variables to the list at the 
bottom of
 the data area, such as hidden constants you want to refer to in your
 formulas.
 
-You can override the variable @code{ses--symbolic-formulas} to be a list of
+You can initialize the variable @code{ses--symbolic-formulas} to be a list of
 symbols (as parenthesized strings) to show as completions for the @kbd{'}
 command.  This initial completions list is used instead of the actual
 set of symbols-as-formulas in the spreadsheet.
@@ -1317,14 +1353,14 @@ avoid virus warnings, each function used in a formula 
needs
 @table @code
 @item copy-region-as-kill
 When copying from the print area of a spreadsheet, treat the region as
-a rectangle and attach each cell's formula and printer as 'ses
+a rectangle and attach each cell's formula and printer as @code{'ses}
 properties.
 
 @item yank
 When yanking into the print area of a spreadsheet, first try to yank
-as cells (if the yank text has 'ses properties), then as tab-separated
-formulas, then (if all else fails) as a single formula for the current
-cell.
+as cells (if the yank text has @code{'ses} properties), then as
+tab-separated formulas, then (if all else fails) as a single formula
+for the current cell.
 @end table
 
 @c ===================================================================
@@ -1345,7 +1381,9 @@ Jonathan Yavner,
 @c monnier@@gnu.org
 Stefan Monnier,
 @c shigeru.fukaya@@gmail.com
-Shigeru Fukaya
+Shigeru Fukaya,
+@c vincent.belaiche@@sourceforge.net
+Vincent Belaïche
 @end quotation
 
 @noindent
@@ -1354,7 +1392,9 @@ Texinfo manual by:
 @c jyavner@@member.fsf.org
 Jonathan Yavner,
 @c brad@@chenla.org
-Brad Collins
+Brad Collins,
+@c vincent.belaiche@@sourceforge.net
+Vincent Belaïche
 @end quotation
 
 @noindent
@@ -1395,7 +1435,9 @@ Luc Teirlinck,
 @c jotto@@pobox.com
 J. Otto Tennant,
 @c jphil@@acs.pagesjaunes.fr
-Jean-Philippe Theberge
+Jean-Philippe Theberge,
+@c rrandresf@@hotmail.com
+Andrés Ramírez
 @end quotation
 
 @c ===================================================================
diff --git a/doc/misc/sieve.texi b/doc/misc/sieve.texi
index 639a2daee02..156e0120a38 100644
--- a/doc/misc/sieve.texi
+++ b/doc/misc/sieve.texi
@@ -10,7 +10,7 @@
 @copying
 This file documents the Emacs Sieve package, for server-side mail filtering.
 
-Copyright @copyright{} 2001--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2001--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/smtpmail.texi b/doc/misc/smtpmail.texi
index cc2f4f85fb3..33f4d558aad 100644
--- a/doc/misc/smtpmail.texi
+++ b/doc/misc/smtpmail.texi
@@ -4,7 +4,7 @@
 @include docstyle.texi
 @syncodeindex vr fn
 @copying
-Copyright @copyright{} 2003--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2003--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/speedbar.texi b/doc/misc/speedbar.texi
index aae9ab762da..f4b9ee702a7 100644
--- a/doc/misc/speedbar.texi
+++ b/doc/misc/speedbar.texi
@@ -5,7 +5,7 @@
 @syncodeindex fn cp
 
 @copying
-Copyright @copyright{} 1999--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1999--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/srecode.texi b/doc/misc/srecode.texi
index 84173f0e0f6..6a4560d5920 100644
--- a/doc/misc/srecode.texi
+++ b/doc/misc/srecode.texi
@@ -16,7 +16,7 @@
 @c %**end of header
 
 @copying
-Copyright @copyright{} 2007--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2007--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex
index 6e521944b22..e8c382f5967 100644
--- a/doc/misc/texinfo.tex
+++ b/doc/misc/texinfo.tex
@@ -3,7 +3,7 @@
 % Load plain if necessary, i.e., if running under initex.
 \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
 %
-\def\texinfoversion{2023-07-27.21}
+\def\texinfoversion{2023-09-19.19}
 %
 % Copyright 1985, 1986, 1988, 1990-2023 Free Software Foundation, Inc.
 %
@@ -5652,42 +5652,13 @@ might help (with 'rm \jobname.?? \jobname.??s')%
       \parfillskip=0pt plus -1fill
       %
       \advance\rightskip by \entryrightmargin
-      % Determine how far we can stretch into the margin.
-      % This allows, e.g., "Appendix H  GNU Free Documentation License" to
-      % fit on one line in @letterpaper format.
-      \ifdim\entryrightmargin>2.1em
-        \dimen@i=2.1em
-      \else
-        \dimen@i=0em
-      \fi
-      \advance \parfillskip by 0pt minus 1\dimen@i
       %
       \dimen@ii = \hsize
       \advance\dimen@ii by -1\leftskip
       \advance\dimen@ii by -1\entryrightmargin
-      \advance\dimen@ii by 1\dimen@i
       \ifdim\wd\boxA > \dimen@ii % If the entry doesn't fit in one line
       \ifdim\dimen@ > 0.8\dimen@ii   % due to long index text
-        % Undo changes above
-        \advance \parfillskip by 0pt minus -1\dimen@i
-        \advance\dimen@ii by -1\dimen@i
-        %
-        % Try to split the text roughly evenly.  \dimen@ will be the length of
-        % the first line.
-        \dimen@ = 0.7\dimen@
-        \dimen@ii = \hsize
-        \ifnum\dimen@>\dimen@ii
-          % If the entry is too long (for example, if it needs more than
-          % two lines), use the same line length for all lines.
-          \dimen@ = \dimen@ii
-        \else
-          \advance \dimen@ by 1\rightskip
-        \fi
         \advance\leftskip by 0pt plus 1fill % ragged right
-        \parshape = 2 0pt \dimen@ 0em \dimen@ii
-        % Ideally we'd add a finite glue at the end of the first line only,
-        % instead of using \parshape with explicit line lengths, but TeX
-        % doesn't seem to provide a way to do such a thing.
         %
         % Indent all lines but the first one.
         \advance\leftskip by \entrycontskip
@@ -5714,12 +5685,11 @@ might help (with 'rm \jobname.?? \jobname.??s')%
 \newskip\thinshrinkable
 \skip\thinshrinkable=.15em minus .15em
 
-% Like plain.tex's \dotfill, except uses up at least 1 em.
+% Like plain.tex's \dotfill, except uses up at least 0.5 em.
 % The filll stretch here overpowers both the fil and fill stretch to push
 % the page number to the right.
 \def\indexdotfill{\cleaders
-  \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1filll}
-
+  \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 0.5em plus 1filll}
 
 \def\primary #1{\line{#1\hfil}}
 
@@ -7709,9 +7679,13 @@ might help (with 'rm \jobname.?? \jobname.??s')%
 \def\deflineheader#1 #2 #3\endheader{%
   \printdefname{#1}{}{#2}\magicamp\defunargs{#3\unskip}%
 }
+
 \def\deftypeline{%
   \doingtypefntrue
-  \parseargusing\activeparens{\printdefunline\deflineheader}%
+  \parseargusing\activeparens{\printdefunline\deftypelineheader}%
+}
+\def\deftypelineheader#1 #2 #3 #4\endheader{%
+  \printdefname{#1}{#2}{#3}\magicamp\defunargs{#4\unskip}%
 }
 
 % \makedefun{deffoo} (\deffooheader parameters) { (\deffooheader expansion) }
@@ -8846,6 +8820,11 @@ might help (with 'rm \jobname.?? \jobname.??s')%
   \fi
 }
 
+% @nodedescription, @nodedescriptionblock - do nothing for TeX
+\parseargdef\nodedescription{}
+\def\nodedescriptionblock{\doignore{nodedescriptionblock}}
+
+
 % @anchor{NAME} -- define xref target at arbitrary point.
 %
 \newcount\savesfregister
@@ -11859,9 +11838,13 @@ directory should work if nowhere else does.}
   \def\c{\loadconf\c}%
   % Definition for the first newline read in the file
   \def ^^M{\loadconf}%
-  % In case the first line has a whole-line command on it
+  % In case the first line has a whole-line or environment command on it
   \let\originalparsearg\parsearg%
   \def\parsearg{\loadconf\originalparsearg}%
+  %
+  % \startenvironment is in the expansion of commands defined with \envdef
+  \let\originalstartenvironment\startenvironment%
+  \def\startenvironment{\loadconf\startenvironment}%
 }}
 
 
@@ -11889,6 +11872,7 @@ directory should work if nowhere else does.}
   \enableemergencynewline
   \let\c=\comment
   \let\parsearg\originalparsearg
+  \let\startenvironment\originalstartenvironment
   %
   % Also turn back on active characters that might appear in the input
   % file name, in case not using a pre-dumped format.
diff --git a/doc/misc/todo-mode.texi b/doc/misc/todo-mode.texi
index 62376195023..9f259b0e65b 100644
--- a/doc/misc/todo-mode.texi
+++ b/doc/misc/todo-mode.texi
@@ -9,7 +9,7 @@
 @c %**end of header
 
 @copying
-Copyright @copyright{} 2013--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2013--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index c21426a32f7..56945d3071c 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -12,7 +12,7 @@
 @footnotestyle end
 
 @copying
-Copyright @copyright{} 1999--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1999--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -321,7 +321,7 @@ behind the scenes when you open a file with @value{tramp}.
 @cindex GNU ELPA
 @vindex tramp-version
 
-@value{tramp} is included as part of Emacs (since @w{Emacs 22.1}).
+@value{tramp} is included as part of Emacs.
 
 @value{tramp} is also freely packaged for download on the Internet at
 @uref{https://ftp.gnu.org/gnu/tramp/}.  The version number of
@@ -343,10 +343,12 @@ versions packaged with Emacs can be retrieved by
 @end lisp
 
 @value{tramp} is also available as @uref{https://elpa.gnu.org, GNU
-ELPA} package.  Besides the standalone releases, further minor versions
-of @value{tramp} will appear on GNU ELPA, until the next @value{tramp}
-release appears.  These minor versions have a four-number string, like
-``2.4.5.1''.
+ELPA} package.  Besides the standalone releases, further minor
+versions of @value{tramp} will appear on GNU ELPA, until the next
+@value{tramp} release appears.  These minor versions have a
+four-number string, like ``2.4.5.1''.  The manual of the latest
+@value{tramp} ELPA package is located at
+@uref{https://elpa.gnu.org/packages/doc/tramp.html}.
 
 @value{tramp} development versions are available on Git servers.
 Development versions contain new and incomplete features.  The
@@ -3671,7 +3673,7 @@ ssh@value{postfixhop}you@@remotehost@value{postfix}/path 
@key{RET}}
 Each involved method must be an inline method (@pxref{Inline methods}).
 
 @value{tramp} adds the ad-hoc definitions on the fly to
-@code{tramp-default-proxies-alist} and is available for re-use during
+@code{tramp-default-proxies-alist} and is available for reuse during
 that Emacs session.  Subsequent @value{tramp} connections to the same
 remote host can then use the shortcut form:
 @samp{@trampfn{ssh,you@@remotehost,/path}}.
@@ -4201,7 +4203,7 @@ To open @command{powershell} as a remote shell, use this:
 
 @subsection Remote process connection type
 @vindex process-connection-type
-@cindex tramp-process-connection-type
+@vindex tramp-process-connection-type
 
 Asynchronous processes behave differently based on whether they use a
 pseudo tty or not.  This is controlled by the variable
@@ -4338,7 +4340,7 @@ called @code{tramp-connection-local-*-ps-profile} and
 @end group
 @end lisp
 
-@cindex proced
+@cindex @code{proced}
 @vindex proced-show-remote-processes
 If you want to see a listing of remote system processes when calling
 @code{proced}, set user option @code{proced-show-remote-processes} to
@@ -4406,9 +4408,6 @@ It does not report the remote terminal name via 
@code{process-tty-name}.
 
 @item
 It does not set process property @code{remote-pid}.
-
-@item
-It does not use @code{tramp-remote-path}.
 @end itemize
 
 In order to gain even more performance, it is recommended to bind
@@ -5322,17 +5321,39 @@ customization is explained in user option
 @item
 Remote host does not understand default options for directory listing
 
-Emacs computes the @command{dired} options based on the local host but
-if the remote host cannot understand the same @command{ls} command,
-then set them with a hook as follows:
+@vindex dired-listing-switches
+Emacs computes the @command{dired} options based on the local host.
+Since @w{Emacs 30}, these options can be set connection-local.
+@ifinfo
+@xref{Connection Variables, , , emacs}.
+@end ifinfo
+
+@lisp
+@group
+(connection-local-set-profile-variables
+  'my-dired-profile
+  '((dired-listing-switches . "-ahl")))
+@end group
+
+@group
+(connection-local-set-profiles
+ '(:application tramp :machine "remotehost")
+ 'my-dired-profile)
+@end group
+@end lisp
+
+@vindex dired-actual-switches
+In older Emacsen, you can set the @command{dired} options with a hook
+as follows:
 
 @lisp
 @group
 (add-hook
  'dired-before-readin-hook
  (lambda ()
-   (when (file-remote-p default-directory)
-     (setq dired-actual-switches "-al"))))
+   (when (string-equal
+           (file-remote-p default-directory 'host) "remotehost")
+     (setq dired-actual-switches "-ahl"))))
 @end group
 @end lisp
 
diff --git a/doc/misc/trampver.texi b/doc/misc/trampver.texi
index 2f505c6acea..bf5c90ee8a9 100644
--- a/doc/misc/trampver.texi
+++ b/doc/misc/trampver.texi
@@ -2,12 +2,12 @@
 @c texi/trampver.texi.  Generated from trampver.texi.in by configure.
 
 @c This is part of the Emacs manual.
-@c Copyright (C) 2003--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2003--2024 Free Software Foundation, Inc.
 @c See file doclicense.texi for copying conditions.
 
 @c In the  Tramp GIT, the version number and the bug report address
 @c are auto-frobbed from configure.ac.
-@set trampver 2.7.0-pre
+@set trampver 2.7.1-pre
 @set trampurl https://www.gnu.org/software/tramp/
 @set tramp-bug-report-address tramp-devel@@gnu.org
 @set emacsver 27.1
diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi
index e06f7759d1b..f76edc6b1e4 100644
--- a/doc/misc/transient.texi
+++ b/doc/misc/transient.texi
@@ -8,7 +8,7 @@
 
 @copying
 @quotation
-Copyright (C) 2018--2023 Free Software Foundation, Inc.
+Copyright (C) 2018--2024 Free Software Foundation, Inc.
 
 You can redistribute this document and/or modify it under the terms
 of the GNU General Public License as published by the Free Software
@@ -31,7 +31,7 @@ General Public License for more details.
 @finalout
 @titlepage
 @title Transient User and Developer Manual
-@subtitle for version 0.4.3
+@subtitle for version 0.5.2
 @author Jonas Bernoulli
 @page
 @vskip 0pt plus 1filll
@@ -44,37 +44,16 @@ General Public License for more details.
 @node Top
 @top Transient User and Developer Manual
 
-Taking inspiration from prefix keys and prefix arguments, Transient
-implements a similar abstraction involving a prefix command, infix
-arguments and suffix commands.  We could call this abstraction a
-``transient command'', but because it always involves at least two
-commands (a prefix and a suffix) we prefer to call it just a
-``transient''.
-
-When the user calls a transient prefix command, a transient
-(temporary) keymap is activated, which binds the transient's infix
-and suffix commands, and functions that control the transient state
-are added to @code{pre-command-hook} and @code{post-command-hook}.  The 
available
-suffix and infix commands and their state are shown in a popup buffer
-until the transient is exited by invoking a suffix command.
-
-Calling an infix command causes its value to be changed, possibly by
-reading a new value in the minibuffer.
+Transient is the library used to implement the keyboard-driven ``menus''
+in Magit.  It is distributed as a separate package, so that it can be
+used to implement similar menus in other packages.
 
-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
+This manual can be bit hard to digest when 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}.
 
 @noindent
-This manual is for Transient version 0.4.3.
+This manual is for Transient version 0.5.2.
 
 @insertcopying
 @end ifnottex
@@ -85,7 +64,6 @@ This manual is for Transient version 0.4.3.
 * Modifying Existing Transients::
 * Defining New Commands::
 * Classes and Methods::
-* Related Abstractions and Packages::
 * FAQ::
 * Keystroke Index::
 * Command and Function Index::
@@ -110,6 +88,7 @@ Usage
 
 Defining New Commands
 
+* Technical Introduction::
 * Defining Transients::
 * Binding Suffix and Infix Commands::
 * Defining Suffix and Infix Commands::
@@ -139,153 +118,87 @@ Suffix Methods
 * Suffix Format Methods::
 
 
-Related Abstractions and Packages
-
-* Comparison With Prefix Keys and Prefix Arguments::
-* Comparison With Other Packages::
-
 @end detailmenu
 @end menu
 
 @node Introduction
 @chapter Introduction
 
-Taking inspiration from prefix keys and prefix arguments, Transient
-implements a similar abstraction involving a prefix command, infix
-arguments and suffix commands.  We could call this abstraction a
-``transient command'', but because it always involves at least two
-commands (a prefix and a suffix) we prefer to call it just a
-``transient''.
-
-@cindex transient prefix command
-@quotation
-Transient keymaps are a feature provided by Emacs.  Transients as
-implemented by this package involve the use of transient keymaps.
-
-Emacs provides a feature that it calls @dfn{prefix commands}.  When we
-talk about ``prefix commands'' in this manual, then we mean our own kind
-of ``prefix commands'', unless specified otherwise.  To avoid ambiguity
-we sometimes use the terms @dfn{transient prefix command} for our kind and
-``regular prefix command'' for Emacs' kind.
-
-@end quotation
+Transient is the library used to implement the keyboard-driven @dfn{menus}
+in Magit.  It is distributed as a separate package, so that it can be
+used to implement similar menus in other packages.
 
-When the user calls a transient prefix command, a transient
-(temporary) keymap is activated, which binds the transient's infix and
-suffix commands, and functions that control the transient state are
-added to @code{pre-command-hook} and @code{post-command-hook}.  The available 
suffix
-and infix commands and their state are shown in a popup buffer until
-the transient state is exited by invoking a suffix command.
-
-Calling an infix command causes its value to be changed.  How that is
-done depends on the type of the infix command.  The simplest case is
-an infix command that represents a command-line argument that does not
-take a value.  Invoking such an infix command causes the switch to be
-toggled on or off.  More complex infix commands may read a value from
-the user, using the minibuffer.
-
-Calling a suffix command usually causes the transient to be exited;
-the transient keymaps and hook functions are removed, the popup buffer
-no longer shows information about the (no longer bound) suffix
-commands, the values of some public global variables are set, while
-some internal global variables are unset, and finally the command is
-actually called.  Suffix commands can also be configured to not exit
-the transient.
-
-A suffix command can, but does not have to, use the infix arguments in
-much the same way any command can choose to use or ignore the prefix
-arguments.  For a suffix command that was invoked from a transient, the
-variable @code{transient-current-suffixes} and the function 
@code{transient-args}
-serve about the same purpose as the variables @code{prefix-arg} and
-@code{current-prefix-arg} do for any command that was called after the prefix
-arguments have been set using a command such as @code{universal-argument}.
-
-The information shown in the popup buffer while a transient is active
-looks a bit like this:
-
-@example
-,-----------------------------------------
-|Arguments
-| -f Force (--force)
-| -a Annotate (--annotate)
-|
-|Create
-| t tag
-| r release
-`-----------------------------------------
-@end example
-
-@quotation
-This is a simplified version of @code{magit-tag}.  Info manuals do not
-support images or colored text, so the above ``screenshot'' lacks some
-information; in practice you would be able to tell whether the
-arguments @code{--force} and @code{--annotate} are enabled or not based on 
their
-color.
-
-@end quotation
-
-@cindex command dispatchers
-Transient can be used to implement simple ``command dispatchers''.  The
-main benefit then is that the user can see all the available commands
-in a popup buffer.  That is useful by itself because it frees the user
-from having to remember all the keys that are valid after a certain
-prefix key or command.  Magit's @code{magit-dispatch} (on @kbd{C-x M-g}) 
command is
-an example of using Transient to merely implement a command
-dispatcher.
-
-In addition to that, Transient also allows users to interactively pass
-arguments to commands.  These arguments can be much more complex than
-what is reasonable when using prefix arguments.  There is a limit to
-how many aspects of a command can be controlled using prefix
-arguments.  Furthermore, what a certain prefix argument means for
-different commands can be completely different, and users have to read
-documentation to learn and then commit to memory what a certain prefix
-argument means to a certain command.
-
-Transient suffix commands, on the other hand, can accept dozens of
-different arguments without the user having to remember anything.
-When using Transient, one can call a command with arguments that are
-just as complex as when calling the same function non-interactively
-from Lisp.
-
-Invoking a transient suffix command with arguments is similar to
-invoking a command in a shell with command-line completion and history
-enabled.  One benefit of the Transient interface is that it remembers
-history not only on a global level (``this command was invoked using
-these arguments, and previously it was invoked using those other
-arguments''), but also remembers the values of individual arguments
-independently.  See @xref{Using History}.
+This manual can be bit hard to digest when 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}.
 
-After a transient prefix command is invoked, @kbd{C-h @var{KEY}} can be used to
-show the documentation for the infix or suffix command that @kbd{@var{KEY}} is
-bound to (see @ref{Getting Help for Suffix Commands}), and infixes and
-suffixes can be removed from the transient using @kbd{C-x l @var{KEY}}. Infixes
-and suffixes that are disabled by default can be enabled the same way.
-@xref{Enabling and Disabling Suffixes}.
+@anchor{Some things that Transient can do}
+@heading Some things that Transient can do
 
-Transient ships with support for a few different types of specialized
-infix commands.  A command that sets a command line option, for example,
-has different needs than a command that merely toggles a boolean flag.
-Additionally, Transient provides abstractions for defining new types,
-which the author of Transient did not anticipate (or didn't get around
-to implementing yet).
+@itemize
+@item
+Display current state of arguments
+@item
+Display and manage lifecycle of modal bindings
+@item
+Contextual user interface
+@item
+Flow control for wizard-like composition of interactive forms
+@item
+History & persistence
+@item
+Rendering arguments for controlling CLI programs
+@end itemize
 
-Note that suffix commands also support regular prefix arguments.  A
-suffix command may even be called with both infix and prefix arguments
-at the same time.  If you invoke a command as a suffix of a transient
-prefix command, but also want to pass prefix arguments to it, then
-first invoke the prefix command, and only after doing that invoke the
-prefix arguments, before finally invoking the suffix command.  If you
-instead began by providing the prefix arguments, then those would
-apply to the prefix command, not the suffix command.  Likewise, if you
-want to change infix arguments before invoking a suffix command with
-prefix arguments, then change the infix arguments before invoking the
-prefix arguments.  In other words, regular prefix arguments always
-apply to the next command, and since transient prefix, infix and
-suffix commands are just regular commands, the same applies to them.
-(Regular prefix keys behave differently because they are not commands
-at all, instead they are just incomplete key sequences, and those
-cannot be interrupted with prefix commands.)
+@anchor{Complexity in CLI programs}
+@heading Complexity in CLI programs
+
+Complexity tends to grow with time.  How do you manage the complexity
+of commands?  Consider the humble shell command @samp{ls}.  It now has over
+@emph{fifty} command line options.  Some of these are boolean flags (@samp{ls 
-l}).
+Some take arguments (@samp{ls --sort=s}).  Some have no effect unless paired
+with other flags (@samp{ls -lh}).  Some are mutually exclusive.  Some shell
+commands even have so many options that they introduce @emph{subcommands}
+(@samp{git branch}, @samp{git commit}), each with their own rich set of options
+(@samp{git branch -f}).
+
+@anchor{Using Transient for composing interactive commands}
+@heading Using Transient for composing interactive commands
+
+What about Emacs commands used interactively? How do these handle
+options?  One solution is to make many versions of the same command,
+so you don't need to! Consider: @samp{delete-other-windows} vs.
+@samp{delete-other-windows-vertically} (among many similar examples).
+
+Some Emacs commands will simply prompt you for the next "argument"
+(@samp{M-x switch-to-buffer}).  Another common solution is to use prefix
+arguments which usually start with @samp{C-u}.  Sometimes these are sensibly
+numerical in nature (@samp{C-u 4 M-x forward-paragraph} to move forward 4
+paragraphs).  But sometimes they function instead as boolean
+"switches" (@samp{C-u C-SPACE} to jump to the last mark instead of just
+setting it, @samp{C-u C-u C-SPACE} to unconditionally set the mark).  Since
+there aren't many standards for the use of prefix options, you have to
+read the command's documentation to find out what the possibilities
+are.
+
+But when an Emacs command grows to have a truly large set of options
+and arguments, with dependencies between them, lots of option values,
+etc., these simple approaches just don't scale.  Transient is designed
+to solve this issue.  Think of it as the humble prefix argument @samp{C-u},
+@emph{raised to the power of 10}.  Like @samp{C-u}, it is key driven.  Like the
+shell, it supports boolean "flag" options, options that take
+arguments, and even "sub-commands", with their own options.  But
+instead of searching through a man page or command documentation,
+well-designed transients @emph{guide} their users to the relevant set of
+options (and even their possible values!) directly, taking into
+account any important pre-existing Emacs settings.  And while for
+shell commands like @samp{ls}, there is only one way to "execute" (hit
+@samp{Return}!), transients can "execute" using multiple different keys tied
+to one of many self-documenting @emph{actions} (imagine having 5 different
+colored return keys on your keyboard!).  Transients make navigating
+and setting large, complex groups of command options and arguments
+easy.  Fun even.  Once you've tried it, it's hard to go back to the
+@samp{C-u what can I do here again?} way.
 
 @node Usage
 @chapter Usage
@@ -366,7 +279,7 @@ it returns to the previous transient, if any.
 
 Transient's predecessor bound @kbd{q} instead of @kbd{C-g} to the quit command.
 To learn how to get that binding back see @code{transient-bind-q-to-quit}'s
-doc string.
+documentation string.
 
 @table @asis
 @item @kbd{C-q} (@code{transient-quit-all})
@@ -562,8 +475,8 @@ What sort of documentation is shown depends on how the 
transient was
 defined.  For infix commands that represent command-line arguments
 this ideally shows the appropriate manpage.  @code{transient-help} then tries
 to jump to the correct location within that.  Info manuals are also
-supported.  The fallback is to show the command's doc string, for
-non-infix suffixes this is usually appropriate.
+supported.  The fallback is to show the command's documentation
+string, for non-infix suffixes this is usually appropriate.
 
 @node Enabling and Disabling Suffixes
 @section Enabling and Disabling Suffixes
@@ -637,6 +550,13 @@ not.  The predicates also apply in edit mode.
 
 Therefore, to control which suffixes are available given a certain
 state, you have to make sure that that state is currently active.
+
+@item @kbd{C-x a} (@code{transient-toggle-level-limit})
+@kindex C-x a
+@findex transient-toggle-level-limit
+This command toggle whether suffixes that are on levels lower than
+the level specified by @code{transient-default-level} are temporarily
+available anyway.
 @end table
 
 @node Other Commands
@@ -782,27 +702,31 @@ If @code{nil}, then the buffer has no mode-line.  If the 
buffer is not
 displayed right above the echo area, then this probably is not a
 good value.
 
-If @code{line} (the default), then the buffer also has no mode-line, but a
-thin line is drawn instead, using the background color of the face
-@code{transient-separator}.  Text-mode frames cannot display thin lines,
-and therefore fall back to treating @code{line} like @code{nil}.
+If @code{line} (the default) or a natural number, then the buffer
+has no mode-line, but a line is drawn is drawn in its place.
+If a number is used, that specifies the thickness of the line.
+On termcap frames we cannot draw lines, so there @code{line} and
+numbers are synonyms for @code{nil}.
+
+The color of the line is used to indicate if non-suffixes are
+allowed and whether they exit the transient.  The foreground
+color of @code{transient-key-noop} (if non-suffix are disallowed),
+@code{transient-key-stay} (if allowed and transient stays active), or
+@code{transient-key-exit} (if allowed and they exit the transient) is
+used to draw the line.
 
 Otherwise this can be any mode-line format.  @xref{Mode Line
 Format,,,elisp,}, for details.
 @end defopt
 
 @defopt transient-semantic-coloring
-This option controls whether prefixes and suffixes are colored in
-a Hydra-like fashion.
+This option controls whether colors are used to indicate the
+transient behavior of commands.
 
 If non-@code{nil}, then the key binding of each suffix is colorized to
 indicate whether it exits the transient state or not.  The color of
 the prefix is indicated using the line that is drawn when the value
 of @code{transient-mode-line-format} is @code{line}.
-
-For more information about how Hydra uses colors see
-@uref{https://github.com/abo-abo/hydra#color} and
-@uref{https://oremacs.com/2015/02/19/hydra-colors-reloaded}.
 @end defopt
 
 @defopt transient-highlight-mismatched-keys
@@ -1015,6 +939,7 @@ signal an error.
 @chapter Defining New Commands
 
 @menu
+* Technical Introduction::
 * Defining Transients::
 * Binding Suffix and Infix Commands::
 * Defining Suffix and Infix Commands::
@@ -1022,6 +947,106 @@ signal an error.
 * Transient State::
 @end menu
 
+@node Technical Introduction
+@section Technical Introduction
+
+Taking inspiration from prefix keys and prefix arguments, Transient
+implements a similar abstraction involving a prefix command, infix
+arguments and suffix commands.
+
+When the user calls a transient prefix command, a transient
+(temporary) keymap is activated, which binds the transient's infix and
+suffix commands, and functions that control the transient state are
+added to @code{pre-command-hook} and @code{post-command-hook}.  The available 
suffix
+and infix commands and their state are shown in a popup buffer until
+the transient state is exited by invoking a suffix command.
+
+Calling an infix command causes its value to be changed.  How that is
+done depends on the type of the infix command.  The simplest case is
+an infix command that represents a command-line argument that does not
+take a value.  Invoking such an infix command causes the switch to be
+toggled on or off.  More complex infix commands may read a value from
+the user, using the minibuffer.
+
+Calling a suffix command usually causes the transient to be exited;
+the transient keymaps and hook functions are removed, the popup buffer
+no longer shows information about the (no longer bound) suffix
+commands, the values of some public global variables are set, while
+some internal global variables are unset, and finally the command is
+actually called.  Suffix commands can also be configured to not exit
+the transient.
+
+A suffix command can, but does not have to, use the infix arguments in
+much the same way any command can choose to use or ignore the prefix
+arguments.  For a suffix command that was invoked from a transient, the
+variable @code{transient-current-suffixes} and the function 
@code{transient-args}
+serve about the same purpose as the variables @code{prefix-arg} and
+@code{current-prefix-arg} do for any command that was called after the prefix
+arguments have been set using a command such as @code{universal-argument}.
+
+@cindex command dispatchers
+Transient can be used to implement simple ``command dispatchers''.  The
+main benefit then is that the user can see all the available commands
+in a popup buffer, which can be thought of as a ``menus''.  That is
+useful by itself because it frees the user from having to remember all
+the keys that are valid after a certain prefix key or command.
+Magit's @code{magit-dispatch} (on @kbd{C-x M-g}) command is an example of using
+Transient to merely implement a command dispatcher.
+
+In addition to that, Transient also allows users to interactively pass
+arguments to commands.  These arguments can be much more complex than
+what is reasonable when using prefix arguments.  There is a limit to
+how many aspects of a command can be controlled using prefix
+arguments.  Furthermore, what a certain prefix argument means for
+different commands can be completely different, and users have to read
+documentation to learn and then commit to memory what a certain prefix
+argument means to a certain command.
+
+Transient suffix commands, on the other hand, can accept dozens of
+different arguments without the user having to remember anything.
+When using Transient, one can call a command with arguments that are
+just as complex as when calling the same function non-interactively
+from Lisp.
+
+Invoking a transient suffix command with arguments is similar to
+invoking a command in a shell with command-line completion and history
+enabled.  One benefit of the Transient interface is that it remembers
+history not only on a global level (``this command was invoked using
+these arguments, and previously it was invoked using those other
+arguments''), but also remembers the values of individual arguments
+independently.  See @ref{Using History}.
+
+After a transient prefix command is invoked, @kbd{C-h @var{KEY}} can be used to
+show the documentation for the infix or suffix command that @kbd{@var{KEY}} is
+bound to (see @ref{Getting Help for Suffix Commands}), and infixes and
+suffixes can be removed from the transient using @kbd{C-x l @var{KEY}}. Infixes
+and suffixes that are disabled by default can be enabled the same way.
+See @ref{Enabling and Disabling Suffixes}.
+
+Transient ships with support for a few different types of specialized
+infix commands.  A command that sets a command line option, for example,
+has different needs than a command that merely toggles a boolean flag.
+Additionally, Transient provides abstractions for defining new types,
+which the author of Transient did not anticipate (or didn't get around
+to implementing yet).
+
+Note that suffix commands also support regular prefix arguments.  A
+suffix command may even be called with both infix and prefix arguments
+at the same time.  If you invoke a command as a suffix of a transient
+prefix command, but also want to pass prefix arguments to it, then
+first invoke the prefix command, and only after doing that invoke the
+prefix arguments, before finally invoking the suffix command.  If you
+instead began by providing the prefix arguments, then those would
+apply to the prefix command, not the suffix command.  Likewise, if you
+want to change infix arguments before invoking a suffix command with
+prefix arguments, then change the infix arguments before invoking the
+prefix arguments.  In other words, regular prefix arguments always
+apply to the next command, and since transient prefix, infix and
+suffix commands are just regular commands, the same applies to them.
+(Regular prefix keys behave differently because they are not commands
+at all, instead they are just incomplete key sequences, and those
+cannot be interrupted with prefix commands.)
+
 @node Defining Transients
 @section Defining Transients
 
@@ -1087,10 +1112,9 @@ Transients}) and adds the transient's infix and suffix 
bindings, as
 described below.
 
 Users and third-party packages can add additional bindings using
-functions such as @code{transient-insert-suffix} (@pxref{Modifying
-Existing Transients}).  These functions take a ``suffix
-specification'' as one of their arguments, which has the same form as
-the specifications used in @code{transient-define-prefix}.
+functions such as @code{transient-insert-suffix} (@pxref{Modifying Existing 
Transients}).  These functions take a ``suffix specification'' as one of
+their arguments, which has the same form as the specifications used in
+@code{transient-define-prefix}.
 
 @menu
 * Group Specifications::
@@ -1251,10 +1275,10 @@ the object's values just for the binding inside this 
transient.
 
 @item
 @var{DESCRIPTION} is the description, either a string or a function that
-returns a string.  The function should be a lambda expression to
-avoid ambiguity.  In some cases a symbol that is bound as a function
-would also work but to be safe you should use @code{:description} in that
-case.
+takes zero or one arguments (the suffix object) and returns a string.
+The function should be a lambda expression to avoid ambiguity.  In
+some cases a symbol that is bound as a function would also work but
+to be safe you should use @code{:description} in that case.
 @end itemize
 
 The next element is either a command or an argument.  This is the only
@@ -1475,63 +1499,55 @@ transient keymap is disallowed and trying to do so 
results in a
 warning.  This does not ``deactivate'' the transient.
 @end itemize
 
-But these are just the defaults.  Whether a certain command
-deactivates or ``exits'' the transient is configurable.  There is more
-than one way in which a command can be ``transient'' or ``non-transient'';
-the exact behavior is implemented by calling a so-called ``pre-command''
-function.  Whether non-suffix commands are allowed to be called is
-configurable per transient.
+The behavior can be changed for all suffixes of a particular prefix
+and/or for individual suffixes.  The values should nearly always be
+booleans, but certain functions, called ``pre-commands'', can also be
+used.  These functions are named @code{transient--do-VERB}, and the symbol
+@code{VERB} can be used as a shorthand.
 
-@itemize
-@item
-The transient-ness of suffix commands (including infix commands) is
-controlled by the value of their @code{transient} slot, which can be set
-either when defining the command or when adding a binding to a
-transient while defining the respective transient prefix command.
+A boolean is interpreted as answering the question "does the
+transient stay active, when this command is invoked?"  @code{t} means that
+the transient stays active, while @code{nil} means that invoking the command
+exits the transient.
 
-Valid values are booleans and the pre-commands described below.
+Note that when the suffix is a ``sub-prefix'', invoking that command
+always activates that sub-prefix, causing the outer prefix to no
+longer be active and displayed.  Here @code{t} means that when you exit the
+inner prefix, then the outer prefix becomes active again, while @code{nil}
+means that all outer prefixes are exited at once.
 
 @itemize
 @item
-@code{t} is equivalent to @code{transient--do-stay}.
-@item
-@code{nil} is equivalent to @code{transient--do-exit}.
-@item
-If @code{transient} is unbound (and that is actually the default for
-non-infix suffixes) then the value of the prefix's
-@code{transient-suffix} slot is used instead.  The default value of that
-slot is @code{nil}, so the suffix's @code{transient} slot being unbound is
-essentially equivalent to it being @code{nil}.
-@end itemize
+The behavior for non-suffixes can be set for a particular prefix,
+by the prefix's @code{transient-non-suffix} slot to a boolean, a suitable
+pre-command function, or a shorthand for such a function.  See
+@ref{Pre-commands for Non-Suffixes}.
 
 @item
-A suffix command can be a prefix command itself, i.e., a
-``sub-prefix''.  While a sub-prefix is active we nearly always want
-@kbd{C-g} to take the user back to the ``super-prefix''.  However in rare
-cases this may not be desirable, and that makes the following
-complication necessary:
+The common behavior for the suffixes of a particular prefix can be
+set using the prefix's @code{transient-suffixes} slot.
 
-For @code{transient-suffix} objects the @code{transient} slot is unbound.  We 
can
-ignore that for the most part because, as stated above, @code{nil} and the
-slot being unbound are equivalent, and mean ``do exit''.  That isn't
-actually true for suffixes that are sub-prefixes though.  For such
-suffixes unbound means ``do exit but allow going back'', which is the
-default, while @code{nil} means ``do exit permanently'', which requires that
-slot to be explicitly set to that value.
+The value specified in this slot does @strong{not} affect infixes.  Because
+it affects both regular suffixes as well as sub-prefixes, which
+have different needs, it is best to avoid explicitly specifying a
+function.
 
 @item
-The transient-ness of certain built-in suffix commands is specified
-using @code{transient-predicate-map}.  This is a special keymap, which
-binds commands to pre-commands (as opposed to keys to commands) and
-takes precedence over the @code{transient} slot.
+The behavior of an individual suffix can be changed using its
+@code{transient} slot.  While it is usually best to use a boolean, for this
+slot it can occasionally make sense to specify a function explicitly.
+
+Note that this slot can be set when defining a suffix command using
+@code{transient-define-suffix} and/or in the definition of the prefix.  If
+set in both places, then the latter takes precedence, as usual.
 @end itemize
 
-The available pre-command functions are documented below.  They are
-called by @code{transient--pre-command}, a function on @code{pre-command-hook} 
and
-the value that they return determines whether the transient is exited.
-To do so the value of one of the constants @code{transient--exit} or
-@code{transient--stay} is used (that way we don't have to remember if @code{t} 
means
-``exit'' or ``stay'').
+The available pre-command functions are documented in the following
+sub-sections.  They are called by @code{transient--pre-command}, a function
+on @code{pre-command-hook}, and the value that they return determines whether
+the transient is exited.  To do so the value of one of the constants
+@code{transient--exit} or @code{transient--stay} is used (that way we don't 
have to
+remember if @code{t} means ``exit'' or ``stay'').
 
 Additionally, these functions may change the value of @code{this-command}
 (which explains why they have to be called using @code{pre-command-hook}),
@@ -1539,11 +1555,39 @@ call @code{transient-export}, 
@code{transient--stack-zap} or @code{transient--st
 and set the values of @code{transient--exitp}, @code{transient--helpp} or
 @code{transient--editp}.
 
+For completeness sake, some notes about complications:
+
+@itemize
+@item
+The transient-ness of certain built-in suffix commands is specified
+using @code{transient-predicate-map}.  This is a special keymap, which
+binds commands to pre-commands (as opposed to keys to commands) and
+takes precedence over the prefix's @code{transient-suffix} slot, but not
+the suffix's @code{transient} slot.
+
+@item
+While a sub-prefix is active we nearly always want @kbd{C-g} to take the
+user back to the ``super-prefix'', even when the other suffixes don't
+do that.  However, in rare cases this may not be desirable, and that
+makes the following complication necessary:
+
+For @code{transient-suffix} objects the @code{transient} slot is unbound.  We 
can
+ignore that for the most part because @code{nil} and the slot being unbound
+are treated as equivalent, and mean ``do exit''.  That isn't actually
+true for suffixes that are sub-prefixes though.  For such suffixes
+unbound means ``do exit but allow going back'', which is the default,
+while @code{nil} means ``do exit permanently'', which requires that slot to
+be explicitly set to that value.
+@end itemize
+
 @anchor{Pre-commands for Infixes}
 @subheading Pre-commands for Infixes
 
 The default for infixes is @code{transient--do-stay}.  This is also the only
-function that makes sense for infixes.
+function that makes sense for infixes, which is why this predicate is
+used even if the value of the prefix's @code{transient-suffix} slot is 
@code{t}.  In
+extremely rare cases, one might want to use something else, which can
+be done by setting the infix's @code{transient} slot directly.
 
 @defun transient--do-stay
 Call the command without exporting variables and stay transient.
@@ -1554,23 +1598,16 @@ Call the command without exporting variables and stay 
transient.
 
 By default, invoking a suffix causes the transient to be exited.
 
-If you want a different default behavior for a certain transient
-prefix command, then set its @code{:transient-suffix} slot.  The value can be
-a boolean, answering the question "does the transient stay active,
-when a suffix command is invoked?"  @code{t} means that the transient stays
-active, while @code{nil} means that invoking a suffix exits the transient.
-In either case, the exact behavior depends on whether the suffix is
-itself a prefix (i.e., a sub-prefix), an infix or a regular suffix.
-
 The behavior for an individual suffix command can be changed by
-setting its @code{transient} slot to one of the following pre-commands.
+setting its @code{transient} slot to a boolean (which is highly recommended),
+or to one of the following pre-commands.
 
 @defun transient--do-exit
 Call the command after exporting variables and exit the transient.
 @end defun
 
 @defun transient--do-return
-Call the command after exporting variables and return to parent
+Call the command after exporting variables and return to the parent
 prefix.  If there is no parent prefix, then call @code{transient--do-exit}.
 @end defun
 
@@ -1578,9 +1615,10 @@ prefix.  If there is no parent prefix, then call 
@code{transient--do-exit}.
 Call the command after exporting variables and stay transient.
 @end defun
 
-The following pre-commands are suitable for sub-prefixes.  Only the
-first should ever explicitly be set as the value of the @code{transient}
-slot.
+The following pre-commands are only suitable for sub-prefixes.  It is
+not necessary to explicitly use these predicates because the correct
+predicate is automatically picked based on the value of the @code{transient}
+slot for the sub-prefix itself.
 
 @defun transient--do-recurse
 Call the transient prefix command, preparing for return to active
@@ -1588,15 +1626,25 @@ transient.
 
 Whether we actually return to the parent transient is ultimately
 under the control of each invoked suffix.  The difference between
-this pre-command and @code{transient--do-replace} is that it changes the
-value of the @code{transient-suffix} slot to @code{transient--do-return}.
+this pre-command and @code{transient--do-stack} is that it changes the
+value of the @code{transient-suffix} slot to @code{t}.
 
 If there is no parent transient, then only call this command and
 skip the second step.
 @end defun
 
+@defun transient--do-stack
+Call the transient prefix command, stacking the active transient.
+Push the active transient to the transient stack.
+
+Unless @code{transient--do-recurse} is explicitly used, this pre-command
+is automatically used for suffixes that are prefixes themselves,
+i.e., for sub-prefixes.
+@end defun
+
 @defun transient--do-replace
 Call the transient prefix command, replacing the active transient.
+Do not push the active transient to the transient stack.
 
 Unless @code{transient--do-recurse} is explicitly used, this pre-command
 is automatically used for suffixes that are prefixes themselves,
@@ -1618,17 +1666,17 @@ By default, non-suffixes (commands that are bound in 
other keymaps
 beside the transient keymap) cannot be invoked.  Trying to invoke
 such a command results in a warning and the transient stays active.
 
-If you want a different behavior, then set the @code{:transient-non-suffix}
-slot of the transient prefix command.  The value can be a boolean,
-answering the question, "is it allowed to invoke non-suffix commands?"
+If you want a different behavior, then set the @code{transient-non-suffix}
+slot of the transient prefix command.  The value should be a boolean,
+answering the question, "is it allowed to invoke non-suffix commands?,
+a pre-command function, or a shorthand for such a function.
 
-If the value is @code{t} or @code{transient--do-stay}, then non-suffixes can be
-invoked, when it is @code{nil} or @code{transient--do-warn} (the default) then 
they
-cannot be invoked.
+If the value is @code{t}, then non-suffixes can be invoked, when it is 
@code{nil}
+(the default) then they cannot be invoked.
 
-The only other recommended value is @code{transient--do-leave}.  If that is
-used, then non-suffixes can be invoked, but if one is invoked, then
-that exits the transient.
+The only other recommended value is @code{leave}.  If that is used, then
+non-suffixes can be invoked, but if one is invoked, then that exits
+the transient.
 
 @defun transient--do-warn
 Call @code{transient-undefined} and stay transient.
@@ -1870,6 +1918,24 @@ indicates that all remaining arguments are files.
 @item
 Classes used for infix commands that represent variables should
 derived from the abstract @code{transient-variable} class.
+
+@item
+The @code{transient-information} class is special in that suffixes that use
+this class are not associated with a command and thus also not with
+any key binding.  Such suffixes are only used to display arbitrary
+information, and that anywhere a suffix can appear.  Display-only
+suffix specifications take this form:
+
+@lisp
+([LEVEL] :info DESCRIPTION [KEYWORD VALUE]...)
+@end lisp
+
+The @code{:info} keyword argument replaces the @code{:description} keyword 
used for
+other suffix classes.  Other keyword arguments that you might want to
+set, include @code{:face}, predicate keywords (such as @code{:if}), and 
@code{:format}.
+By default the value of @code{:format} includes @code{%k}, which for this 
class is
+replaced with the empty string or spaces, if keys are being padded in
+the containing group.
 @end itemize
 
 Magit defines additional classes, which can serve as examples for the
@@ -1990,12 +2056,13 @@ Show help for the prefix, infix or suffix command 
represented by
 
 For prefixes, show the info manual, if that is specified using the
 @code{info-manual} slot.  Otherwise, show the manpage if that is specified
-using the @code{man-page} slot.  Otherwise, show the command's doc string.
+using the @code{man-page} slot.  Otherwise, show the command's
+documentation string.
 
-For suffixes, show the command's doc string.
+For suffixes, show the command's documentation string.
 
 For infixes, show the manpage if that is specified.  Otherwise show
-the command's doc string.
+the command's documentation string.
 @end defun
 
 @node Prefix Slots
@@ -2019,11 +2086,24 @@ determining whether the currently active transient 
prefix command
 remains active/transient when a suffix or arbitrary non-suffix
 command is invoked.  @xref{Transient State}.
 
+@item
+@code{refresh-suffixes} Normally suffix objects and keymaps are only setup
+once, when the prefix is invoked.  Setting this to @code{t}, causes them to
+be recreated after every command.  This is useful when using @code{:if...}
+predicates, and those need to be rerun for some reason.  Doing this
+is somewhat costly, and there is a risk of losing state, so this is
+disabled by default and still considered experimental.
+
 @item
 @code{incompatible} A list of lists.  Each sub-list specifies a set of
 mutually exclusive arguments.  Enabling one of these arguments
 causes the others to be disabled.  An argument may appear in
-multiple sub-lists.
+multiple sub-lists.  Arguments must me given in the same form as
+used in the @code{argument} or @code{argument-format} slot of the respective
+suffix objects, usually something like @code{--switch} or @code{--option=%s}.  
For
+options and @code{transient-switches} suffixes it is also possible to match
+against a specific value, as returned by @code{transient-infix-value},
+for example, @code{--option=one}.
 
 @item
 @code{scope} For some transients it might be necessary to have a sort of
@@ -2099,8 +2179,14 @@ It must contain the following %-placeholders:
 @end itemize
 
 @item
-@code{description} The description, either a string or a function that is
-called with no argument and returns a string.
+@code{description} The description, either a string or a function, which is
+called with zero or one argument (the suffix object), and returns a
+string.
+
+@item
+@code{face} Face used for the description.  In simple cases it is easier
+to use this instead of using a function as @code{description} and adding
+the styling there.  @code{face} is appended using 
@code{add-face-text-property}.
 
 @item
 @code{show-help} A function used to display help for the suffix.  If
@@ -2189,8 +2275,10 @@ function that takes the object as the only argument and 
which
 returns a prompt string.
 
 @item
-@code{choices} A list of valid values.  How exactly that is used depends on
-the class of the object.
+@code{choices} A list of valid values, or a function that returns such a
+list.  The latter is not implemented for @code{transient-switches}, because
+I couldn't think of a use-case.  How exactly the choices are used
+varies depending on the class of the suffix.
 @end itemize
 
 @anchor{Slots of @code{transient-variable}}
@@ -2241,6 +2329,10 @@ what happens if you use more than one.
 @code{if-not-derived} Enable if major-mode does not derive from value.
 @end itemize
 
+By default these predicates run when the prefix command is invoked,
+but this can be changes, using the @code{refresh-suffixes} prefix slot.
+See @ref{Prefix Slots}.
+
 One more slot is shared between group and suffix classes, @code{level}.  Like
 the slots documented above, it is a predicate, but it is used for a
 different purpose.  The value has to be an integer between 1
@@ -2248,331 +2340,6 @@ and 7.  @code{level} controls whether a suffix or a 
group should be
 available depending on user preference.
 @xref{Enabling and Disabling Suffixes}.
 
-@node Related Abstractions and Packages
-@chapter Related Abstractions and Packages
-
-@menu
-* Comparison With Prefix Keys and Prefix Arguments::
-* Comparison With Other Packages::
-@end menu
-
-@node Comparison With Prefix Keys and Prefix Arguments
-@section Comparison With Prefix Keys and Prefix Arguments
-
-While transient commands were inspired by regular prefix keys and
-prefix arguments, they are also quite different and much more complex.
-
-The following diagrams illustrate some of the differences.
-
-@itemize
-@item
-@samp{(c)} represents a return to the command loop.
-@item
-@samp{(+)} represents the user's choice to press one key or another.
-@item
-@samp{@{WORD@}} are possible behaviors.
-@item
-@samp{@{NUMBER@}} is a footnote.
-@end itemize
-
-@anchor{Regular Prefix Commands}
-@subheading Regular Prefix Commands
-
-@xref{Prefix Keys,,,elisp,}.
-
-@example
-                                  ,--> command1 --> (c)
-                                  |
-(c)-(+)-> prefix command or key --+--> command2 --> (c)
-                                  |
-                                  `--> command3 --> (c)
-@end example
-
-@anchor{Regular Prefix Arguments}
-@subheading Regular Prefix Arguments
-
-@xref{Prefix Command Arguments,,,elisp,}.
-
-@example
-        ,----------------------------------,
-        |                                  |
-        v                                  |
-(c)-(+)---> prefix argument command --(c)-(+)-> any command --> (c)
-               |                                        ^        |
-               |                                        |        |
-               `-- sets or changes --, ,-- maybe used --'        |
-                                     | |                         |
-                                     v |                         |
-                          prefix argument state                  |
-                                      ^                          |
-                                      |                          |
-                                      `-------- discards --------'
-@end example
-
-@anchor{Transients}
-@subheading Transients
-
-(∩`-´)⊃━☆゚.*・。゚
-
-This diagram ignores the infix value and external state:
-
-@example
-(c)
- |        ,- @{stay@} ------<-,-<------------<-,-<---,
-(+)       |                 |                |     |
- |        |                 |                |     |
- |        |   ,--> infix1 --|                |     |
- |        |   |             |                |     |
- |        |   |--> infix2 --|                |     |
- v        v   |             |                |     |
- prefix -(c)-(+)-> infix3 --'                ^     |
-              |                              |     |
-              |---------------> suffix1 -->--|     |
-              |                              |     |
-              |---------------> suffix2 ----@{1@}------> @{exit@} --> (c)
-              |                                    |
-              |---------------> suffix3 -------------> @{exit@} --> (c)
-              |                                    |
-              `--> any command --@{2@}-> @{warn@} -->--|
-                                  |                |
-                                  |--> @{noop@} -->--|
-                                  |                |
-                                  |--> @{call@} -->--'
-                                  |
-                                  `------------------> @{exit@} --> (c)
-@end example
-
-This diagram takes the infix value into account to an extend, while
-still ignoring external state:
-
-@example
-(c)
- |        ,- @{stay@} ------<-,-<------------<-,-<---,
-(+)       |                 |                |     |
- |        |                 |                |     |
- |        |   ,--> infix1 --|                |     |
- |        |   |    |        |                |     |
- |        |   ,--> infix2 --|                |     |
- v        v   |    |        |                |     |
- prefix -(c)-(+)-> infix3 --'                |     |
-              |    |                         ^     |
-              |    |                         |     |
-              |---------------> suffix1 -->--|     |
-              |    |             ^           |     |
-              |    |             |           |     |
-              |---------------> suffix2 ----@{1@}------> @{exit@} --> (c)
-              |    |             ^                 |     |
-              |    |             |                 |     v
-              |    |             |                 |     |
-              |---------------> suffix3 -------------> @{exit@} --> (c)
-              |    |             ^                 |     |
-              | sets             |                 |     v
-              |    |             maybe             |     |
-              |    |             used              |     |
-              |    |             |                 |     |
-              |    |     infix --'                 |     |
-              |    `---> value                     |     |
-              |           ^                        |     |
-              |           |                        |     |
-              |       hides                        |     |
-              |           |                        |     |
-              |           `--------------------------<---|
-              |                                    |     |
-              `--> any command --@{2@}-> @{warn@} -->--|     |
-                                  |                |     |
-                                  |--> @{noop@} -->--|     |
-                                  |                |     |
-                                  |--> @{call@} -->--'     ^
-                                  |                      |
-                                  `------------------> @{exit@} --> (c)
-@end example
-
-This diagram provides more information about the infix value
-and also takes external state into account.
-
-@example
-                                       ,----sets--- "anything"
-                                       |
-                                       v
-                      ,---------> external
-                      |           state
-                      |            | |
-                      |  initialized |                      ☉‿⚆
-                   sets         from |
-                      |            | maybe
-                      | ,----------' used
-                      | |            |
-(c)                   | |            v
- |        ,- @{stay@} --|---<-,-<------|-----<-,-<---,
-(+)       |           | |   |        |       |     |
- |        |           | v   |        |       |     |
- |        |   ,--> infix1 --|        |       |     |
- |        |   |       | |   |        |       |     |
- |        |   |       | v   |        |       |     |
- |        |   ,--> infix2 --|        |       |     |
- |        |   |    | ^      |        |       |     |
- v        v   |    | |      |        |       |     |
- prefix -(c)-(+)-> infix3 --'        |       |     |
-              |    | ^               |       ^     |
-              |    | |               v       |     |
-              |---------------> suffix1 -->--|     |
-              |    | |            ^  |       |     |
-              |    | |            |  v       |     |
-              |---------------> suffix2 ----@{1@}------> @{exit@} --> (c)
-              |    | |            ^  |             |     |
-              |    | |            |  |             |     v
-              |    | |            |  v             |     |
-              |---------------> suffix3 -------------> @{exit@} --> (c)
-              |    | |            ^                |     |
-              | sets |            |                |     v
-              |    | initialized  maybe            |     |
-              |    | from         used             |     |
-              |    | |            |                |     |
-              |    | `-- infix ---'                |     |
-              |    `---> value -----------------------------> persistent
-              |           ^ ^                      |     |    across
-              |           | |                      |     |    invocations -,
-              |       hides |                      |     |                 |
-              |           | `----------------------------------------------'
-              |           |                        |     |
-              |           `--------------------------<---|
-              |                                    |     |
-              `--> any command --@{2@}-> @{warn@} -->--|     |
-                                  |                |     |
-                                  |--> @{noop@} -->--|     |
-                                  |                |     |
-                                  |--> @{call@} -->--'     ^
-                                  |                      |
-                                  `------------------> @{exit@} --> (c)
-@end example
-
-@itemize
-@item
-@samp{@{1@}} Transients can be configured to be exited when a suffix command
-is invoked.  The default is to do so for all suffixes except for
-those that are common to all transients and which are used to
-perform tasks such as providing help and saving the value of the
-infix arguments for future invocations.  The behavior can also be
-specified for individual suffix commands and may even depend on
-state.
-
-@item
-@samp{@{2@}} Transients can be configured to allow the user to invoke
-non-suffix commands.  The default is to not allow that and instead
-warn the user.
-@end itemize
-
-Despite already being rather complex, even the last diagram leaves out
-many details.  Most importantly it implies that the decision whether
-to remain transient is made later than it actually is made (for the
-most part a function on @code{pre-command-hook} is responsible).  But such
-implementation details are of little relevance to users and are
-covered elsewhere.
-
-@node Comparison With Other Packages
-@section Comparison With Other Packages
-
-@anchor{Magit-Popup}
-@subheading Magit-Popup
-
-Transient is the successor to Magit-Popup (@pxref{Top,,,magit-popup,}).
-
-One major difference between these two implementations of the same
-ideas is that while Transient uses transient keymaps and embraces the
-command-loop, Magit-Popup implemented an inferior mechanism that does
-not use transient keymaps and that instead of using the command-loop
-implements a naive alternative based on @code{read-char}.
-
-Magit-Popup does not use classes and generic functions and defining a
-new command type is near impossible as it involves adding hard-coded
-special-cases to many functions.  Because of that only a single new
-type was added, which was not already part of Magit-Popup's initial
-release.
-
-A lot of things are hard-coded in Magit-Popup.  One random example is
-that the key bindings for switches must begin with @code{-} and those for
-options must begin with @code{=}.
-
-@anchor{Hydra}
-@subheading Hydra
-
-Hydra (see @uref{https://github.com/abo-abo/hydra}) is another package that
-provides features similar to those of Transient.
-
-Both packages use transient keymaps to make a set of commands
-temporarily available and show the available commands in a popup
-buffer.
-
-A Hydra ``body'' is equivalent to a Transient ``prefix'' and a Hydra
-``head'' is equivalent to a Transient ``suffix''.  Hydra has no equivalent
-of a Transient ``infix''.
-
-Both hydras and transients can be used as simple command dispatchers.
-Used like this they are similar to regular prefix commands and prefix
-keys, except that the available commands are shown in the popup buffer.
-
-(Another package that does this is @code{which-key}. It does so automatically
-for any incomplete key sequence.  The advantage of that approach is
-that no additional work is necessary; the disadvantage is that the
-available commands are not organized semantically.)
-
-Both Hydra and Transient provide features that go beyond simple
-command dispatchers:
-
-@itemize
-@item
-Invoking a command from a hydra does not necessarily exit the hydra.
-That makes it possible to invoke the same command again, but using a
-shorter key sequence (i.e., the key that was used to enter the hydra
-does not have to be pressed again).
-
-Transient supports that too, but for now this feature is not a focus
-and the interface is a bit more complicated.  A very basic example
-using the current interface:
-
-@lisp
-(transient-define-prefix outline-navigate ()
-  :transient-suffix     'transient--do-stay
-  :transient-non-suffix 'transient--do-warn
-  [("p" "previous visible heading" outline-previous-visible-heading)
-   ("n" "next visible heading" outline-next-visible-heading)])
-@end lisp
-
-@item
-Transient supports infix arguments; values that are set by infix
-commands and then consumed by the invoked suffix command(s).
-
-To my knowledge, Hydra does not support that.
-@end itemize
-
-Both packages make it possible to specify how exactly the available
-commands are outlined:
-
-@itemize
-@item
-With Hydra this is often done using an explicit format string, which
-gives authors a lot of flexibility and makes it possible to do fancy
-things.
-
-The downside of this is that it becomes harder for a user to add
-additional commands to an existing hydra and to change key bindings.
-
-@item
-Transient allows the author of a transient to organize the commands
-into groups and the use of generic functions allows authors of
-transients to control exactly how a certain command type is
-displayed.
-
-However while Transient supports giving sections a heading it does
-not currently support giving the displayed information more
-structure by, for example, using box-drawing characters.
-
-That could be implemented by defining a new group class, which lets
-the author specify a format string.  It should be possible to
-implement that without modifying any existing code, but it does not
-currently exist.
-@end itemize
-
 @node FAQ
 @appendix FAQ
 
@@ -2584,10 +2351,10 @@ Yes, see @code{transient-display-buffer-action} in 
@ref{Configuration}.
 @anchor{How can I copy text from the popup buffer?}
 @appendixsec How can I copy text from the popup buffer?
 
-To be able to mark text in any transient popup buffer using the mouse,
-you have to add the following binding.  Note that the region won't be
-visualized, while doing so.  After you have quit the transient popup,
-you will be able to yank it another buffer.
+To be able to mark text in Transient's popup buffer using the mouse,
+you have to add the below binding.  Note that for technical reasons,
+the region won't be visualized, while doing so.  After you have quit
+the transient popup, you will be able to yank it in another buffer.
 
 @lisp
 (keymap-set transient-predicate-map
@@ -2595,6 +2362,16 @@ you will be able to yank it another buffer.
             #'transient--do-stay)
 @end lisp
 
+@anchor{How does Transient compare to prefix keys and universal arguments?}
+@appendixsec How does Transient compare to prefix keys and universal arguments?
+
+See 
@uref{https://github.com/magit/transient/wiki/Comparison-with-prefix-keys-and-universal-arguments}.
+
+@anchor{How does Transient compare to Magit-Popup and Hydra?}
+@appendixsec How does Transient compare to Magit-Popup and Hydra?
+
+See 
@uref{https://github.com/magit/transient/wiki/Comparison-with-other-packages}.
+
 @anchor{Why did some of the key bindings change?}
 @appendixsec Why did some of the key bindings change?
 
@@ -2657,7 +2434,7 @@ for @kbd{q}.
 If you want to get @kbd{q}'s old binding back then you can do so.  Doing
 that is a bit more complicated than changing a single key binding, so
 I have implemented a function, @code{transient-bind-q-to-quit} that makes the
-necessary changes.  See its doc string for more information.
+necessary changes.  See its documentation string for more information.
 
 @node Keystroke Index
 @appendix Keystroke Index
diff --git a/doc/misc/url.texi b/doc/misc/url.texi
index 6517f858324..db717633faf 100644
--- a/doc/misc/url.texi
+++ b/doc/misc/url.texi
@@ -21,7 +21,7 @@
 @copying
 This is the manual for the @code{url} Emacs Lisp library.
 
-Copyright @copyright{} 1993--1999, 2002, 2004--2023 Free Software
+Copyright @copyright{} 1993--1999, 2002, 2004--2024 Free Software
 Foundation, Inc.
 
 @quotation
@@ -1231,8 +1231,6 @@ the @file{*URL-DEBUG*} buffer.
 A number means log all messages and show them with @code{message}.
 It may also be a list of the types of messages to be logged.
 @end defopt
-@defopt url-personal-mail-address
-@end defopt
 @defopt url-privacy-level
 @end defopt
 @defopt url-lastloc-privacy-level
diff --git a/doc/misc/use-package.texi b/doc/misc/use-package.texi
index 37ed50ab2b1..d834e1be754 100644
--- a/doc/misc/use-package.texi
+++ b/doc/misc/use-package.texi
@@ -13,7 +13,7 @@
 @copying
 This manual is for use-package @value{USEP_VER} @value{USEP_DIST}.
 
-Copyright @copyright{} 2022--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2022--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/vhdl-mode.texi b/doc/misc/vhdl-mode.texi
index a5ad92ca01e..86df723aa5a 100644
--- a/doc/misc/vhdl-mode.texi
+++ b/doc/misc/vhdl-mode.texi
@@ -10,7 +10,7 @@
 @copying
 This file documents VHDL Mode, an Emacs mode for editing VHDL code.
 
-Copyright @copyright{} 1995--2008, 2010, 2012, 2015--2023 Free Software
+Copyright @copyright{} 1995--2008, 2010, 2012, 2015--2024 Free Software
 Foundation, Inc.
 
 @quotation
diff --git a/doc/misc/vip.texi b/doc/misc/vip.texi
index f5a6dfe9f8c..0248edb328f 100644
--- a/doc/misc/vip.texi
+++ b/doc/misc/vip.texi
@@ -4,7 +4,7 @@
 @include docstyle.texi
 
 @copying
-Copyright @copyright{} 1987, 2001--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1987, 2001--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/viper.texi b/doc/misc/viper.texi
index e0ab563ca33..01e94de4e48 100644
--- a/doc/misc/viper.texi
+++ b/doc/misc/viper.texi
@@ -8,7 +8,7 @@
 @include docstyle.texi
 
 @copying
-Copyright @copyright{} 1995--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1995--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/vtable.texi b/doc/misc/vtable.texi
index de652eb227f..a4f2ed29d93 100644
--- a/doc/misc/vtable.texi
+++ b/doc/misc/vtable.texi
@@ -12,7 +12,7 @@
 @copying
 This file documents the GNU vtable.el package.
 
-Copyright @copyright{} 2022--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2022--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/widget.texi b/doc/misc/widget.texi
index eb411f29c5c..cfb9d2211cf 100644
--- a/doc/misc/widget.texi
+++ b/doc/misc/widget.texi
@@ -9,7 +9,7 @@
 @c %**end of header
 
 @copying
-Copyright @copyright{} 2000--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2000--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -1384,6 +1384,15 @@ a specific way.  If present, @var{value} is used to 
initialize the
 @code{:value} property.  When created, it inserts the value as a
 string in the buffer.
 
+@noindent
+Example:
+
+@lisp
+(widget-create 'item :tag "Today is" :format "%t: %v\n"
+               (format-time-string "%d-%m-%Y"))
+@end lisp
+
+
 By default, it has the following properties:
 
 @table @code
@@ -1428,6 +1437,20 @@ The @var{value}, if present, is used to initialize the 
@code{:value}
 property.  The value should be a string, which will be inserted in the
 buffer.
 
+@noindent
+Example:
+
+@lisp
+(widget-create 'link
+               :button-prefix ""
+               :button-suffix ""
+               :tag "Mail yourself"
+               :action #'(lambda (widget &optional _event)
+                           (compose-mail-other-window (widget-value widget)))
+               user-mail-address)
+@end lisp
+
+
 By default, it has the following properties:
 
 @table @code
@@ -1471,6 +1494,31 @@ A widget to represent a link to a web page.  Its super 
is the
 It overrides the @code{:action} property to open up the @var{url}
 specified.
 
+@noindent
+Example:
+
+@lisp
+@group
+(widget-create 'url-link
+               :button-prefix ""
+               :button-suffix ""
+               ;; Return appropriate face.
+               :button-face-get (lambda (widget)
+                 (if (widget-get widget :visited)
+                     'link-visited
+                   'link))
+               :format "%[%t%]"
+               :tag "Browse this manual"
+               :action (lambda (widget &optional _event)
+                          (widget-put widget :visited t)
+                          ;; Takes care of redrawing the widget.
+                          (widget-value-set widget (widget-value widget))
+                          ;; And then call the original function.
+                          (widget-url-link-action widget))
+               
"https://www.gnu.org/software/emacs/manual/html_mono/widget.html";)
+@end group
+@end lisp
+
 @node info-link
 @subsection The @code{info-link} Widget
 @findex info-link@r{ widget}
@@ -1487,6 +1535,17 @@ A widget to represent a link to an info file.  Its super 
is the
 It overrides the @code{:action} property, to a function to start the
 built-in Info reader on @var{address}, when invoked.
 
+@noindent
+Example:
+
+@lisp
+(widget-create 'info-link
+               :button-prefix ""
+               :button-suffix ""
+               :tag "Browse this manual"
+               "(widget) info-link")))
+@end lisp
+
 @node function-link
 @subsection The @code{function-link} Widget
 @findex function-link@r{ widget}
@@ -1502,6 +1561,17 @@ A widget to represent a link to an Emacs function.  Its 
super is the
 It overrides the @code{:action} property, to a function to describe
 @var{function}.
 
+@noindent
+Example:
+
+@lisp
+(widget-create 'function-link
+               :button-prefix ""
+               :button-suffix ""
+               :tag "Describe the function that gets called"
+               #'widget-function-link-action)
+@end lisp
+
 @node variable-link
 @subsection The @code{variable-link} Widget
 @findex variable-link@r{ widget}
@@ -1517,6 +1587,17 @@ A widget to represent a link to an Emacs variable.  Its 
super is the
 It overrides the @code{:action} property, to a function to describe
 @var{var}.
 
+@noindent
+Example:
+
+@lisp
+(widget-create 'variable-link
+               :button-prefix ""
+               :button-suffix ""
+               :tag "What setting controls button-prefix?"
+               'widget-button-prefix)
+@end lisp
+
 @node face-link
 @subsection The @code{face-link} Widget
 @findex face-link@r{ widget}
@@ -1532,6 +1613,17 @@ A widget to represent a link to an Emacs face.  Its 
super is the
 It overrides the @code{:action} property, to a function to describe
 @var{face}.
 
+@noindent
+Example:
+
+@lisp
+(widget-create 'face-link
+               :button-prefix ""
+               :button-suffix ""
+               :tag "Which face is this one?"
+               'widget-button)
+@end lisp
+
 @node file-link
 @subsection The @code{file-link} Widget
 @findex file-link@r{ widget}
@@ -1547,6 +1639,19 @@ A widget to represent a link to a file.  Its super is the
 It overrides the @code{:action} property, to a function to find the file
 @var{file}.
 
+@noindent
+Example:
+
+@lisp
+(let ((elisp-files (directory-files user-emacs-directory t ".el$")))
+  (dolist (file elisp-files)
+    (widget-create 'file-link
+                   :button-prefix ""
+                   :button-suffix ""
+                   file)
+    (widget-insert "\n")))
+@end lisp
+
 @node emacs-library-link
 @subsection The @code{emacs-library-link} Widget
 @findex emacs-library-link@r{ widget}
@@ -1562,6 +1667,17 @@ A widget to represent a link to an Emacs Lisp file.  Its 
super is the
 It overrides the @code{:action} property, to a function to find the file
 @var{file}.
 
+@noindent
+Example:
+
+@lisp
+(widget-create 'emacs-library-link
+               :button-prefix ""
+               :button-suffix ""
+               :tag "Show yourself, Widget Library!"
+               "wid-edit.el")
+@end lisp
+
 @node emacs-commentary-link
 @subsection The @code{emacs-commentary-link} Widget
 @findex emacs-commentary-link@r{ widget}
@@ -1577,6 +1693,17 @@ file.  Its super is the @code{link} widget.
 It overrides the @code{:action} property, to a function to find the file
 @var{file} and put point in the Comment section.
 
+@noindent
+Example:
+
+@lisp
+(widget-create 'emacs-commentary-link
+               :button-prefix ""
+               :button-suffix ""
+               :tag "Check our good friend Customize"
+               "cus-edit.el")
+@end lisp
+
 @node  push-button
 @subsection The @code{push-button} Widget
 @findex push-button@r{ widget}
@@ -1703,7 +1830,7 @@ A variable that holds the history of field minibuffer 
edits.
 
 @item :prompt-value
 A function that uses the @code{:prompt-internal} function and the
-@code{:prompt-history} value to prompt for a string, and retun the
+@code{:prompt-history} value to prompt for a string, and return the
 user response in the external format.
 
 @item :action
@@ -1714,7 +1841,7 @@ Function that takes care of creating the widget, 
respecting its
 @code{:size} and @code{:value}.
 
 @item :value-set
-Function to use to modify programatically the current value of the
+Function to use to modify programmatically the current value of the
 widget.
 
 @item :value-delete
@@ -2009,6 +2136,33 @@ A widget that can toggle between two states.  Its super 
is the
 The widget has two possible states, @samp{on} and @samp{off}, which
 correspond to a @code{t} or @code{nil} value, respectively.
 
+@noindent
+Example:
+
+@lisp
+@group
+(widget-insert "Press the button to activate/deactivate the field: ")
+(widget-create 'toggle
+               :notify (lambda (widget &rest _ignored)
+                          (widget-apply widget-example-field
+                                        (if (widget-value widget)
+                                            :activate
+                                          :deactivate))))
+(widget-insert "\n")
+@end group
+@group
+(setq widget-example-field
+      (widget-create 'editable-field
+                     :deactivate (lambda (widget)
+                                   (widget-specify-inactive
+                                    widget
+                                    (widget-field-start widget)
+                                    (widget-get widget :to)))))
+(widget-apply widget-example-field :deactivate)))
+@end group
+@end lisp
+
+
 It either overrides or adds the following properties:
 
 @table @code
@@ -2148,6 +2302,21 @@ The @var{type} arguments represent each checklist item.  
The widget's
 value will be a list containing the values of all checked @var{type}
 arguments.
 
+@noindent
+Example:
+
+@lisp
+(widget-create 'checklist
+               :notify (lambda (widget child &optional _event)
+                         (funcall
+                           (widget-value (widget-get-sibling child))
+                           'toggle))
+               :value (list 'tool-bar-mode 'menu-bar-mode)
+               '(item :tag "Tool-bar" tool-bar-mode)
+               '(item :tag "Menu-bar" menu-bar-mode))))
+@end lisp
+
+
 It either overrides or adds the following properties:
 
 @table @code
@@ -2455,7 +2624,7 @@ difference from the @code{const} widget is that they will 
allow the
 user to see the variable or function documentation for the symbol.
 
 This is accomplished via using the @samp{%h} format escape, and adding
-an appropiate @code{:documentation-property} function for each widget.
+an appropriate @code{:documentation-property} function for each widget.
 
 @deffn Widget variable-item
 An immutable symbol that is bound as a variable.
@@ -2899,6 +3068,59 @@ The predefined functions 
@code{widget-types-convert-widget} and
 @code{widget-value-convert-widget} can be used here.
 @end table
 
+@noindent
+Example:
+
+@lisp
+@group
+(defvar widget-ranged-integer-map
+  (let ((map (copy-keymap widget-keymap)))
+    (define-key map [up] #'widget-ranged-integer-increase)
+    (define-key map [down] #'widget-ranged-integer-decrease)
+    map))
+@end group
+
+@group
+(define-widget 'ranged-integer 'integer
+  "A ranged integer widget."
+  :min-value most-negative-fixnum
+  :max-value most-positive-fixnum
+  :keymap widget-ranged-integer-map)
+@end group
+
+@group
+(defun widget-ranged-integer-change (widget how)
+  "Change the value of the ranged-integer WIDGET, according to HOW."
+  (let* ((value (widget-value widget))
+         (newval (cond
+                  ((eq how 'up)
+                   (if (< (1+ value) (widget-get widget :max-value))
+                       (1+ value)
+                     (widget-get widget :max-value)))
+                  ((eq how 'down)
+                   (if (> (1- value) (widget-get widget :min-value))
+                       (1- value)
+                     (widget-get widget :min-value)))
+                  (t (error "HOW has a bad value"))))
+         (inhibit-read-only t))
+    (widget-value-set widget newval)))
+@end group
+
+@group
+(defun widget-ranged-integer-increase (widget)
+  "Increase the value of the ranged-integer WIDGET."
+  (interactive (list (widget-at)))
+  (widget-ranged-integer-change widget 'up))
+@end group
+
+@group
+(defun widget-ranged-integer-decrease (widget)
+  "Decrease the value of the ranged-integer WIDGET."
+  (interactive (list (widget-at)))
+  (widget-ranged-integer-change widget 'down))
+@end group
+@end lisp
+
 @node Inspecting Widgets
 @chapter Inspecting Widgets
 @cindex widget browser
diff --git a/doc/misc/wisent.texi b/doc/misc/wisent.texi
index e1fee10d954..9738d790259 100644
--- a/doc/misc/wisent.texi
+++ b/doc/misc/wisent.texi
@@ -24,7 +24,7 @@
 @c %**end of header
 
 @copying
-Copyright @copyright{} 1988--1993, 1995, 1998--2004, 2007, 2012--2023
+Copyright @copyright{} 1988--1993, 1995, 1998--2004, 2007, 2012--2024
 Free Software Foundation, Inc.
 
 @c Since we are both GNU manuals, we do not need to ack each other here.
diff --git a/doc/misc/woman.texi b/doc/misc/woman.texi
index 32543b9e48d..ecef81996ec 100644
--- a/doc/misc/woman.texi
+++ b/doc/misc/woman.texi
@@ -15,7 +15,7 @@
 This file documents WoMan: A program to browse Unix manual pages ``W.O.
 (without) man''.
 
-Copyright @copyright{} 2001--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2001--2024 Free Software Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/etc/CALC-NEWS b/etc/CALC-NEWS
index a466a9db40b..06d4a3fc948 100644
--- a/etc/CALC-NEWS
+++ b/etc/CALC-NEWS
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Calc is an advanced desk calculator for GNU Emacs.
diff --git a/etc/ChangeLog.1 b/etc/ChangeLog.1
index f7786775e50..0c7e432bba9 100644
--- a/etc/ChangeLog.1
+++ b/etc/ChangeLog.1
@@ -6891,7 +6891,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1993-1999, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1993-1999, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/etc/DEBUG b/etc/DEBUG
index 5aeb38c6460..4eae090621f 100644
--- a/etc/DEBUG
+++ b/etc/DEBUG
@@ -1,6 +1,6 @@
 Debugging GNU Emacs
 
-Copyright (C) 1985, 2000-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 2000-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 ** Preliminaries
@@ -605,7 +605,17 @@ recommend to follow the procedure below to try to identify 
the cause:
  . Reduce the problematic .el file to the minimum by bisection, and
    try identifying the function that causes the problem.
 
- . Reduce the problematic function to the minimal code that still
+ . Try natively compiling the problematic file with
+   'native-comp-speed' set to 1 or even zero.  If doing that solves
+   the problem, you can use
+
+     (declare (speed 1))
+
+   at the beginning of the body of suspected function(s) to change
+   'native-comp-speed' only for those functions -- this could help you
+   identify the function(s) which cause(s) the problem.
+
+ . Reduce the problematic function(s) to the minimal code that still
    reproduces the problem.
 
  . Study the problem's artifacts, like Lisp or C backtraces, to try
@@ -854,11 +864,6 @@ in your ~/.emacs file.  When the problem happens, exit the 
Emacs that
 you were running, kill it, and rename the two files.  Then you can start
 another Emacs without clobbering those files, and use it to examine them.
 
-An easy way to see if too much text is being redrawn on a terminal is to
-evaluate '(setq inverse-video t)' before you try the operation you think
-will cause too much redrawing.  This doesn't refresh the screen, so only
-newly drawn text is in inverse video.
-
 ** Debugging LessTif
 
 If you encounter bugs whereby Emacs built with LessTif grabs all mouse
@@ -923,7 +928,10 @@ data that is modified only very rarely.)
 
 It is also useful to look at the corrupted object or data structure in
 a fresh Emacs session and compare its contents with a session that you
-are debugging.
+are debugging.  This might be somewhat harder on modern systems which
+randomize addresses of running executables (the so-called Address
+Space Layout Randomization, or ASLR, feature).  If you have this
+problem, see below under "How to disable ASLR".
 
 ** Debugging the TTY (non-windowed) version
 
@@ -1075,6 +1083,37 @@ suppresses some Valgrind false alarms during Emacs 
garbage collection:
 Unfortunately Valgrind suppression files tend to be system-dependent,
 so you will need to keep one around that matches your system.
 
+** How to disable ASLR
+
+Modern systems use the so-called Address Space Layout Randomization,
+(ASLR) feature, which randomizes the base address of running programs,
+making it harder for malicious software or hackers to find the address
+of some function or variable in a running program by looking at its
+executable file.  This causes the address of the same symbol to be
+different across rerunning of the same program.  Sometimes, it can be
+useful to disable ASLR, for example, if you want to compare objects in
+two different Emacs sessions.
+
+On GNU/Linux, you can disable ASLR temporarily with the following
+shell command:
+
+  echo 0 > /proc/sys/kernel/randomize_va_space
+
+or by running Emacs in an environment where ASLR is temporarily
+disabled:
+
+  setarch -R emacs [args...]
+
+To disable ASLR in Emacs on MS-Windows, you will have to rebuild Emacs
+while adding '-Wl,-disable-dynamicbase' to LD_SWITCH_SYSTEM_TEMACS
+variable defined in src/Makefile.  Alternatively, use some tool to
+edit the PE header of the Emacs executable file and reset the
+DYNAMIC_BASE (0x40) flag in the DllCharacteristics flags recorded by
+the PE header.
+
+On macOS, there's no official way for disabling ASLR, but there are
+various hacks that can be found by searching the Internet.
+
 ** How to recover buffer contents from an Emacs core dump file
 
 The file etc/emacs-buffer.gdb defines a set of GDB commands for
@@ -1142,7 +1181,7 @@ one to upload, like so:
   ../java/debug.sh --gdbserver /path/to/gdbserver
 
 This Gdbserver should be statically linked or compiled using the
-Android NDK, and must target the same architecture as the debugee
+Android NDK, and must target the same architecture as the debugged
 Emacs binary.  Older versions of the Android NDK (such as r24)
 distribute suitable Gdbserver binaries, usually located within
 
diff --git a/etc/DISTRIB b/etc/DISTRIB
index 359422ae895..66f28858298 100644
--- a/etc/DISTRIB
+++ b/etc/DISTRIB
@@ -1,7 +1,7 @@
                                                -*- text -*-
             GNU Emacs availability information
 
-Copyright (C) 1986-1993, 1995, 1998, 2000-2023 Free Software Foundation,
+Copyright (C) 1986-1993, 1995, 1998, 2000-2024 Free Software Foundation,
 Inc.
 See the end of the file for license conditions.
 
diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS
index 2f54dc43cbf..12e7d3f6b9b 100644
--- a/etc/EGLOT-NEWS
+++ b/etc/EGLOT-NEWS
@@ -1,6 +1,6 @@
 Eglot NEWS                                                     -*- outline -*-
 
-Copyright (C) 2018-2023 Free Software Foundation, Inc.
+Copyright (C) 2018-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send Eglot bug reports to 'bug-gnu-emacs@gnu.org', and Cc (or
@@ -20,15 +20,43 @@ https://github.com/joaotavora/eglot/issues/1234.
 
 * Changes in upcoming Eglot
 
-** Diff previews of edits and new variable 'eglot-confirm-server-edits'
+
+* Changes in Eglot 1.17 (25/1/2024)
+
+** Fixes to completion (github#847, github#1349)
+
+** Fix code-action gathering for some servers (github#847)
+
+** Experimental support for Eglot-only subprojects
+
+Until project.el's support for subprojects improves, github#1337
+describes a reasonably sane way to configure nested sub-projects
+within a larger one just for Eglot purposes.
+
+
+* Changes in Eglot 1.16 (27/12/2023)
+
+** Code actions can be previewed in diff format
 
 The variable 'eglot-confirm-server-edits' replaces the obsolete
 'eglot-confirm-server-initiated-edits' and brings about a new
-confirmation model, making it possible to have only certain commands
-require user confirmation.  The type of confirmation has also been
-enhanced.  In particular it allows a temporary 'diff-mode' buffer to
-display the proposed changes, so the user can apply them one by one.
-See bug#60338.
+confirmation model for code actions, making it possible to have only
+certain commands require user confirmation.  It allows a temporary
+'diff-mode' buffer to display the proposed changes, so the user can
+apply them one by one.  See bug#60338.
+
+** Completion sorting has been fixed
+
+In some situations, Eglot was not respecting the completion sort order
+decided by the language server, falling back on the sort order
+determined by the 'flex' completion style instead.  See github#1306.
+
+** Improve mouse invocation of code actions
+
+When invoking code actions by middle clicking with the mouse on
+Flymake diagnostics, it was often the case that Eglot didn't request
+code actions correctly and thus no actions were offered to the user.
+This has been fixed.  See github#1295.
 
 ** Optimized file-watching capability
 
@@ -37,24 +65,43 @@ watching requests.  This change slightly reduces the number 
of file
 watcher objects requested from the operating system, which can be a
 problem, particularly on Mac OS.  See github#1228 and github#1226.
 
-** Fixed "onTypeFormatting" feature
+** Faster, more accurate, event logging
+
+The Eglot events buffer takes advantage of new functionality in
+Jsonrpc 1.23.  By default, Lisp-style printing of JSON-RPC message (a
+common cause of performance degradation) is disabled.  The full
+original JSON message is presented instead.  See new variable
+'eglot-events-buffer-config', which replaces the obsolete
+'eglot-events-buffer-size'.
+
+** 'textdocument/onTypeFormatting' feature has been fixed
 
 For 'newline' commands, Eglot sometimes sent the wrong character code
-to the server.  Also made this feature less chatty in the mode-line
+to the server.  Also this feature is now less chatty in the mode-line
 and messages buffer.
 
-** Fixed completion sorting
+** Partial fix C-M-i "middle-of-symbol" completions (github#1339)
 
-In some situations, Eglot was not respecting the completion sort order
-decided by the language server, falling back on the sort order
-determined by the 'flex' completion style instead.  See github#1306.
+** Add "Extending Eglot" section to manual
 
-** Improve mouse invocation of code actions
+** Fixed Elisp interface 'eglot-lsp-context' (github#1336, github#1337)
 
-When invoking code actions by middle clicking with the mouse on
-Flymake diagnostics, it was often the case that Eglot didn't request
-code actions correctly and thus no actions were offered to the user.
-This has been fixed. github#1295
+** Supports LSP's 'window/showRequest' (bug#62116)
+
+** The self-upgrade command is now called 'eglot-upgrade-eglot'
+
+** Newly added directories also watched (github#1228)
+
+** Send correct ':language-id' for JavaScript server (bug#67150)
+
+** New servers have been added to 'eglot-server-programs'.
+
+- nls (bug#63603)
+- nixd (bug#64214)
+- lexical (bug#65359)
+- terraform-ls (bug#65671)
+- ruff-lsp (bug#67441)
+- uiua (bug#67850)
 
 
 * Changes in Eglot 1.15 (29/4/2023)
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index 7b39af03a88..1e88500d169 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -1,6 +1,6 @@
 ERC NEWS
 
-Copyright (C) 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 2006-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send ERC bug reports to 'bug-gnu-emacs@gnu.org',
@@ -131,13 +131,6 @@ connectivity before attempting to reconnect in earnest.  
See option
 'erc-server-reconnect-function' and new local module 'services-regain'
 (also experimental) to get started.
 
-** Module 'fill' can add a bit of space between messages.
-On graphical displays, it's now possible to add some breathing room
-around certain messages via the new option 'erc-fill-line-spacing'.
-This is especially handy when using the option 'erc-fill-wrap-merge'
-to omit repeated speaker tags, which can make message boundaries less
-detectable by tired eyes.
-
 ** Modules rather than their libraries set major-mode keybindings.
 To put it another way, simply loading a built-in module's library no
 longer modifies 'erc-mode-map'.  Instead, modifications occur during
@@ -170,6 +163,19 @@ options, like 'erc-command-indicator', have moved to the 
'erc-goodies'
 library, although their Custom groups remain the same.  Add
 'command-indicator' to 'erc-modules' to get started.
 
+** Option 'erc-track-faces-normal-list' slightly more influential.
+This option has always been a source of confusion for users, mainly
+because its influence rode heavily on the makeup of faces in a given
+message.  Historically, when a buffer's current mode-line face was a
+member of this option's value, ERC would only swap it out for a fellow
+"normal" if it was absent from the message being processed.  Beginning
+with this release, ERC now looks to other ranked and, if necessary,
+unranked "normals" instead of sustaining the same face between
+messages.  This was done to better honor the stated purpose of the
+option, which is to provide consistent visual feedback when buffer
+activity occurs.  If you experience problems with this development,
+see the compatibility flag 'erc-track-ignore-normal-contenders-p'.
+
 ** 'erc-button-alist' and 'erc-nick-popup-alist' have evolved slightly.
 It's no secret that the 'buttons' module treats potential nicknames
 specially.  This is perhaps most evident in its treatment of the
@@ -184,6 +190,23 @@ s-expressions, which ERC will continue to honor.  Although 
the default
 lineup remains functionally equivalent, its members have all been
 updated accordingly.
 
+** 'erc-track-faces-priority-list' and 'erc-track-faces-normal-list' slimmed.
+These options have been purged of certain 'button'-related face
+combinations.  Originally added in ERC 5.3, these combinations
+described the effect of "buttonizing" atop faces added by the 'match'
+module, like '(erc-nick-default-face erc-pal-face)'.  However, since
+at least Emacs 27, 'match' has run before 'button' in
+'erc-insert-modify-hook', meaning such permutations aren't possible.
+
+More importantly, users who've customized either of these options
+should update them with the new default value of the option
+'erc-button-nickname-face'.  Like 'erc-nick-default-face', which it
+replaces, the new 'erc-button-nick-default-face' is also a "real"
+face.  Its sole reason for existing is to make it easier for users and
+modules to distinguish between basic buttonized faces and
+'erc-nick-default-face', which is now reserved to mean the base
+"speaker" face.
+
 ** Option 'erc-query-on-unjoined-chan-privmsg' restored and renamed.
 This option was accidentally removed from the default client in ERC
 5.5 and was thus prevented from influencing PRIVMSG routing.  It's now
@@ -214,7 +237,17 @@ Users of the default theme may notice that 
'erc-action-face' and
 'erc-notice-face' now appear slightly less bold on systems supporting
 a weight of 'semi-bold'.  This was done to make buttons detectable and
 to spare users from resorting to tweaking these faces, or options like
-'erc-notice-highlight-type', just to achieve this effect.
+'erc-notice-highlight-type', just to achieve this effect.  It's
+currently most prominent in "/ME" messages, where 'erc-action-face'
+sits beneath 'erc-input-face', as well as 'erc-my-nick-face' in the
+speaker portion.
+
+** Fewer nick buttons in QUIT, JOIN, and PART messages.
+Common messages that show a nickname followed by a "userhost" often
+end up with redundant buttons because the nick reappears in or is the
+same as the "~user" portion.  ERC now tamps down on this to make
+<TAB>ing around more convenient.  To opt out, see the new variable
+'erc-button-highlight-nick-once'.
 
 ** Improved interplay between buffer truncation and message logging.
 While most of these improvements are subtle, some affect everyday use.
@@ -272,6 +305,35 @@ buffers.  In channels, it's grown to include all letters 
and their
 possibly truncated arguments, with the exception of stateful list
 modes, like "b".
 
+** In-buffer "status messages" are now a thing.
+The ancient option 'erc-ensure-target-buffer-on-privmsg' has been
+repurposed slightly to express a third state denoted by the symbol
+'status'.  It tells ERC to revert to the old default behavior in which
+separate, "pseudo" target buffers for status-prefixed conversing
+co-existed alongside actual target buffers.  Instead of this awkward
+arrangement, ERC now acts like other clients by default and inserts
+so-called "status messages" in situ, right between other messages.
+Similar insertion-routing behavior now also applies to CTCP ACTIONs
+directed at status-prefixed channels.  Unfortunately, outgoing "/msg
+@#chan hi" messages aren't yet shown in the same fashion, but the
+groundwork has been laid, making such an addition almost trivial.
+
+** An easier way to see channel-membership prefixes on speakers.
+The option 'erc-format-@nick' has been deprecated in favor of the new
+boolean option 'erc-show-speaker-membership-status', a simple switch
+to enable the displaying of status prefixes on the speaker nicks of
+incoming chat messages.  Prefixes on your speaker nick for outgoing
+chat messages continue to always be present.
+
+** Updating user options requires cycling associated minor modes.
+During a live ERC session, you may need to disable and re-enable a
+module's minor mode via 'M-x erc-foo-mode RET' or similar before an
+option's updated value takes effect.  This primarily impacts new
+options introduced by this release and existing ones whose behavior
+has changed in some way.  At present, ERC does not perform this step
+automatically on your behalf, even if a change was made in a
+'Custom-mode' buffer or via 'setopt'.
+
 ** Miscellaneous UX changes.
 Some minor quality-of-life niceties have finally made their way to
 ERC.  For example, fool visibility has become togglable with the new
@@ -306,6 +368,15 @@ from 't' to the more useful 'erc-prompt', although the 
property of the
 same name has been retained and now has a value of 'hidden' when
 disconnected.
 
+*** Lists of faces in buttonized text are no longer nested.
+Previously, when "buttonizing" a new region, ERC would combine faces
+by blindly consing the new onto the existing.  In theory, this kept a
+nice record of all modifications to a given region.  However, it also
+complicated life for other modules wanting to analyze and operate on
+these regions.  Beginning with this release, ERC now merges combined
+faces together when creating buttons, although the odd nested list may
+still crop up here and there.
+
 *** Members of insert- and send-related hooks have been reordered.
 As anyone reading this is no doubt aware, both built-in and
 third-party modules rely on certain hooks for adjusting incoming and
@@ -325,8 +396,10 @@ when present, at depths beginning at 20 and ending below 
80.  Of most
 interest to module authors is the new relative positioning of the
 first three, which have been rotated leftward with respect to their
 previous places in recent ERC versions (fill, button, match ,stamp).
+A similar designated range from -80 to -20 also exists and is home to
+the function 'erc-controls-highlight'.
 
-ERC also provisionally reserves the same depth interval for
+ERC also provisionally reserves the same depth intervals for
 'erc-insert-pre-hook' and possibly other, similar hooks, but will
 continue to modify non-ERC hooks locally whenever possible, especially
 in new code.
@@ -362,9 +435,12 @@ contains unique closures and thus no longer proves 
effective for
 traversing inserted messages.  For now, ERC only provides an internal
 means of visiting messages, but a public interface is forthcoming.
 Also affecting the 'stamp' module is the deprecation of the function
-'erc-insert-aligned' and its removal from client code.  Additionally,
-the module now merges its 'invisible' property with existing ones and
-includes all white space around stamps when doing so.
+'erc-insert-aligned' and its removal from the default client's code.
+In the same library, the function 'erc-munge-invisibility-spec' has
+been renamed to 'erc-stamp--manage-local-options-state' to better
+reflect its purpose.  Additionally, the module now merges its
+'invisible' property with existing ones and includes all white space
+around stamps when doing so.
 
 This "propertizing" of surrounding white space extends to all
 'stamp'-applied properties, like 'field', in all intervening space
@@ -376,6 +452,17 @@ those folded onto the next line.  Such inconsistency made 
stamp
 detection overly complex and produced uneven results when toggling
 stamp visibility.
 
+*** Invisible message insertions not automatically made 'intangible'.
+Previously, when 'erc-display-message' and friends spotted the
+'invisible' text property with a value of t anywhere in text to be
+inserted, it would apply that property to the entire message, along
+with a t-valued 'intangible' property.  Beginning with ERC 5.6, users
+expecting this behavior will have to instead perform the treatment
+themselves.  To help with the transition, a temporary escape hatch has
+been made available to regain this behavior, but its existence is only
+guaranteed for this one minor version alone.  See source code in the
+vicinity of 'erc-insert-line' for more.
+
 *** Date stamps have become independent messages.
 ERC now inserts "date stamps" generated from the option
 'erc-timestamp-format-left' as separate, standalone messages.  This
@@ -401,7 +488,9 @@ also not appreciate that 'erc-timestamp-last-inserted-left' 
no longer
 records the final trailing newline in 'erc-timestamp-format-left'.  If
 these inconveniences prove too encumbering to deal with right away,
 see the escape hatch 'erc-stamp-prepend-date-stamps-p', which should
-help ease the transition.
+help ease the transition.  As for detecting these new stamp-only
+messages from members of 'erc-insert-modify-hook' and friends, see the
+function 'erc-stamp-inserting-date-stamp-p'.
 
 *** The role of a module's Custom group is now more clearly defined.
 Associating built-in modules with Custom groups and "provided" library
@@ -425,11 +514,44 @@ Built-in modules can now provide more detailed help for a 
particular
 subcommand by telling ERC to defer to a specialized handler.  This
 facility can be opened up to third parties should any one request it.
 
+*** Message-formatting templates in 'notify' renamed.
+All templates beginning with the prefix "erc-message-english-notify_"
+have been renamed to begin with "erc-message-english-notify-".  For
+example, the variable 'erc-message-english-notify_current' is now
+'erc-message-english-notify_current'.  The old names have been
+preserved as obsolete aliases.
+
 *** Longtime quasi modules made proper.
 The 'fill' module is now defined by 'define-erc-module'.  The same
 goes for ERC's imenu integration, which has 'imenu' now appearing in
 the default value of 'erc-modules'.
 
+*** Function 'erc-get-user-mode-prefix' renamed.
+This utility has been renamed to 'erc-get-channel-membership-prefix'
+to better reflect its role of delivering a formatted "status prefix",
+like "+" (for "voice"), and to avoid confusion with user modes, like
+"+i" (for "invisible").  Additionally, its lone parameter is now
+overloaded to accept an 'erc-channel-user' object as well as a string.
+
+*** Channel-membership table 'erc-channel-users' renamed.
+Distinguishing between 'erc-channel-user' objects and values of the
+'erc-channel-users' (plural) hash-table has been a constant source of
+confusion, even within ERC's own code base.  The hash-table's values
+are cons cells whose CDR slot is an 'erc-channel-user'.  To help keep
+things sane, 'erc-channel-users' (plural) is now officially being
+redubbed 'erc-channel-members'.  Similarly, the utility function
+'erc-get-channel-user' has been renamed to 'erc-get-channel-member'.
+Expect deprecations of the old names to follow in a future release.
+
+*** The 'erc-channel-user' struct has a changed internally.
+The five boolean slots for membership prefixes have been folded
+("encoded") into a single integer slot.  However, the old 'setf'-able
+accessors remain available, and the constructor's signature remains
+unchanged.  Since third-party code must be recompiled when upgrading
+ERC anyway, users shouldn't experience any churn.  The only caveat is
+that third-party code using the literal read-syntax of these objects,
+for example, in unit tests, will have to be updated.
+
 *** Hidden messages contain a preceding rather than trailing newline.
 ERC has traditionally only offered to hide messages involving fools,
 but plans are to make hiding more powerful.  Anyone depending on the
@@ -452,13 +574,27 @@ third-party code, the key takeaway is that more 
'font-lock-face'
 properties encountered in the wild may be combinations of faces rather
 than lone ones.
 
+*** 'erc-flood-protect' no longer influences input splitting.
+This variable's role has been narrowed to rate limiting only.  ERC
+used to suppress protocol line-splitting when its value was nil, but
+that's now handled by setting 'erc-split-line-length' to zero.
+
 *** 'erc-pre-send-functions' visits prompt input post-split.
 ERC now adjusts input lines to fall within allowed length limits
 before showing hook members the result.  For compatibility,
 third-party code can request that the final input be adjusted again
 prior to being sent.  To facilitate this, the 'erc-input' object
-shared among hook members has gained a new 'refoldp' slot, making this
-a breaking change, if only in theory.  See doc string for details.
+shared among hook members has gained a 'refoldp' slot.  See doc string
+for details.
+
+*** More flexibility in sending and displaying prompt input.
+The abnormal hook 'erc-pre-send-functions' previously married outgoing
+message text to its inserted representation in an ERC target buffer.
+Going forward, users can populate the new slot 'substxt' with
+alternate text to insert in place of the 'string' slot's contents,
+which ERC still sends to the server.  This dichotomy lets users
+completely avoid the often fiddly 'erc-send-modify-hook' and friends
+for use cases like language translation and subprotocol encoding.
 
 *** ERC's prompt survives the insertion of user input and messages.
 Previously, ERC's prompt and its input marker disappeared while
@@ -510,6 +646,43 @@ handling specific "MODE" types and letters in coming 
releases.  If
 you'd like a say in shaping how this transpires, please share your
 ideas and use cases on the tracker.
 
+*** A better way to define message-formatting templates.
+The functions 'erc-define-catalog-entry' and 'erc-define-catalog' have
+been deprecated in favor of 'erc-define-message-format-catalog', a new
+macro for defining template "catalogs" at the top level of libraries.
+
+*** Interface for determining display names renamed.
+The option 'erc-format-nick-function' has been renamed to
+'erc-speaker-from-channel-member-function' to better reflect its
+actual role.  So too has the related function 'erc-format-nick', which
+is now 'erc-determine-speaker-from user'.
+
+*** A template-based approach to formatting inserted chat messages.
+Predicting and influencing how ERC formats messages containing a
+leading "<speaker>" has never been straightforward.  The characters
+bracketing the speaker and the faces used for each component have
+always been hard-coded, with 'erc-format-query-as-channel-p' being the
+only knob of any consequence.  With this release, ERC begins its
+transition to a unified formatting paradigm that builds upon the
+already familiar "language catalog" templating system.  Using a
+separate "speaker catalog" keyed by contextual symbols, like
+'query-privmsg', ERC (and eventually everyone) will more easily be
+able to influence how inserted messages take shape in buffers.
+
+*** New format templates for inserted CTCP ACTION messages.
+In 5.5 and earlier, ERC displayed outgoing CTCP ACTION messages in
+'erc-input-face' alone (before buttonizing).  Incoming ACTION messages
+mirrored this, except with 'erc-action-face' throughout.  Going
+forward, inserted outgoing "/ME" messages will also incorporate
+'erc-action-face', only underneath 'erc-input-face', with
+'erc-my-nick-face' sitting atop both in the leading "speaker" nickname
+portion (again, pre-buttonizing).  This new behavior sidesteps the
+traditional format template 'erc-message-english-ACTION' from the
+default "language catalog" in favor of an entry from the new internal
+"speaker catalog".  Users needing to access the old behavior can do so
+by toggling a provided compatibility switch.  See source code around
+the function 'erc-send-action' for details.
+
 *** Miscellaneous changes
 Two helper macros from GNU ELPA's Compat library are now available to
 third-party modules as 'erc-compat-call' and 'erc-compat-function'.
@@ -1706,7 +1879,7 @@ Only the macros in cl-macs.el are used.
 
 ** Make flood protection toggle-able as on/off, removing the 'strict option.
 
-** If possible, re-use channel buffers when reconnecting to a server.
+** If possible, reuse channel buffers when reconnecting to a server.
 
 ** Text in ERC buffers is now read-only by default.
 To get the previous behavior,
diff --git a/etc/ETAGS.EBNF b/etc/ETAGS.EBNF
index f2aa45de43f..2d67de68928 100644
--- a/etc/ETAGS.EBNF
+++ b/etc/ETAGS.EBNF
@@ -94,7 +94,7 @@ those.
 
 ===================== end of discussion of tag names =====================
 
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 COPYING PERMISSIONS:
 
diff --git a/etc/ETAGS.README b/etc/ETAGS.README
index 8308da52171..3264dae01cc 100644
--- a/etc/ETAGS.README
+++ b/etc/ETAGS.README
@@ -28,7 +28,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
LIABILITY, OR TORT
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2023 Free Software
+Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2024 Free Software
 Foundation, Inc.
 
 This file is not considered part of GNU Emacs.
diff --git a/etc/HELLO b/etc/HELLO
index a589e69bf03..84868b6d75e 100644
--- a/etc/HELLO
+++ b/etc/HELLO
@@ -131,7 +131,7 @@ Wancho (𞋒𞋀𞋉𞋃𞋕)      𞋂𞋈𞋛
 
 
 
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 
 This file is part of GNU Emacs.
diff --git a/etc/HISTORY b/etc/HISTORY
index f6df3e6fe60..afa14cb2350 100644
--- a/etc/HISTORY
+++ b/etc/HISTORY
@@ -233,6 +233,8 @@ Was not actually released.
 
 GNU Emacs 29.1 (2023-07-30) emacs-29.1
 
+GNU Emacs 29.2 (2024-01-18) emacs-29.2
+
 
 ----------------------------------------------------------------------
 This file is part of GNU Emacs.
diff --git a/etc/MACHINES b/etc/MACHINES
index c9f6ec265d8..3e0628a64d0 100644
--- a/etc/MACHINES
+++ b/etc/MACHINES
@@ -1,6 +1,6 @@
 Emacs machines list
 
-Copyright (C) 1989-1990, 1992-1993, 1998, 2001-2023 Free Software
+Copyright (C) 1989-1990, 1992-1993, 1998, 2001-2024 Free Software
 Foundation, Inc.
 See the end of the file for license conditions.
 
diff --git a/etc/MH-E-NEWS b/etc/MH-E-NEWS
index b2b05c3d024..2ec2faebc98 100644
--- a/etc/MH-E-NEWS
+++ b/etc/MH-E-NEWS
@@ -1,6 +1,6 @@
 * COPYRIGHT
 
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 * Changes in MH-E 8.6
diff --git a/etc/NEWS b/etc/NEWS
index 29f4e5c0b66..816613de4ec 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.
 
-Copyright (C) 2022-2023 Free Software Foundation, Inc.
+Copyright (C) 2022-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
@@ -15,12 +15,6 @@ in older Emacs versions.
 You can narrow news to a specific version by calling 'view-emacs-news'
 with a prefix argument or by typing 'C-u C-h C-n'.
 
-Temporary note:
-+++ indicates that all relevant manuals in doc/ have been updated.
---- means no change in the manuals is needed.
-When you add a new item, use the appropriate mark if you are sure it
-applies, and please also update docstrings as needed.
-
 
 * Installation Changes in Emacs 30.1
 
@@ -37,7 +31,7 @@ See the file 'java/INSTALL' for more details.
 libgccjit is present and functional on the system.  To disable native
 compilation, configure Emacs with the option:
 
-  $ ./configure --with-native-compilation=no
+    ./configure --with-native-compilation=no
 
 ---
 ** Emacs now defaults to ossaudio library for sound on NetBSD and OpenBSD.
@@ -66,8 +60,48 @@ URI scheme.  See the Org mode manual, Info node "(org) 
Protocols" for
 more details.
 
 
+* Incompatible Changes in Emacs 30.1
+
++++
+** URL now never sends user email addresses in HTTP requests.
+Emacs never sent email addresses by default, but it used to be
+possible to customize 'url-privacy-level' so that the users email
+address was sent along in HTTP requests.  This feature has now been
+removed, as it was considered more dangerous than useful.  RFC 9110
+(§ 10.1.2) also recommends against it.  The user option
+'url-personal-mail-address' is now also obsolete.
+
+To send an email address in the header of individual HTTP requests,
+see the variable 'url-request-extra-headers'.
+
++++
+** 'completion-auto-help' now affects 'icomplete-in-buffer'.
+Previously, completion-auto-help mostly affected only minibuffer
+completion.  Now, if 'completion-auto-help' has the value 'lazy', then
+Icomplete's in-buffer display of possible completions will only appear
+after the 'completion-at-point' command has been invoked twice, and if
+'completion-auto-help' is nil, then Icomplete's in-buffer display is
+completely suppressed.  Thus, if you use 'icomplete-in-buffer', ensure
+'completion-auto-help' is not customized to 'lazy' or nil.
+
++++
+** The *Completions* buffer now always accompanies 'icomplete-in-buffer'.
+Previously, it was not consistent when the *Completions* buffer would
+appear when using 'icomplete-in-buffer'.  Now the *Completions* buffer
+and Icomplete's in-buffer display of possible completions always
+appear together.  If you would prefer to see only Icomplete's
+in-buffer display, and not the *Completions* buffer, you can add this
+to your init:
+
+    (advice-add 'completion-at-point :after #'minibuffer-hide-completions)
+
+
 * Changes in Emacs 30.1
 
+** 'advice-remove' is now an interactive command.
+When called interactively, 'advice-remove' now prompts for an advised
+function to the advice to remove.
+
 ** Emacs now supports Unicode Standard version 15.1.
 
 ** Network Security Manager
@@ -222,6 +256,12 @@ Anything following the symbol 
'mode-line-format-right-align' in
 right-aligned to is controlled by the new user option
 'mode-line-right-align-edge'.
 
+** Windows
+
+*** New action alist entry 'post-command-select-window' for display-buffer.
+It specifies whether the window of the displayed buffer should be
+selected or deselected at the end of executing the current command.
+
 ** Tab Bars and Tab Lines
 
 *** New user option 'tab-bar-tab-name-format-functions'.
@@ -242,7 +282,7 @@ It can be used to customize the look of the appointment 
notification
 displayed on the mode line when 'appt-display-mode-line' is non-nil.
 
 ---
-*** Emacs now recognizes shebang lines that pass -S/--split-string to 'env'.
+*** Emacs now recognizes shebang lines that pass '-S'/'--split-string' to 
'env'.
 When visiting a script that invokes 'env -S INTERPRETER ARGS...' in
 its shebang line, Emacs will now skip over 'env -S' and deduce the
 major mode based on the interpreter after 'env -S'.
@@ -258,9 +298,33 @@ called in the '--eval' expression, which is useful when 
those
 arguments contain arbitrary characters that otherwise might require
 elaborate and error-prone escaping (to protect them from the shell).
 
++++
+** 'recover-file' can show diffs between auto save file and current file.
+When answering the prompt with "diff" or "=", it now shows the diffs
+between the auto save file and the current file.
+
+---
+** 'ffap-lax-url' now defaults to nil.
+Previously, it was set to 'ffap-lax-url' to t but this broke remote file
+name detection.
+
 
 * Editing Changes in Emacs 30.1
 
++++
+** New minor mode 'visual-wrap-prefix-mode'.
+When enabled, continuation lines displayed for a wrapped long line
+will receive a 'wrap-prefix' automatically computed from the line's
+surrounding context, such that continuation lines are indented on
+display as if they were filled with 'M-q' or similar.  Unlike 'M-q',
+the indentation only happens on display, and doesn't change the buffer
+text in any way.  The global minor mode
+'global-visual-wrap-prefix-mode' enables this minor mode in all
+buffers.
+
+(This minor mode is the 'adaptive-wrap' ELPA package renamed and
+lightly edited for inclusion in Emacs.)
+
 +++
 ** New user option 'gud-highlight-current-line'.
 When enabled, Gud will visually emphasize the line being executed upon
@@ -346,9 +410,9 @@ functions in CJK locales.
 
 ---
 *** New input methods for the Urdu, Pashto, and Sindhi languages.
-These languages are spoken in Pakistan and Afganistan.
+These languages are spoken in Pakistan and Afghanistan.
 
-*** Additional 'C-x 8' key translations for æ and Æ.
+*** Additional 'C-x 8' key translations for "æ" and "Æ".
 These characters can now be input with 'C-x 8 a e' and 'C-x 8 A E',
 respectively, in addition to the existing translations 'C-x 8 / e' and
 'C-x 8 / E'.
@@ -356,14 +420,36 @@ respectively, in addition to the existing translations 
'C-x 8 / e' and
 
 * Changes in Specialized Modes and Packages in Emacs 30.1
 
+---
+** Trace
+In batch mode, tracing now sends the trace to stdout.
+
 +++
-** New command 'lldb'.
-Run the LLDB debugger, analogous to the 'gud-gdb' command.  Note that
-you might want to add these settings to your ".lldbinit" file, to reduce
-the output in the LLDB output when stepping through source files.
+** Mwheel
+The 'wheel-up/down/left/right' events are now bound unconditionally,
+and the 'mouse-wheel-up/down/left/right-event' variables are thus used
+only to specify the 'mouse-4/5/6/7' events generated by older
+configurations such as X11 when the X server does not support at least
+version 2.1 of the X Input Extension, and 'xterm-mouse-mode'.
+
+** 'xterm-mouse-mode'
+This mode now emits `wheel-up/down/right/left' events instead of
+'mouse-4/5/6/7' events for the mouse wheel.
+It uses the 'mouse-wheel-up/down/left/right-event'
+variables to decide which button maps to which wheel event (if any).
+
+** Info
 
-    settings set stop-line-count-before 0
-    settings set stop-line-count-after 0
+---
+*** New user option 'Info-url-alist'.
+This user option associates manual-names with URLs.  It affects the
+'Info-goto-node-web' command.  By default, associations for all
+Emacs-included manuals are set.  Further associations can be added for
+arbitrary Info manuals.
+
++++
+** New command 'lldb'.
+Run the LLDB debugger, analogous to the 'gud-gdb' command.
 
 ** gdb-mi
 
@@ -407,6 +493,11 @@ This is because it partly acts by modifying other rules 
which may
 occasionally be surprising.  It can be re-enabled by adding 'omake' to
 'compilation-error-regexp-alist'.
 
+*** Lua errors and stack traces are now recognized.
+Compilation mode now recognizes Lua language errors and stack traces.
+Every Lua error is recognized as a compilation error, and every Lua
+stack frame is recognized as a compilation info.
+
 ** Project
 
 +++
@@ -425,7 +516,7 @@ The look of the key prompt in the project switcher has been 
changed
 slightly.  To get the previous one, set this option to 'brackets'.
 
 *** 'project-try-vc' tries harder to find the responsible VCS.
-When 'project-vc-extra-root-markers' is non-nil, and causes
+When 'project-vc-extra-root-markers' is non-nil, and causes a
 subdirectory project to be detected which is not a VCS root, we now
 additionally traverse the parent directories until a VCS root is found
 (if any), so that the ignore rules for that repository are used, and
@@ -439,10 +530,15 @@ have access to all keys defined inside 
'project-prefix-map', as well
 as global bindings (to run other commands inside the project root),
 you can add this to your init script:
 
-  (setopt project-switch-commands #'project-prefix-or-any-command)
+    (setopt project-switch-commands #'project-prefix-or-any-command)
 
 ** VC
 
+---
+*** Log-Edit buffers now display a tool bar.
+This tool bar contains items for committing log entries and editing or
+generating log entries, among other editing operations.
+
 ---
 *** New user option 'vc-git-shortlog-switches'.
 This is a string or a list of strings that specifies the Git log
@@ -457,6 +553,25 @@ With this value only the revision number is displayed on 
the mode-line.
 *** Obsolete command 'vc-switch-backend' re-added as 'vc-change-backend'.
 The command was previously obsoleted and unbound in Emacs 28.
 
+*** Support for viewing VC change history across renames.
+When a fileset's VC change history ('C-x v l') ends at a rename, we
+now print the old name(s) and a button which jumps to their history.
+Git and Hg are supported.  Naturally, 'vc-git-print-log-follow' should
+be nil for this to work (or '--follow' should not be in
+'vc-hg-print-log-switches', in Hg's case).  Unlike when the '--follow'
+switch is used, commands to see the diff of the old revision ('d'),
+check out an old file version ('f') or annotate it right away ('a'),
+also work on revisions which precede renames.
+
+---
+*** 'vc-annotate' now abbreviates the Git revision in the buffer name.
+When using the Git backend, 'vc-annotate' will use an abbreviated
+revision identifier in its buffer name.  To restore the previous
+behavior, set 'vc-annotate-use-short-revision' to nil.
+
+*** New option 'vc-git-file-name-changes-switches'.
+It allows tweaking the thresholds for rename and copy detection.
+
 ** Diff mode
 
 +++
@@ -498,7 +613,7 @@ the last line will move to the first line).  The default is 
nil.
 
 *** New user option 'dired-filename-display-length'.
 It is an integer representing the maximum display length of filenames.
-The middle part of filename whose length exceeds the restriction is
+The middle part of a filename whose length exceeds the restriction is
 hidden and an ellipsis is displayed instead.  A value of 'window'
 means using the right edge of window as the display restriction.  The
 default is nil.
@@ -511,6 +626,31 @@ based on marked files in Dired.  Possible backends are
 and a universal command such as "open" or "start"
 that delegates to the OS.
 
+*** New command 'dired-do-open'.
+This command is bound to "Open" in the context menu; it "opens" the
+marked or clicked on files according to the OS conventions.  For
+example, on systems supporting XDG, this runs 'xdg-open' on the
+files.
+
++++
+*** 'dired-listing-switches' handles connection-local values if exist.
+This allows to customize different switches for different remote machines.
+
+** Registers
+
++++
+*** New mode of prompting for register names and showing preview.
+The new user option 'register-use-preview' can be customized to the
+value t or insist to request a different user interface of prompting for
+register names and previewing the registers: Emacs will require
+confirmation for overwriting the value of a register, and will show
+the preview of registers without delay.  You can also customize this
+new option to disable the preview completely.
+
+The default value of 'register-use-preview' preserves the behavior of
+Emacs 29 and before.  See the Info node "(emacs) Registers" for more
+details about the new UI and its variants.
+
 ** Ediff
 
 ---
@@ -539,13 +679,29 @@ appropriate, but still allow piping the output elsewhere 
if desired.
 For more information, see the "(eshell) Built-ins" node in the Eshell
 manual.
 
++++
+*** Eshell's 'env' command now supports running commands.
+Like in many other shells, Eshell's 'env' command now lets you run a
+command passed as arguments to 'env'.  If you pass any initial
+arguments of the form 'VAR=VALUE', 'env' will first set 'VAR' to
+'VALUE' before running the command.
+
+---
+*** Eshell's 'umask' command now supports setting the mask symbolically.
+Now, you can pass an argument like "u+w,o-r" to Eshell's 'umask'
+command, which will give write permission for owners of newly-created
+files and deny read permission for users who are not members of the
+file's group.  See the Info node '(coreutils)File permissions' for
+more information on this notation.
+
 +++
 *** New special reference type '#<marker POSITION BUFFER>'.
 This special reference type returns a marker at 'POSITION' in
 'BUFFER'.  You can insert it by typing or using the new interactive
-command 'eshell-insert-marker'.  You can also insert markers of any
-type with the new command 'eshell-insert-special-reference'.  See the
-"(eshell) Arguments" node in the Eshell manual for more details.
+command 'eshell-insert-marker'.  You can also insert special
+references of any type using the new interactive command
+'eshell-insert-special-reference'.  See the "(eshell) Arguments" node
+in the Eshell manual for more details.
 
 +++
 *** New splice operator for Eshell dollar expansions.
@@ -613,34 +769,55 @@ calling external rgrep.
 +++
 *** If a command exits abnormally, the Eshell prompt now shows its exit code.
 
++++
+*** New user option 'eshell-history-append'.
+If non-nil, each Eshell session will save history by appending new
+entries of that session to the history file rather than overwriting
+the file with the whole history of the session.  The default is nil.
+
 ** Minibuffer and Completions
 
 *** New commands 'previous-line-completion' and 'next-line-completion'.
-Bound to '<UP>' and '<DOWN>' arrow keys, respectively, they navigate
+Bound to '<up>' and '<down>' arrow keys, respectively, they navigate
 the "*Completions*" buffer vertically by lines, wrapping at the
 top/bottom when 'completion-auto-wrap' is non-nil.
 
 *** New user option 'minibuffer-visible-completions'.
-When customized to non-nil, you can use arrow key in the minibuffer
-to navigate the completions displayed in the *Completions* window.
+When customized to non-nil, you can use arrow keys in the minibuffer
+to navigate the completions displayed in the "*Completions*" window.
 Typing 'RET' selects the highlighted candidate.  'C-g' hides the
 completions window.  When the completions window is not visible,
 then all these keys have their usual meaning in the minibuffer.
 This option is supported for in-buffer completion as well.
 
 *** Selected completion candidates are deselected on typing.
-When a user types, point in the *Completions* window will be moved off
-any completion candidates.  'minibuffer-choose-completion' ('M-RET')
-will still choose a previously-selected completion candidate, but the
-new command 'minibuffer-choose-completion-or-exit' (bound by
-'minibuffer-visible-completions') will exit with the minibuffer
-contents instead.  The deselection behavior can be controlled with the
-new user option 'completion-auto-deselect'.
-
-*** New value 'historical' for user option 'completions-sort'
+When you type at the minibuffer prompt, the current completion
+candidate will be un-highlighted, and point in the "*Completions*" window
+will be moved off that candidate.  'minibuffer-choose-completion'
+('M-RET') will still choose a previously-selected completion
+candidate, but the new command 'minibuffer-choose-completion-or-exit'
+(bound to 'RET' by 'minibuffer-visible-completions') will exit with
+the minibuffer contents instead.  This deselection behavior can be
+controlled with the new user option 'completion-auto-deselect', which
+is t by default.
+
+*** New value 'historical' for user option 'completions-sort'.
 When 'completions-sort' is set to 'historical', completion candidates
-will be sorted by their chronological order in the minibuffer history,
-with more recent candidates appearing first.
+will be first sorted alphabetically, and then re-sorted by their order
+in the minibuffer history, with more recent candidates appearing first.
+
++++
+*** 'completion-category-overrides' supports more metadata.
+The new supported completion properties are 'cycle-sort-function',
+'display-sort-function', 'annotation-function', 'affixation-function',
+'group-function'.  You can now customize them for any category in
+'completion-category-overrides' that will override the properties
+defined in completion metadata.
+
++++
+*** 'completion-extra-properties' supports more metadata.
+The new supported completion properties are 'category',
+'group-function', 'display-sort-function', 'cycle-sort-function'.
 
 ** Pcomplete
 
@@ -654,7 +831,7 @@ suppress remote file name completion at all.
 *** Completion for the 'doas' command has been added.
 Command completion for 'doas' in Eshell and Shell mode will now work.
 
-** Shell Mode
+** Shell mode
 
 +++
 *** New user option 'shell-get-old-input-include-continuation-lines'.
@@ -743,6 +920,11 @@ buffer must either visit a file, or it must run 
'dired-mode'.  Another
 method but "sudo" can be configured with user option
 'tramp-file-name-with-method'.
 
+---
+*** Direct asynchronous processes use 'tramp-remote-path'.
+When a direct asynchronous process is invoked, it uses 'tramp-remote-path'
+for setting the remote PATH environment variable.
+
 ** File Notifications
 
 +++
@@ -870,13 +1052,18 @@ distracting and easily confused with actual code, or a 
significant
 early aid that relieves you from moving the buffer or reaching for the
 mouse to consult an error message.
 
-** JS Mode
+** JS mode.
 The binding 'M-.' has been removed from the major mode keymaps in
 'js-mode' and 'js-ts-mode', having it default to the global binding
 which calls 'xref-find-definitions'.  If the previous one worked
 better for you, use 'define-key' in your init script to bind
 'js-find-symbol' to that combination again.
 
+** Json mode
+`js-json-mode` does not derive from `js-mode` any more so as not
+to confuse tools like Eglot or YASnippet into thinking that those
+buffers contain Javascript code.
+
 ** Python mode
 
 ---
@@ -983,6 +1170,11 @@ Previously, the '@' character, which normally has 
'symbol' syntax,
 would combine with a following Lisp symbol and interfere with symbol
 searching.
 
+---
+*** 'emacs-lisp-docstring-fill-column' now defaults to 72.
+It was previously 65.  The new default formats documentation strings to
+fit on fewer lines without negatively impacting readability.
+
 ** CPerl mode
 
 ---
@@ -1001,6 +1193,11 @@ value of 'perl-code' is useful for trailing POD and for 
AutoSplit
 modules, the value 'comment' makes CPerl mode treat trailers as
 comment, like Perl mode does.
 
+*** New command 'cperl-file-style'.
+This command sets the indentation style for the current buffer.  To
+change the default style, either use the option with the same name or
+use the command cperl-set-style.
+
 *** Commands using the Perl info page are obsolete.
 The Perl documentation in info format is no longer distributed with
 Perl or on CPAN since more than 10 years.  Perl documentation can be
@@ -1052,6 +1249,12 @@ This can help avoid some awkward skip conditions.  For 
example
 '(skip-unless (not noninteractive))' can be changed to the easier
 to read '(skip-when noninteractive)'.
 
++++
+*** Syntax highlighting unit testing support.
+An ERT extension ('ert-font-lock') now provides support for face
+assignment unit testing.  For more information, see the "(ert) Syntax
+Highlighting Tests" node in the ERT manual.
+
 ** URL
 
 +++
@@ -1096,12 +1299,26 @@ URIs are now prefixed with "https://"; instead.
 Now, calling '(thing-at-point 'url)' when point is on a bug reference
 will return the URL for that bug.
 
++++
+*** New user option 'rcirc-log-time-format'
+This allows for rcirc logs to use a custom timestamp format, than the
+chat buffers use by default.
+
 ** Customize
 
 +++
 *** New command 'customize-dirlocals'.
 This command pops up a buffer to edit the settings in ".dir-locals.el".
-
+** Calc
++++
+*** Calc parses fractions written using U+2044 FRACTION SLASH
+Fractions of the form 123⁄456 are handled as if written 123:456.  Note
+in particular the difference in behavior from U+2215 DIVISION SLASH
+and U+002F SOLIDUS, which result in division rather than a rational
+fraction.  You may also be interested to know that precomposed
+fraction characters, such as ½ (U+00BD VULGAR FRACTION ONE HALF), are
+also recognized as rational fractions.  They have been since 2004, but
+it looks like it was never mentioned in the NEWS, or even the manual.
 
 * New Modes and Packages in Emacs 30.1
 
@@ -1151,22 +1368,34 @@ the needs of users with red-green or blue-yellow color 
deficiency.
 The Info manual "(modus-themes) Top" describes the details and
 showcases all their customization options.
 
++++
+** New global minor mode 'etags-regen-mode'.
+This minor mode generates the tags table automatically based on the
+current project configuration, and later updates it as you edit the
+files and save the changes.
+
 
 * Incompatible Lisp Changes in Emacs 30.1
 
 ---
-** 'register-preview-delay' is no longer used.
-Register preview is no more delayed.  If you want to disable it use
-'register-use-preview' instead with a boolean value.
+** Old 'derived.el' functions removed.
+The following functions have been deleted because they were only used
+by code compiled with Emacs<21:
+'derived-mode-setup-function-name', 'derived-mode-init-mode-variables',
+'derived-mode-set-keymap', 'derived-mode-set-syntax-table',
+'derived-mode-set-abbrev-table', 'derived-mode-run-hooks',
+'derived-mode-merge-keymaps', 'derived-mode-merge-syntax-tables',
+'derived-mode-merge-abbrev-tables'.
 
 +++
 ** 'M-TAB' now invokes 'completion-at-point' also in Text mode.
-Text mode no longer binds 'M-TAB' to 'ispell-complete-word', and
-instead this mode arranges for 'completion-at-point', globally bound
-to 'M-TAB', to perform word completion as well.  If you want 'M-TAB'
-to invoke 'ispell-complete-word', as it did in previous Emacs
-versions, customize the new option
-'text-mode-meta-tab-ispell-complete-word' to non-nil.
+By default, Text mode no longer binds 'M-TAB' to
+'ispell-complete-word'.  Instead this mode arranges for
+'completion-at-point', globally bound to 'M-TAB', to perform word
+completion as well.  You can have Text mode bind 'M-TAB' to
+'ispell-complete-word' as it did in previous Emacs versions, or
+disable Ispell word completion in Text mode altogether, by customizing
+the new user option 'text-mode-ispell-word-completion'.
 
 ** 'pp' and 'pp-to-string' now always include a terminating newline.
 In the past they included a terminating newline in most cases but not all.
@@ -1199,7 +1428,7 @@ This user option has been obsoleted in Emacs 27, use
 ---
 ** User options 'eshell-NAME-unload-hook' are now obsolete.
 These hooks were named incorrectly, and so they never actually ran
-when unloading the correspending feature.  Instead, you should use
+when unloading the corresponding feature.  Instead, you should use
 hooks named after the feature name, like 'esh-mode-unload-hook'.
 
 +++
@@ -1268,21 +1497,55 @@ values.
 
 * Lisp Changes in Emacs 30.1
 
++++
+** 'define-advice' now sets the new advice's 'name' property to NAME
+Named advice defined with 'define-advice' can now be removed with
+'(advice-remove SYMBOL NAME)' in addition to '(advice-remove SYMBOL
+SYMBOL@NAME)'.
+
++++
+** New function 'require-with-check' to detect new versions shadowing.
+This is like 'require', but it checks whether the argument 'feature'
+is already loaded, in which case it either signals an error or
+forcibly reloads the file that defines the feature.
+
++++
+** New variable 'lisp-eval-depth-reserve'.
+It puts a limit to the amount by which Emacs can temporarily increase
+'max-lisp-eval-depth' when handling signals.
+
++++
+** New special form 'handler-bind'.
+Provides a functionality similar to `condition-case` except it runs the
+handler code without unwinding the stack, such that we can record the
+backtrace and other dynamic state at the point of the error.
+See the Info node "(elisp) Handling Errors".
+
++++
+** New 'pop-up-frames' action alist entry for 'display-buffer'.
+This has the same effect as the variable of the same name and takes
+precedence over the variable when present.
+
 ** New function 'merge-ordered-lists'.
 Mostly used internally to do a kind of topological sort of
 inheritance hierarchies.
 
+** New function 'sort-on'.
+This function implements the Schwartzian transform, and is appropriate
+for sorting lists when the computation of the sort key of a list
+element can be expensive.
+
 ** New API for 'derived-mode-p' and control of the graph of major modes.
 
 *** 'derived-mode-p' now takes the list of modes as a single argument.
-The same holds for `provided-mode-derived-p`.
+The same holds for 'provided-mode-derived-p'.
 The old calling convention where multiple modes are passed as
 separate arguments is deprecated.
 
 *** New functions to access the graph of major modes.
 While 'define-derived-mode' still only supports single inheritance,
 modes can declare additional parents (for tests like 'derived-mode-p')
-with `derived-mode-add-parents`.
+with 'derived-mode-add-parents'.
 Accessing the 'derived-mode-parent' property directly is now
 deprecated in favor of the new functions 'derived-mode-set-parent'
 and 'derived-mode-all-parents'.
@@ -1595,6 +1858,13 @@ The declaration '(important-return-value t)' sets the
 'important-return-value' property which indicates that the function
 return value should probably not be thrown away implicitly.
 
+** Bytecode is now always loaded eagerly.
+Bytecode compiled with older Emacs versions for lazy loading using
+'byte-compile-dynamic' is now loaded all at once.
+As a consequence, 'fetch-bytecode' has no use, does nothing, and is
+now obsolete.  The variable 'byte-compile-dynamic' has no effect any
+more; compilation will always yield bytecode for eager loading.
+
 +++
 ** New functions 'file-user-uid' and 'file-group-gid'.
 These functions are like 'user-uid' and 'group-gid', respectively, but
@@ -1627,9 +1897,50 @@ A 5th argument, optional, has been added to
 'modify-dir-local-variable'.  It can be used to specify which
 dir-locals file to modify.
 
+** Connection local variables
+
++++
+*** New macros 'connection-local-p' and 'connection-local-value'.
+The former macro returns non-nil if a variable has a connection-local
+binding.  The latter macro returns the connection-local value of a
+variable if any, or its current value.
+
+** Hash tables
+
++++
+*** ':rehash-size' and ':rehash-threshold' args no longer have any effect.
+These keyword arguments are now ignored by 'make-hash-table'.  Emacs
+manages the memory for all hash table objects in the same way.
+The functions 'hash-table-rehash-size' and 'hash-table-rehash-threshold'
+remain for compatibility but now always return the old default values.
+
++++
+*** The printed representation has been shrunk and simplified.
+The 'test' parameter is omitted if it is 'eql' (the default), as is
+'data' if empty.  'rehash-size', 'rehash-threshold' and 'size' are
+always omitted, and ignored if present when the object is read back in.
+
++++
+** 'treesit-install-language-grammar' can handle local directory instead of 
URL.
+It is now possible to pass a directory of a local repository as URL
+inside 'treesit-language-source-alist', so that calling
+'treesit-install-language-grammar' would avoid cloning the repository.
+It may be useful, for example, for the purposes of bisecting a
+treesitter grammar.
+
 
 * Changes in Emacs 30.1 on Non-Free Operating Systems
 
+** MS-Windows
+
++++
+*** You can now opt out of following the system's Dark mode.
+By default, Emacs on MS-Windows follows the system's Dark mode for its
+title bars' and scroll bars' appearance.  If the new user option
+'w32-follow-system-dark-mode' is customized to the nil value, Emacs
+will disregard the system's Dark mode and will always use the default
+Light mode.
+
 
 ----------------------------------------------------------------------
 This file is part of GNU Emacs.
diff --git a/etc/NEWS.1-17 b/etc/NEWS.1-17
index 952b5e5c3fb..64626060c94 100644
--- a/etc/NEWS.1-17
+++ b/etc/NEWS.1-17
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.  26-Mar-1986
 
-Copyright (C) 1985-1986, 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-1986, 2006-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/etc/NEWS.18 b/etc/NEWS.18
index a1df6245e09..f94d89eab7e 100644
--- a/etc/NEWS.18
+++ b/etc/NEWS.18
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.  17-Aug-1988
 
-Copyright (C) 1988, 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 1988, 2006-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/etc/NEWS.19 b/etc/NEWS.19
index 18d6d630d5b..fb43e80feac 100644
--- a/etc/NEWS.19
+++ b/etc/NEWS.19
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.  1992.
 
-Copyright (C) 1993-1995, 2001, 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1995, 2001, 2006-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/etc/NEWS.20 b/etc/NEWS.20
index ade83eb3dd0..ad41c873c1d 100644
--- a/etc/NEWS.20
+++ b/etc/NEWS.20
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.  2006-05-31
 
-Copyright (C) 1999-2001, 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 1999-2001, 2006-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/etc/NEWS.21 b/etc/NEWS.21
index 89cac46e248..d7f5ba184a5 100644
--- a/etc/NEWS.21
+++ b/etc/NEWS.21
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.  2006-05-31
 
-Copyright (C) 2000-2023 Free Software Foundation, Inc.
+Copyright (C) 2000-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/etc/NEWS.22 b/etc/NEWS.22
index 7021fce52ed..848b9afda4b 100644
--- a/etc/NEWS.22
+++ b/etc/NEWS.22
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.
 
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send Emacs bug reports to bug-gnu-emacs@gnu.org.
diff --git a/etc/NEWS.23 b/etc/NEWS.23
index 7ac91e6165f..3ba5bdd180c 100644
--- a/etc/NEWS.23
+++ b/etc/NEWS.23
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.
 
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send Emacs bug reports to bug-gnu-emacs@gnu.org.
diff --git a/etc/NEWS.24 b/etc/NEWS.24
index 160674f5918..f2e434352a7 100644
--- a/etc/NEWS.24
+++ b/etc/NEWS.24
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.
 
-Copyright (C) 2010-2023 Free Software Foundation, Inc.
+Copyright (C) 2010-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send Emacs bug reports to bug-gnu-emacs@gnu.org.
diff --git a/etc/NEWS.25 b/etc/NEWS.25
index 3fa604bd92d..3c5e9569b49 100644
--- a/etc/NEWS.25
+++ b/etc/NEWS.25
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.
 
-Copyright (C) 2014-2023 Free Software Foundation, Inc.
+Copyright (C) 2014-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send Emacs bug reports to bug-gnu-emacs@gnu.org.
diff --git a/etc/NEWS.26 b/etc/NEWS.26
index fb13733f45c..b374c8b5ed3 100644
--- a/etc/NEWS.26
+++ b/etc/NEWS.26
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.
 
-Copyright (C) 2016-2023 Free Software Foundation, Inc.
+Copyright (C) 2016-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
diff --git a/etc/NEWS.27 b/etc/NEWS.27
index 3e1b4a49946..080568433c2 100644
--- a/etc/NEWS.27
+++ b/etc/NEWS.27
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.
 
-Copyright (C) 2017-2023 Free Software Foundation, Inc.
+Copyright (C) 2017-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
@@ -28,7 +28,6 @@ If set to a non-nil value which isn't a function, resize the 
mini
 frame using the new function 'fit-mini-frame-to-buffer' which won't
 skip leading or trailing empty lines of the buffer.
 
-+++
 ** Update IRC-related references to point to Libera.Chat.
 In June 2021, the Free Software Foundation and the GNU Project moved
 their official IRC channels from the Freenode network to Libera.Chat
diff --git a/etc/NEWS.28 b/etc/NEWS.28
index 89ef25bb32d..ac65eaa986f 100644
--- a/etc/NEWS.28
+++ b/etc/NEWS.28
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.
 
-Copyright (C) 2019-2023 Free Software Foundation, Inc.
+Copyright (C) 2019-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
diff --git a/etc/NEWS.29 b/etc/NEWS.29
index 333699f1015..06086e9bdfb 100644
--- a/etc/NEWS.29
+++ b/etc/NEWS.29
@@ -1,6 +1,6 @@
 GNU Emacs NEWS -- history of user-visible changes.
 
-Copyright (C) 2021-2023 Free Software Foundation, Inc.
+Copyright (C) 2021-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
@@ -15,11 +15,32 @@ in older Emacs versions.
 You can narrow news to a specific version by calling 'view-emacs-news'
 with a prefix argument or by typing 'C-u C-h C-n'.
 
-Temporary note:
-+++ indicates that all relevant manuals in doc/ have been updated.
---- means no change in the manuals is needed.
-When you add a new item, use the appropriate mark if you are sure it
-applies, and please also update docstrings as needed.
+
+* Installation Changes in Emacs 29.3
+
+
+* Startup Changes in Emacs 29.3
+
+
+* Changes in Emacs 29.3
+
+
+* Editing Changes in Emacs 29.3
+
+
+* Changes in Specialized Modes and Packages in Emacs 29.3
+
+
+* New Modes and Packages in Emacs 29.3
+
+
+* Incompatible Lisp Changes in Emacs 29.3
+
+
+* Lisp Changes in Emacs 29.3
+
+
+* Changes in Emacs 29.3 on Non-Free Operating Systems
 
 
 * Installation Changes in Emacs 29.2
@@ -43,37 +64,25 @@ more details.
 
 * Changes in Emacs 29.2
 
-
-* Editing Changes in Emacs 29.2
+This is a bug-fix release with no new features.
 
 
 * Changes in Specialized Modes and Packages in Emacs 29.2
 
 ** Tramp
 
-+++
 *** New user option 'tramp-show-ad-hoc-proxies'.
 When non-nil, ad-hoc definitions are kept in remote file names instead
 of showing the shortcuts.
 
 
-* New Modes and Packages in Emacs 29.2
-
-
 * Incompatible Lisp Changes in Emacs 29.2
 
-+++
 ** 'with-sqlite-transaction' rolls back changes if its BODY fails.
 If the BODY of the macro signals an error, or committing the results
 of the transaction fails, the changes will now be rolled back.
 
 
-* Lisp Changes in Emacs 29.2
-
-
-* Changes in Emacs 29.2 on Non-Free Operating Systems
-
-
 * Installation Changes in Emacs 29.1
 
 ** Ahead-of-time native compilation can now be requested via configure.
diff --git a/etc/NEXTSTEP b/etc/NEXTSTEP
index 547f146c623..25c14c6af21 100644
--- a/etc/NEXTSTEP
+++ b/etc/NEXTSTEP
@@ -1,4 +1,4 @@
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 This file contains information about GNU Emacs on "Nextstep" platforms.
diff --git a/etc/NXML-NEWS b/etc/NXML-NEWS
index 2bd2cc6e326..2efc4544f1e 100644
--- a/etc/NXML-NEWS
+++ b/etc/NXML-NEWS
@@ -1,4 +1,4 @@
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 5f92c056018..d07ce53ab20 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -6,7 +6,7 @@ ORG NEWS -- history of user-visible changes.   -*- mode: org; 
coding: utf-8 -*-
 #+LINK: msg https://list.orgmode.org/%s/
 #+LINK: git https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=%s
 
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please send Org bug reports to mailto:emacs-orgmode@gnu.org.
@@ -1098,7 +1098,7 @@ Conversion to SVG exposes a number of additional 
customizations that
 give the user full control over the contents of the latex source
 block. ~org-babel-latex-preamble~, ~org-babel-latex-begin-env~ and
 ~org-babel-latex-end-env~ are new customization options added to allow
-the user to specify the preamble and code that preceedes and proceeds
+the user to specify the preamble and code that precedes and proceeds
 the contents of the source block.
 
 *** New option ~org-html-meta-tags~ allows for HTML meta tags customization
diff --git a/etc/PROBLEMS b/etc/PROBLEMS
index fdce1bc81ba..048c56baa1a 100644
--- a/etc/PROBLEMS
+++ b/etc/PROBLEMS
@@ -1,6 +1,6 @@
 Known Problems with GNU Emacs
 
-Copyright (C) 1987-1989, 1993-1999, 2001-2023 Free Software Foundation,
+Copyright (C) 1987-1989, 1993-1999, 2001-2024 Free Software Foundation,
 Inc.
 See the end of the file for license conditions.
 
@@ -530,9 +530,10 @@ The solution is to use gawk (GNU awk).
 *** Saving a file encrypted with GnuPG via EasyPG hangs.
 
 This is known to happen with GnuPG v2.4.1.  The only known workaround
-is to downgrade to a version of GnuPG older than 2.4.1 (or, in the
-future, upgrade to a newer version which solves the problem, when such
-a fixed version becomes available).
+is to downgrade to a version of GnuPG older than 2.4.1, or upgrade to
+version 2.4.4 and newer, which reportedly solves the problem.  Note
+that GnuPG v2.2.42 and later also has this problem, so you should also
+avoid those later 2.2.4x versions; v2.2.41 is reported to work fine.
 
 *** EasyPG loopback pinentry does not work with gpgsm.
 
@@ -2014,7 +2015,7 @@ remote X server, try this:
 
 *** Dropping text on xterm doesn't work.
 
-Emacs sends sythetic button events to legacy clients such as xterm
+Emacs sends synthetic button events to legacy clients such as xterm
 that do not support either the XDND or Motif drag-and-drop protocols
 in order to "paste" the text that was dropped.  Unfortunately, xterm
 is configured to ignore these events by default.  Add the following to
@@ -3404,26 +3405,22 @@ this and many other problems do not exist on the 
regular X builds.
 
 ** Text displayed in the default monospace font looks horrible.
 
-Droid Sans Mono (the default Monospace font which comes with Android)
-incorporates instruction code designed for Microsoft's proprietary
-TrueType font scaler.  When this code is executed by Emacs to instruct
-a glyph containing more than one component, it tries to address
-"reference points" which are set to the values of two extra "phantom
-points" in the glyph, that are a proprietary extension of the MS font
-scaler.
-
-Emacs does not support these extensions, and as a result characters
-such as
-
-  ĥ
-
-display incorrectly, with the right most edge of the `h' component
-stretched very far out to the right, on some low density displays.
-
-The solution is to replace the MS-specific hinting code in Droid Sans
-Mono with automatically generated code from the FreeType project's
-"ttfautohint" program.  First, extract
-'/system/fonts/DroidSansMono.ttf' from your device:
+TrueType fonts incorporate instruction code executed by the font
+scaler (the component responsible for transforming outlines into
+bitmap images capable of being displayed onscreen) to align features
+of each glyph to pixel boundaries while maintaining their shape, in
+order to alleviate visual imperfections produced by scaling.  The
+substandard instruction code provided by the Android "Droid Sans Mono"
+font misplaces features of glyphs containing, as components, "E" and
+"F", between PPEM sizes of 16 and 24, resulting in noticeable
+whitespace inconsistencies with other glyphs.  Furthermore, the
+vertical stem in the glyph "T" is positioned too far to the left at
+PPEM sizes of 12.
+
+The remedy for this is to replace the instruction code with
+automatically generated code from the FreeType project's "ttfautohint"
+program.  First, extract '/system/fonts/DroidSansMono.ttf' from your
+device:
 
   $ adb pull /system/fonts/DroidSansMono.ttf
   /system/fonts/DroidSansMono.ttf: 1 file pulled, 0 skipped.
@@ -3446,85 +3443,18 @@ allowed by free versions of Android, such as Replicant):
 
 or to the user fonts directory described in the "Android Fonts" node
 of the Emacs manual.  You may want to perform this procedure even if
-you are not seeing problems with character display, as the
-automatically generated instructions result in superior display
-results that are easier to read.
-
-We have been told that the default Sans font under Android 2.3.7,
-named "Droid Sans", also exhibits this problem.  The procedure for
-repairing the font is identical to the procedure outlined above,
-albeit with "DroidSansMono" replaced by simply "DroidSans".
-
-** The "Anonymous Pro" font displays incorrectly.
-
-Glyph instruction code within the Anonymous Pro font relies on
-undocumented features of the Microsoft TrueType font scaler, namely
-that the scaler always resets the "projection" and "freedom" vector
-interpreter control registers after the execution of the font
-pre-program, which sets them to a value that is perpendicular to the
-horizontal plane of movement.
-
-Since Emacs does not provide this "feature", various points inside
-glyphs are moved vertically rather than horizontally when a glyph
-program later executes an instruction such as "MIRP" (Move Indirect
-Relative Point) that moves and measures points along the axis
-specified by those registers.
-
-This can be remedied in two ways; the first (and the easiest) is to
-replace its instruction code with that supplied by "ttfautohint", as
-depicted above.  The second is to patch the instruction code inside
-the font itself, using the "ttx" utility:
-
-  https://fonttools.readthedocs.io/en/latest/ttx.html
-
-First, convert the font to its XML representation:
-
-  $ ttx Anonymous_Pro.ttf
-
-then, find the end of the section labeled 'prep':
-
-  <prep>
-    <assembly>
-      [...]
-      ROUND[01]        /* Round */
-      RTG[ ]   /* RoundToGrid */
-      WCVTP[ ] /* WriteCVTInPixels */
-    </assembly>
-  </prep>
-
-and insert the following instruction immediately before the closing
-'/assembly' tag, so as to reset the interpreter control registers back
-to their default values prior to the completion of the pre-program:
-
-     SVTCA[1]  /* Set Vector registers to Control Axis X */
-
-Then, reassemble the font from the modified XML:
-
-  $ ttx Anonymous_Pro.ttx
-
-which should produce a modified font by the name of
-Anonymous_Pro#1.ttf.
-
-** The "IBM Plex Mono" font displays incorrectly.
-
-This problem is precipitated by an attempt to exploit the undocumented
-feature of the MS font scaler explicated within the previous heading.
-
-Its remedy is also unsurprisingly alike the fix described there: both
-patching the preprogram to reset the point movement vectors and
-replacing the instruction code with code generated by "ttfautohint"
-will adequately resolve the problem.
+you are not experiencing problems with character display, as the
+automatically generated instructions result in more legible text.
 
 ** Glyphs are missing within the "Arial" font or it does not load.
 
-On account of its origins at Microsoft, instruction code included
-within this font is awash with references to behavior specific to the
-MS scaler.  It is incorrigibly broken, to a degree that even
-"ttfautohint" cannot repair; your only recourse is to select some
-other font.
-
-This issue may extend beyond Arial to encompass a larger selection of
-fonts designed by Microsoft.
+Old versions of this font included instruction code that assumed a
+degree of latitude from the Microsoft font scaler, which grants fonts
+leave to address nonexistent points without aborting the scaling
+process, among other invalid TrueType operations.  This issue may
+extend beyond Arial to encompass a larger selection of old fonts
+designed by Microsoft or Monotype; most of the time, installing newer
+versions of such fonts will suffice.
 
 ** Some TrueType test fonts don't work.
 
@@ -3539,7 +3469,7 @@ The Microsoft scaler and FreeType promptly disregard such 
points.
 
 Nothing in the TrueType specifications implies that points "hidden" in
 this fashion should be afforded any special treatment, and thus Emacs
-eschews doing so.  Consequentially, black streaks are displayed as
+eschews doing so.  Consequently, black streaks are displayed as
 Emacs interpolates glyph edges between points within the glyph and
 points the test font attempts to hide.
 
@@ -3552,9 +3482,9 @@ Executing instruction code is not a strict requirement 
for producing
 correct display results from most current fonts.  If a font's
 instruction code produces results that are merely unpleasing, but not
 incorrect, then the font was presumably not designed for Emacs's
-scaler.  If its uninstructed glyphs are satisfactory (such as if your
-screen resolution is high to the extent that scaling artifacts prove
-invisible), disable instruction code execution by appending its family
+scaler.  If its uninstructed glyphs are satisfactory (such as when
+your screen resolution is high enough to ameliorate scaling
+artifacts), disable instruction code execution by appending its family
 name to the variable 'sfnt-uninstructable-font-regexp', then
 restarting Emacs.
 
diff --git a/etc/README b/etc/README
index 2884b0a039a..8ec120c1ce4 100644
--- a/etc/README
+++ b/etc/README
@@ -7,5 +7,5 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
 
 File: emacs.icon
   Author: Sun Microsystems, Inc
-  Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
   License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/TERMS b/etc/TERMS
index 444e194f8c0..b1b857c8391 100644
--- a/etc/TERMS
+++ b/etc/TERMS
@@ -1,4 +1,4 @@
-Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
 See the end of the file for copying permissions.
 
 This file describes what you must or might want to do to termcap entries
diff --git a/etc/TODO b/etc/TODO
index d2d124c9c8e..0152cf9303e 100644
--- a/etc/TODO
+++ b/etc/TODO
@@ -1,6 +1,6 @@
 Emacs TODO List                                                   -*-outline-*-
 
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
@@ -133,6 +133,20 @@ This should use a heuristic of some kind?
 ** In Emacs Info, examples of using Customize should be clickable
 They should create Custom buffers when clicked.
 
+** Replacements under 'Info-hide-note-references' should be language-sensitive
+Currently, we replace the "*note" cross-reference indicators with a
+hard-coded "see", which is English-centric and doesn't look well in
+manuals written in languages other than English.  To fix this, we need
+a change in the Texinfo's 'makeinfo' program so that it records the
+document's language (specified via the @documentlanguage directive in
+Texinfo) in a variable in the Local Variables section of the produced
+Info file.  Then 'Info-fontify-node' should be modified to look up the
+translation of "see" to that language in a database (which should be
+added), and should use that translation instead of "see".  See this
+discussion on the Texinfo mailing list for more details:
+
+  https://lists.gnu.org/archive/html/help-texinfo/2023-12/msg00011.html
+
 ** Add function to redraw the tool bar
 
 ** Redesign the load-history data structure
@@ -142,6 +156,8 @@ from.
 
 ** Make back_comment use syntax-ppss or equivalent
 
+** Make play-sound asynchronous and non-blocking
+
 ** Consider improving src/sysdep.c's search for a fqdn
 https://lists.gnu.org/r/emacs-devel/2007-04/msg00782.html
 
diff --git a/etc/charsets/README b/etc/charsets/README
index 4916972b2d6..361a6449451 100644
--- a/etc/charsets/README
+++ b/etc/charsets/README
@@ -1,6 +1,6 @@
 # README file for charset mapping files in this directory.
 
-# Copyright (C) 2003-2023 Free Software Foundation, Inc.
+# Copyright (C) 2003-2024 Free Software Foundation, Inc.
 # Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
 #   National Institute of Advanced Industrial Science and Technology (AIST)
 #   Registration Number H13PRO009
diff --git a/etc/compilation.txt b/etc/compilation.txt
index 5f6ecb09cc2..05f0829864c 100644
--- a/etc/compilation.txt
+++ b/etc/compilation.txt
@@ -344,6 +344,19 @@ In /home/janneke/vc/guile/examples/gud-break.scm:
 1033: 0 [stderr "~a:hello world\n" (# # #)]
 
 
+* Lua 5.1, 5.2, 5.3, 5.4, and LuaJIT 2.1
+
+/usr/bin/lua: database.lua:31: assertion failed!
+stack traceback:
+       [C]: in function 'assert'
+       database.lua:31: in field 'statement'
+       database.lua:42: in field 'table'
+       database.lua:55: in field 'row'
+       database.lua:63: in field 'value'
+       io.lua: in main chunk
+       [C]: in ?
+
+
 * Lucid Compiler, lcc 3.x
 
 symbol: lcc
@@ -702,7 +715,7 @@ Compilation segmentation fault at Thu Jul 13 10:55:49
 Compilation finished at Thu Jul 21 15:02:15
 
 
-Copyright (C) 2004-2023 Free Software Foundation, Inc.
+Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 COPYING PERMISSIONS:
 
diff --git a/etc/edt-user.el b/etc/edt-user.el
index 1a9216adaed..0813a97856d 100644
--- a/etc/edt-user.el
+++ b/etc/edt-user.el
@@ -1,6 +1,6 @@
 ;;; edt-user.el --- Sample user customizations for Emacs EDT emulation -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1986, 1992-1993, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1986, 1992-1993, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Kevin Gallagher <kevin.gal@verizon.net>
diff --git a/etc/emacs-buffer.gdb b/etc/emacs-buffer.gdb
index dd01d48855c..e36452af004 100644
--- a/etc/emacs-buffer.gdb
+++ b/etc/emacs-buffer.gdb
@@ -1,6 +1,6 @@
 # emacs-buffer.gdb --- gdb macros for recovering buffers from emacs coredumps
 
-# Copyright (C) 2005-2023 Free Software Foundation, Inc.
+# Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 # Author: Noah Friedman <friedman@splode.com>
 # Created: 2005-04-28
diff --git a/etc/emacs.metainfo.xml b/etc/emacs.metainfo.xml
index 65b0eda62ec..80bbd690217 100644
--- a/etc/emacs.metainfo.xml
+++ b/etc/emacs.metainfo.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2014-2023 Free Software Foundation, Inc. -->
+<!-- Copyright (C) 2014-2024 Free Software Foundation, Inc. -->
 <component type="desktop-application">
  <id>org.gnu.emacs</id>
  <metadata_license>GFDL-1.3+</metadata_license>
diff --git a/etc/emacs_lldb.py b/etc/emacs_lldb.py
index fa8d95d7b5b..fdf4314e2d0 100644
--- a/etc/emacs_lldb.py
+++ b/etc/emacs_lldb.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2022-2023 Free Software Foundation, Inc.
+# Copyright (C) 2022-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/etc/enriched.txt b/etc/enriched.txt
index 5828a6e68a7..a3bd3f21f5d 100644
--- a/etc/enriched.txt
+++ b/etc/enriched.txt
@@ -259,7 +259,7 @@ it.</indent>
 
 
 
-Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 
 COPYING PERMISSIONS:
 
diff --git a/etc/forms/forms-d2.el b/etc/forms/forms-d2.el
index afdf5119bb4..b1f378cbc39 100644
--- a/etc/forms/forms-d2.el
+++ b/etc/forms/forms-d2.el
@@ -1,6 +1,6 @@
 ;;; forms-d2.el --- demo forms-mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1991, 1994-1997, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1991, 1994-1997, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Johan Vromans <jvromans@squirrel.nl>
diff --git a/etc/gnus-tut.txt b/etc/gnus-tut.txt
index 9212a81be27..02b4b7e2193 100644
--- a/etc/gnus-tut.txt
+++ b/etc/gnus-tut.txt
@@ -24,7 +24,7 @@ was done by moi, yours truly, your humble servant, Lars Magne
 Ingebrigtsen.  If you have a WWW browser, you can investigate to your
 heart's delight at <URL:http://www.ifi.uio.no/~larsi/larsi.html>.
 
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
 ;; Keywords: news
diff --git a/etc/grep.txt b/etc/grep.txt
index 99e6d3641be..653123344dc 100644
--- a/etc/grep.txt
+++ b/etc/grep.txt
@@ -104,7 +104,7 @@ grep -nH -e "xyzxyz" ../info/*
 
 * Miscellaneous
 
-Copyright (C) 2005-2023 Free Software Foundation, Inc.
+Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 COPYING PERMISSIONS:
 
diff --git a/etc/images/README b/etc/images/README
index 5886f641536..a778d9ce6c3 100644
--- a/etc/images/README
+++ b/etc/images/README
@@ -27,19 +27,19 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
 
 File: mh-logo.xpm
   Author: Satyaki Das
-  Copyright (C) 2003-2023 Free Software Foundation, Inc.
+  Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 Files: gnus.pbm
   Author: Luis Fernandes <elf@ee.ryerson.ca>
-  Copyright (C) 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 Files: splash.png, splash.svg, splash.pbm, splash.xpm
   Author: Francesc Rocher <francesc.rocher@gmail.com>
-  Copyright (C) 2008-2023 Free Software Foundation, Inc.
+  Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 Files: checked.xpm, unchecked.xpm
   Author: Chong Yidong <cyd@stupidchicken.com>
-  Copyright (C) 2010-2023 Free Software Foundation, Inc.
+  Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 
 * The following icons are from GTK+ 2.x. They are not part of Emacs, but
@@ -67,21 +67,25 @@ Emacs images and their source in the GNOME icons stock/ 
directory:
   attach.xpm                document/stock_attach
   bookmark_add.xpm          actions/bookmark_add
   cancel.xpm                slightly modified generic/stock_stop
-  connect.xpm               net/stock_connect
+  commit.xpm                code/stock_run
   connect-to-url.xpm        net/stock_connect-to-url
+  connect.xpm               net/stock_connect
   contact.xpm               net/stock_contact
   data-save.xpm             data/stock_data-save
   delete.xpm                generic/stock_delete
   describe.xpm              generic/stock_properties
   disconnect.xpm            net/stock_disconnect
   exit.xpm                  generic/stock_exit
+  gen-changelog.xpm         text/stock_autoformat
+  ins-changelog.xpm         form/stock_show-form-dialog
+  load-changelog.xpm        text/stock_insert_endnote
   lock-broken.xpm           data/stock_lock-broken
   lock-ok.xpm               data/stock_lock-ok
   lock.xpm                  data/stock_lock
-  redo.xpm                  generic/stock_redo
-  search-replace.xpm        slightly modified generic/stock_search-and-replace
   next-page.xpm             navigation/stock_next-page
+  redo.xpm                  generic/stock_redo
   refresh.xpm               generic/stock_refresh
+  search-replace.xpm        slightly modified generic/stock_search-and-replace
   separator.xpm             ?
   show.xpm                  slightly modified document/stock_new
   sort-ascending.xpm        slightly modified data/stock_sort-ascending
@@ -89,6 +93,7 @@ Emacs images and their source in the GNOME icons stock/ 
directory:
   sort-criteria.xpm         data/stock_sort-criteria
   sort-descending.xpm       slightly modified data/stock_sort-descending
   sort-row-ascending.xpm    data/stock_sort-row-ascending
+  view-diff.xpm             text/stock_list_enum-restart
   zoom-in.xpm               navigation/stock_zoom-in
   zoom-out.xpm              navigation/stock_zoom-out
 
diff --git a/etc/images/commit.pbm b/etc/images/commit.pbm
new file mode 100644
index 00000000000..11fe690ac1b
Binary files /dev/null and b/etc/images/commit.pbm differ
diff --git a/etc/images/commit.xpm b/etc/images/commit.xpm
new file mode 100644
index 00000000000..1730f155811
--- /dev/null
+++ b/etc/images/commit.xpm
@@ -0,0 +1,101 @@
+/* XPM */
+static char *commit[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 71 1 ",
+"  c None",
+". c black",
+"X c gray13",
+"o c gray14",
+"O c #252525",
+"+ c gray25",
+"@ c gray33",
+"# c #555555",
+"$ c #565656",
+"% c #5A5A5A",
+"& c #5D5D5D",
+"* c gray40",
+"= c #6C6C6C",
+"- c #DF421E",
+"; c #46A046",
+": c #625B81",
+"> c #887FA3",
+", c #848484",
+"< c gray53",
+"1 c #888888",
+"2 c #8E8E8E",
+"3 c #979797",
+"4 c #9A9A9A",
+"5 c #A0A0A0",
+"6 c gray65",
+"7 c #A9A9A9",
+"8 c #AEAEAE",
+"9 c gray75",
+"0 c #BBB6CA",
+"q c #C2C2C1",
+"w c gray76",
+"e c #C3C3C2",
+"r c #C3C3C3",
+"t c gray77",
+"y c #C7C7C6",
+"u c #C8C8C8",
+"i c gray79",
+"p c #C5C1D2",
+"a c #CAC6D6",
+"s c gray84",
+"d c #D8D8D8",
+"f c gray88",
+"g c #E1E1E1",
+"h c #E6E6E6",
+"j c #EDEDEB",
+"k c #EEEEED",
+"l c #EFEFEF",
+"z c #ECEAF0",
+"x c #ECEBF0",
+"c c #F0EFF3",
+"v c gray94",
+"b c #F1F1F0",
+"n c #F2F2F1",
+"m c #F4F4F3",
+"M c #F4F3F6",
+"N c #F5F5F4",
+"B c gray96",
+"V c #F6F6F5",
+"C c #F6F6F6",
+"Z c gray97",
+"A c #F8F8F7",
+"S c #F7F6F8",
+"D c #F8F8F8",
+"F c #F9F9F9",
+"G c gray98",
+"H c #FCFCFB",
+"J c gray99",
+"K c #FDFDFC",
+"L c #FDFDFD",
+"P c #FEFEFE",
+"I c white",
+/* pixels */
+"                 ...... ",
+"                 .xx00. ",
+"                ..xp>>..",
+"                .Spa>>>.",
+"+++++++++##      .Mp>>. ",
+"IIIIIIIIIGs<o     .c>.  ",
+"IIIIIIIIIGhv5.     ..   ",
+"IIIIIIIIIGdIB3o         ",
+"IIIIIIIIIBiIIg1X        ",
+";:IIIIIIIB9gsiw2        ",
+"IIIIIIIIHB7*&#%<.       ",
+":::G::::GBvsy64=.       ",
+"GGGGGGGGGGGGGGG8.       ",
+"--::G:::GGGGGGGw.       ",
+"GGGGGGGGGGGGGGGy.       ",
+"::A::AAAAAAAAAAy.       ",
+"BBBBBBBBBBBBBBBy.       ",
+"BBBBBBBBBBBBBBBw.       ",
+":mmmmmmmmmmmmmmw.       ",
+"vvvvvvvvvvvvvvvw.       ",
+"---v:v:::v:::vvw.       ",
+"lllllllllllllllw.       ",
+"::::l--:lllllllw.       ",
+"jjjjjjjjjjjjjjjw.       "
+};
diff --git a/etc/images/custom/README b/etc/images/custom/README
index 7ed66523ecd..235303c3dd3 100644
--- a/etc/images/custom/README
+++ b/etc/images/custom/README
@@ -6,5 +6,5 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
 
 Files: down.xpm down-pushed.xpm right.xpm right-pushed.xpm
 Author: Juri Linkov
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/ezimage/README b/etc/images/ezimage/README
index 4d2482de515..02178819211 100644
--- a/etc/images/ezimage/README
+++ b/etc/images/ezimage/README
@@ -7,5 +7,5 @@ Files: bits.xpm bitsbang.xpm box-minus.xpm box-plus.xpm
        tag-gt.xpm tag-minus.xpm tag-plus.xpm tag-type.xpm tag-v.xpm
        tag.xpm unlock.xpm
 Author: Eric M. Ludlam
-Copyright (C) 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1999-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/gen-changelog.pbm b/etc/images/gen-changelog.pbm
new file mode 100644
index 00000000000..40bea125b06
Binary files /dev/null and b/etc/images/gen-changelog.pbm differ
diff --git a/etc/images/gen-changelog.xpm b/etc/images/gen-changelog.xpm
new file mode 100644
index 00000000000..65ea7c16f04
--- /dev/null
+++ b/etc/images/gen-changelog.xpm
@@ -0,0 +1,152 @@
+/* XPM */
+static char *gen_changelog[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 122 2 ",
+"   c None",
+".  c black",
+"X  c gray10",
+"o  c #353535",
+"O  c #442D0E",
+"+  c #5E4417",
+"@  c #7D5A22",
+"#  c #645435",
+"$  c #464646",
+"%  c #505050",
+"&  c gray32",
+"*  c #535353",
+"=  c gray33",
+"-  c #585858",
+";  c gray35",
+":  c #675E46",
+">  c gray39",
+",  c #6E6E6C",
+"<  c gray43",
+"1  c gray44",
+"2  c #787775",
+"3  c #797979",
+"4  c #7B7B7B",
+"5  c #88601F",
+"6  c #A27E36",
+"7  c #9A8558",
+"8  c #9F8B5F",
+"9  c #A09069",
+"0  c #BAA069",
+"q  c #C7AF7A",
+"w  c #CCB176",
+"e  c #868583",
+"r  c #868686",
+"t  c gray53",
+"y  c #8B8A86",
+"u  c #888888",
+"i  c #898989",
+"p  c #8B8B88",
+"a  c gray54",
+"s  c #8B8B8B",
+"d  c #8C8C89",
+"f  c gray55",
+"g  c #8D8D8D",
+"h  c #8E8E8E",
+"j  c gray56",
+"k  c #909090",
+"l  c gray57",
+"z  c #929292",
+"x  c #939393",
+"c  c #969592",
+"v  c gray58",
+"b  c #959595",
+"n  c #979797",
+"m  c #9B9996",
+"M  c #9C9B97",
+"N  c #B8B39B",
+"B  c #A4A4A4",
+"V  c gray65",
+"C  c #A8A7A3",
+"Z  c #AAAAAA",
+"A  c #B0AFAC",
+"S  c gray70",
+"D  c #B4B4B4",
+"F  c #B6B6B6",
+"G  c #C0BFBD",
+"H  c #D6C08E",
+"J  c #D9C28B",
+"K  c #DEC58D",
+"L  c #D8C291",
+"P  c #DFCA96",
+"I  c #E1CC99",
+"U  c #C2C1BD",
+"Y  c #F3E5BE",
+"T  c #C5C5C5",
+"R  c #C6C6C6",
+"E  c gray79",
+"W  c #CACACA",
+"Q  c gray80",
+"!  c #CECECE",
+"~  c #D2D0D0",
+"^  c #DBDAD8",
+"/  c gray86",
+"(  c gainsboro",
+")  c #DDDDDD",
+"_  c #F4E7C2",
+"`  c #EBE8D3",
+"'  c gray88",
+"]  c #E1E1E1",
+"[  c #E2E2E2",
+"{  c gray89",
+"}  c #E4E4E4",
+"|  c gray90",
+" . c #E6E6E6",
+".. c #E7E7E7",
+"X. c #EAE8E3",
+"o. c gray91",
+"O. c #E9E9E9",
+"+. c #EAEAEA",
+"@. c gray92",
+"#. c #EFEDE9",
+"$. c #ECECEC",
+"%. c gray93",
+"&. c #EEEEEE",
+"*. c #EFEFEF",
+"=. c #FEFCE8",
+"-. c #FEFEED",
+";. c gray94",
+":. c #F1F1F1",
+">. c gray95",
+",. c #F3F3F3",
+"<. c #F4F4F4",
+"1. c gray96",
+"2. c #F6F6F6",
+"3. c gray97",
+"4. c #F8F8F8",
+"5. c #F9F9F9",
+"6. c gray98",
+"7. c #FBFBFB",
+"8. c gray99",
+"9. c #FDFDFD",
+"0. c #FEFEFE",
+"q. c white",
+/* pixels */
+"  . . . . . . . . . . . . . . . . . . . .       ",
+". [ >.>.>.>.>.>.>.<.<.<.<.<.<.<.<.<.<.<.) .     ",
+". >.[ [ [ [ [ } } } } o.o.o.o.o.$.$.$.$.$..     ",
+". >.[ r r r r i i ; . & i o.o.$.$.$.$.>.>..     ",
+". >.[ [ [ } } } [ . N . [ $.$.$.$.$.>.>.>..     ",
+". >.[ r i i i i < . ` . = g g g g >.>.>.>..     ",
+". >.} } } } } 3 . . -.. . 3 o.>.>.>.>.>.<..     ",
+". >.} i i ; . . : _ =.6 # . . D >.>.>.<.<..     ",
+". <.} } o.. 7 q J P Y w I K 8 . T <.<.<.<..     ",
+". <.} i i & . . O @ 0 5 + . . n <.<.<.<.<..     ",
+". <.o.o.o.o.[ k . . H . X $ . <.<.<.<.<.4..     ",
+". <.o.i g g g g > . L . ; d C . <.<.4.4.4..     ",
+". <.o.$.$.$.$.$.o.. 9 o . 2 G U . 4.4.4.4..     ",
+". <.o.g g g g g g & . 1 T . i ~ C . 4.4.9..     ",
+". <.$.$.$.$.>.>.>.>.T ) T T . M ^ A . 9.9..     ",
+". <.$.g g g g k >.<.<.<.) ) S . C #.c . 9..     ",
+". 4.>.>.>.>.>.<.<.<.<.4.4.[ E D . M X.e . .     ",
+". 4.>.k k k k k k k k n n n [ Q B . m X.< .     ",
+". >.>.<.<.<.<.<.<.4.4.4.4.9.9.} Q B . c X.2 .   ",
+". E $.4.<.<.<.4.4.4.4.4.9.9.9.9.} Q Z . y X.2 . ",
+"  . . . . . . . . . . . . . . . . . . . . y X.. ",
+"                                          . .   ",
+"                                                ",
+"                                                "
+};
diff --git a/etc/images/gnus/README b/etc/images/gnus/README
index f05cf0f7f10..40bdc103f11 100644
--- a/etc/images/gnus/README
+++ b/etc/images/gnus/README
@@ -7,7 +7,7 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
 
 Files: important.xpm, unimportant.xpm
 Author: Simon Josefsson <simon@josefsson.org>
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 Files: catchup.pbm catchup.xpm cu-exit.pbm cu-exit.xpm
   describe-group.pbm describe-group.xpm exit-gnus.pbm exit-gnus.xpm
@@ -21,11 +21,11 @@ Files: catchup.pbm catchup.xpm cu-exit.pbm cu-exit.xpm
   unsubscribe.pbm unsubscribe.xpm uu-decode.pbm uu-decode.xpm
   uu-post.pbm uu-post.xpm
 Author: Luis Fernandes <elf@ee.ryerson.ca>
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 Files: gnus.png, gnus.svg
   Author: Francesc Rocher <rocher@member.fsf.org>
-  Copyright (C) 2008-2023 Free Software Foundation, Inc.
+  Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 
 * The following icons are from GNOME 2.x. They are not part of Emacs,
diff --git a/etc/images/gnus/gnus-pointer.svg b/etc/images/gnus/gnus-pointer.svg
index 67a631cdcf5..590e0f56d89 100644
--- a/etc/images/gnus/gnus-pointer.svg
+++ b/etc/images/gnus/gnus-pointer.svg
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!-- Gnu Emacs Logo
 
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
    Author: Francesc Rocher <f.rocher@member.fsf.org>
 
diff --git a/etc/images/gnus/gnus.svg b/etc/images/gnus/gnus.svg
index 14f96da5e55..42aee872bf0 100644
--- a/etc/images/gnus/gnus.svg
+++ b/etc/images/gnus/gnus.svg
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!-- Gnu Emacs Logo
 
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
    Author: Francesc Rocher <f.rocher@member.fsf.org>
 
diff --git a/etc/images/gud/README b/etc/images/gud/README
index 6a06a2671ac..6cdcce35fba 100644
--- a/etc/images/gud/README
+++ b/etc/images/gud/README
@@ -1,7 +1,7 @@
 COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
 
 The following icons were created by Nick Roberts <nickrob@snap.net.nz>.
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
 
   break.pbm, nexti.pbm, go.pbm, pp.pbm, print.pbm, pstar.pbm, remove.pbm
diff --git a/etc/images/icons/README b/etc/images/icons/README
index bb455980ca7..c7d755dc1b9 100644
--- a/etc/images/icons/README
+++ b/etc/images/icons/README
@@ -6,7 +6,7 @@ Files: hicolor/16x16/apps/emacs.png hicolor/24x24/apps/emacs.png
        hicolor/scalable/mimetypes/emacs-document.svg
 
 Author: Nicolas Petton <nicolas@petton.fr>
-Copyright (C) 2015-2023 Free Software Foundation, Inc.
+Copyright (C) 2015-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
 
 Files: hicolor/16x16/apps/emacs23.png hicolor/24x24/apps/emacs23.png
@@ -14,7 +14,7 @@ Files: hicolor/16x16/apps/emacs23.png 
hicolor/24x24/apps/emacs23.png
        hicolor/128x128/apps/emacs23.png hicolor/scalable/apps/emacs23.svg
 
 Author: Kentaro Ohkouchi <nanasess@fsm.ne.jp>
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
 
 
@@ -22,7 +22,7 @@ Files: hicolor/16x16/apps/emacs22.png 
hicolor/24x24/apps/emacs22.png
        hicolor/32x32/apps/emacs22.png hicolor/48x48/apps/emacs22.png
 
 Author: Andrew Zhilin <andrew_zhilin@yahoo.com>
-Copyright (C) 2005-2023 Free Software Foundation, Inc.
+Copyright (C) 2005-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
 
 Files: allout-widgets-dark-bg/closed.png
@@ -71,5 +71,5 @@ Files: allout-widgets-dark-bg/closed.png
        allout-widgets-light-bg/through-descender.xpm
 
 Author: Ken Manheimer <ken.manheimer@gmail.com>
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/icons/hicolor/scalable/apps/emacs.svg 
b/etc/images/icons/hicolor/scalable/apps/emacs.svg
index a7da237a720..d352f184db2 100644
--- a/etc/images/icons/hicolor/scalable/apps/emacs.svg
+++ b/etc/images/icons/hicolor/scalable/apps/emacs.svg
@@ -15,7 +15,7 @@
      id="metadata70"><rdf:RDF><cc:Work
          rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
            rdf:resource="http://purl.org/dc/dcmitype/StillImage"; 
/><dc:title></dc:title></cc:Work></rdf:RDF></metadata><!-- Gnu Emacs Icon
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
    Author: Nicolas Petton <nicolas@petton.fr>
 
diff --git a/etc/images/icons/hicolor/scalable/apps/emacs23.svg 
b/etc/images/icons/hicolor/scalable/apps/emacs23.svg
index 966c265ffcf..a4122d67547 100644
--- a/etc/images/icons/hicolor/scalable/apps/emacs23.svg
+++ b/etc/images/icons/hicolor/scalable/apps/emacs23.svg
@@ -10,7 +10,7 @@
    id="svg4768"
    xml:space="preserve">
 <!-- Gnu Emacs Icon
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
    This file is part of GNU Emacs.
 
diff --git a/etc/images/icons/hicolor/scalable/mimetypes/emacs-document23.svg 
b/etc/images/icons/hicolor/scalable/mimetypes/emacs-document23.svg
index 23373c6ad08..7abcb917712 100644
--- a/etc/images/icons/hicolor/scalable/mimetypes/emacs-document23.svg
+++ b/etc/images/icons/hicolor/scalable/mimetypes/emacs-document23.svg
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!-- Gnu Emacs Document Icon
 
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
    This file is part of GNU Emacs.
 
diff --git a/etc/images/ins-changelog.pbm b/etc/images/ins-changelog.pbm
new file mode 100644
index 00000000000..fb97cf7d5d8
--- /dev/null
+++ b/etc/images/ins-changelog.pbm
@@ -0,0 +1,3 @@
+P4
+24 24
+��������������������������������������������������������������
\ No newline at end of file
diff --git a/etc/images/ins-changelog.xpm b/etc/images/ins-changelog.xpm
new file mode 100644
index 00000000000..24deee3c344
--- /dev/null
+++ b/etc/images/ins-changelog.xpm
@@ -0,0 +1,67 @@
+/* XPM */
+static char *ins_changelog[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 37 1 ",
+"  c None",
+". c black",
+"X c #161616",
+"o c gray25",
+"O c #4B4B49",
+"+ c #5D5D5D",
+"@ c #494066",
+"# c #767676",
+"$ c gray52",
+"% c #A0A0A0",
+"& c gray66",
+"* c gray68",
+"= c #BBBBBB",
+"- c #BCBCBC",
+"; c gray74",
+": c #C1C1C1",
+"> c gray76",
+", c #C3C3C3",
+"< c gray88",
+"1 c #E2E2E2",
+"2 c gray89",
+"3 c #E4E4E4",
+"4 c gray90",
+"5 c #E6E6E6",
+"6 c #E7E7E7",
+"7 c gray91",
+"8 c #EAEAEA",
+"9 c gray92",
+"0 c #ECECEC",
+"q c gray93",
+"w c #EEEEEE",
+"e c #EFEFEF",
+"r c gray94",
+"t c #F1F1F1",
+"y c #FBFBFB",
+"u c #FDFDFD",
+"i c #FEFEFE",
+/* pixels */
+"                        ",
+"                        ",
+"  @ @@ @@ @@ @@         ",
+"  @                     ",
+"              @         ",
+"  @           @         ",
+"  @                     ",
+"           .........    ",
+"  @       .iiiiiii2>.   ",
+"  @       .itttttt>y&.  ",
+"          .itttttt*#+o. ",
+"  @       .it@@@@t2$OX. ",
+"  @       .iteeeeeeee=. ",
+"          .ie@@@@@@@e=. ",
+"  @       .ieeeeeeee9=. ",
+"  @       .ie@@@@@@@9=. ",
+"          .i999999499=. ",
+"  @@ @@ @@.i9@@@@@@@4=. ",
+"          .i944444444=. ",
+"          .i4@@@@@@@4=. ",
+"          .i444444222=. ",
+"          .>-----====%. ",
+"           ...........  ",
+"                        "
+};
diff --git a/etc/images/load-changelog.pbm b/etc/images/load-changelog.pbm
new file mode 100644
index 00000000000..43f1a1b221f
Binary files /dev/null and b/etc/images/load-changelog.pbm differ
diff --git a/etc/images/load-changelog.xpm b/etc/images/load-changelog.xpm
new file mode 100644
index 00000000000..6d317b6afa2
--- /dev/null
+++ b/etc/images/load-changelog.xpm
@@ -0,0 +1,82 @@
+/* XPM */
+static char *load_changelog[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 52 1 ",
+"  c None",
+". c black",
+"X c #434343",
+"o c gray33",
+"O c #DF421E",
+"+ c #8B8B8B",
+"@ c gray55",
+"# c #8D8D8D",
+"$ c #8E8E8E",
+"% c gray56",
+"& c #909090",
+"* c gray57",
+"= c #929292",
+"- c #939393",
+"; c gray58",
+": c #959595",
+"> c gray66",
+", c #B7B7B7",
+"< c gray74",
+"1 c #C0C0C0",
+"2 c gray79",
+"3 c #CACACA",
+"4 c gray84",
+"5 c gray85",
+"6 c #DADADA",
+"7 c #DDDDDD",
+"8 c #DFDFDF",
+"9 c gray90",
+"0 c gray91",
+"q c #E9E9E9",
+"w c #EAEAEA",
+"e c gray92",
+"r c #ECECEC",
+"t c gray93",
+"y c #EEEEEE",
+"u c #EFEFEF",
+"i c gray94",
+"p c #F1F1F1",
+"a c gray95",
+"s c #F3F3F3",
+"d c #F4F4F4",
+"f c gray96",
+"g c #F6F6F6",
+"h c gray97",
+"j c #F8F8F8",
+"k c #F9F9F9",
+"l c gray98",
+"z c #FBFBFB",
+"x c gray99",
+"c c #FDFDFD",
+"v c #FEFEFE",
+"b c white",
+/* pixels */
+"  ..  ..  ..  ..        ",
+" .d3..51..7>..d,..      ",
+" .d00tttttiiiiddd4.     ",
+" .d0+$$$$$$&&&$jjt.     ",
+" .d00ttiiiidddjjX5.     ",
+" .d0$$$&9OOOOcjj........",
+" .dttiiidddddjjjo7.    .",
+" .dttiiiddddddjjc5.    .",
+" .jiidddddjjjcccc7.    .",
+" .ji&&&&&&;;;;;cc7.    .",
+" .jiiiddddjjjjccc7.    .",
+" .ji&&&&&;;;;cccc7.    .",
+" .iiidddjjjjccccct.    .",
+" .3tjdjjjjjccccct<.    .",
+"  ................     .",
+"                       .",
+"                       .",
+"                     . .",
+"                    .. .",
+"   OOOOOOOOOOOOO  ......",
+"   OOOOOOOOOOOOO    ..  ",
+"                     .  ",
+"                        ",
+"                        "
+};
diff --git a/etc/images/mpc/README b/etc/images/mpc/README
index 27e1b356dc5..17b347e13d6 100644
--- a/etc/images/mpc/README
+++ b/etc/images/mpc/README
@@ -2,5 +2,5 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
 
 Files: add.xpm ffwd.xpm next.xpm pause.xpm play.xpm prev.xpm rewind.xpm 
stop.xpm
 Author: Stefan Monnier <monnier@iro.umontreal.ca>
-Copyright (C) 2009-2023 Free Software Foundation, Inc.
+Copyright (C) 2009-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/newsticker/README b/etc/images/newsticker/README
index dafa77ea186..65d1782829b 100644
--- a/etc/images/newsticker/README
+++ b/etc/images/newsticker/README
@@ -4,5 +4,5 @@ Files: browse-url.xpm get-all.xpm mark-immortal.xpm 
mark-read.xpm
        narrow.xpm next-feed.xpm next-item.xpm prev-feed.xpm
        prev-item.xpm rss-feed.png rss-feed.svg update.xpm
 Author: Ulf Jasper
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/smilies/README b/etc/images/smilies/README
index 20a17376bf7..7e000ae7def 100644
--- a/etc/images/smilies/README
+++ b/etc/images/smilies/README
@@ -3,5 +3,5 @@ Files: blink.pbm blink.xpm braindamaged.xpm cry.xpm dead.xpm 
evil.xpm
        sad.xpm smile.pbm smile.xpm wry.pbm wry.xpm
 Authors: Reiner Steib, Simon Josefsson, Kai Grossjohann, Alex
          Schroeder, Oliver Scholz, Per Abrahamsen, Kim F. Storm.
-Copyright (C) 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1999-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/smilies/grayscale/README 
b/etc/images/smilies/grayscale/README
index 5b3422866dd..b41d7eb19d3 100644
--- a/etc/images/smilies/grayscale/README
+++ b/etc/images/smilies/grayscale/README
@@ -3,5 +3,5 @@ Files: blink.xpm braindamaged.xpm cry.xpm dead.xpm evil.xpm 
forced.xpm
        frown.xpm grin.xpm indifferent.xpm reverse-smile.xpm sad.xpm
        smile.xpm wry.xpm
 Author: Adam Sjøgren
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/smilies/medium/README b/etc/images/smilies/medium/README
index 5b3422866dd..b41d7eb19d3 100644
--- a/etc/images/smilies/medium/README
+++ b/etc/images/smilies/medium/README
@@ -3,5 +3,5 @@ Files: blink.xpm braindamaged.xpm cry.xpm dead.xpm evil.xpm 
forced.xpm
        frown.xpm grin.xpm indifferent.xpm reverse-smile.xpm sad.xpm
        smile.xpm wry.xpm
 Author: Adam Sjøgren
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/splash.svg b/etc/images/splash.svg
index cfb027b8f94..114b637bfaf 100644
--- a/etc/images/splash.svg
+++ b/etc/images/splash.svg
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!-- Gnu Emacs Logo
 
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
    Author: Francesc Rocher <francesc.rocher@gmail.com>
    Based on the original work by Luis Fernandes <elf@ee.ryerson.ca>
diff --git a/etc/images/symbols/README b/etc/images/symbols/README
index f69a4ba8760..24429302e63 100644
--- a/etc/images/symbols/README
+++ b/etc/images/symbols/README
@@ -4,7 +4,7 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
 
 Files: *.svg
 Author: Yuan Fu <casouri@gmail.com>
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
 
 How I made these icons: I made them with Figma, and exported them into
diff --git a/etc/images/symbols/minus_16.pbm b/etc/images/symbols/minus_16.pbm
index 4f73340f179..c564ca290d8 100644
Binary files a/etc/images/symbols/minus_16.pbm and 
b/etc/images/symbols/minus_16.pbm differ
diff --git a/etc/images/symbols/minus_16.svg b/etc/images/symbols/minus_16.svg
index 9cb61d8d379..f0769763e5d 100644
--- a/etc/images/symbols/minus_16.svg
+++ b/etc/images/symbols/minus_16.svg
@@ -1,3 +1,3 @@
 <svg width="16" height="16" viewBox="0 0 16 16"  
xmlns="http://www.w3.org/2000/svg";>
-<path d="M13 7H3V9H13V7Z" />
+<path d="M12.5 7H3.5V9H12.5V7Z" />
 </svg>
diff --git a/etc/images/symbols/plus_16.pbm b/etc/images/symbols/plus_16.pbm
index c369231b636..2d8a45a5db4 100644
Binary files a/etc/images/symbols/plus_16.pbm and 
b/etc/images/symbols/plus_16.pbm differ
diff --git a/etc/images/symbols/plus_16.svg b/etc/images/symbols/plus_16.svg
index a4d2f84f318..573a5e5ca76 100644
--- a/etc/images/symbols/plus_16.svg
+++ b/etc/images/symbols/plus_16.svg
@@ -1,3 +1,3 @@
 <svg width="16" height="16" viewBox="0 0 16 16"  
xmlns="http://www.w3.org/2000/svg";>
-<path d="M9 3H7V7H3V9H7V13H9V9H13V7H9V3Z" />
+<path d="M9 3.5H7V7H3.5V9H7V12.5H9V9H12.5V7H9V3.5Z" />
 </svg>
diff --git a/etc/images/tabs/README b/etc/images/tabs/README
index d9a1b814b72..1b646812882 100644
--- a/etc/images/tabs/README
+++ b/etc/images/tabs/README
@@ -4,5 +4,5 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
 
 Files: close.xpm new.xpm left-arrow.xpm right-arrow.xpm
 Author: Juri Linkov <juri@linkov.net>
-Copyright (C) 2019-2023 Free Software Foundation, Inc.
+Copyright (C) 2019-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/tree-widget/default/README 
b/etc/images/tree-widget/default/README
index 88e9328d52e..16f98c82d8e 100644
--- a/etc/images/tree-widget/default/README
+++ b/etc/images/tree-widget/default/README
@@ -5,5 +5,5 @@ Files: close.png close.xpm empty.png empty.xpm end-guide.png 
end-guide.xpm
        no-guide.png no-guide.xpm no-handle.png no-handle.xpm open.png
        open.xpm
 Author: David Ponce <david.ponce@wanadoo.fr>
-Copyright (C) 2004-2023 Free Software Foundation, Inc.
+Copyright (C) 2004-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/tree-widget/folder/README 
b/etc/images/tree-widget/folder/README
index 992159dff2a..b3d11f20558 100644
--- a/etc/images/tree-widget/folder/README
+++ b/etc/images/tree-widget/folder/README
@@ -5,5 +5,5 @@ Files:  close.png close.xpm empty.png empty.xpm end-guide.png
         leaf.png leaf.xpm no-guide.png no-guide.xpm no-handle.png
         no-handle.xpm open.png open.xpm
 Author: David Ponce <david.ponce@wanadoo.fr>
-Copyright (C) 2004-2023 Free Software Foundation, Inc.
+Copyright (C) 2004-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/view-diff.pbm b/etc/images/view-diff.pbm
new file mode 100644
index 00000000000..35aabdabb1e
Binary files /dev/null and b/etc/images/view-diff.pbm differ
diff --git a/etc/images/view-diff.xpm b/etc/images/view-diff.xpm
new file mode 100644
index 00000000000..3ebd0b3002b
--- /dev/null
+++ b/etc/images/view-diff.xpm
@@ -0,0 +1,93 @@
+/* XPM */
+static char *view_diff[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 63 1 ",
+"  c None",
+". c black",
+"X c gray43",
+"o c #6F6F6F",
+"O c gray44",
+"+ c #717171",
+"@ c #727272",
+"# c gray45",
+"$ c #747474",
+"% c gray46",
+"& c #767676",
+"* c #777777",
+"= c gray47",
+"- c #DF421E",
+"; c #E3846E",
+": c #838383",
+"> c gray74",
+", c #E19989",
+"< c #E29A8A",
+"1 c #E39B8B",
+"2 c #E59C8B",
+"3 c #E49C8C",
+"4 c #E4AB9E",
+"5 c #E8AEA1",
+"6 c #C5C5C5",
+"7 c gray79",
+"8 c gray81",
+"9 c #DADADA",
+"0 c gray86",
+"q c #DDDDDD",
+"w c #EAD4CE",
+"e c gray88",
+"r c #E1E1E1",
+"t c #E2E2E2",
+"y c gray89",
+"u c #E4E4E4",
+"i c gray90",
+"p c #E6E6E6",
+"a c #E7E7E7",
+"s c gray91",
+"d c #E9E9E9",
+"f c #EAEAEA",
+"g c gray92",
+"h c #ECECEC",
+"j c gray93",
+"k c #EEEEEE",
+"l c #EFEFEF",
+"z c gray94",
+"x c #F1F1F1",
+"c c gray95",
+"v c #F3F3F3",
+"b c #F4F4F4",
+"n c gray96",
+"m c #F6F6F6",
+"M c gray97",
+"N c #F8F8F8",
+"B c #F9F9F9",
+"V c gray98",
+"C c #FBFBFB",
+"Z c gray99",
+"A c #FDFDFD",
+"S c #FEFEFE",
+"D c white",
+/* pixels */
+" ....................   ",
+".tcccccccbbbbbbbbbbbq.  ",
+".ctttttiiiidddddhhhhh.  ",
+".ctttti8Xidddddhhhhcc.  ",
+".cttti8XXdd+++++++ccc.  ",
+".ctiiiiiXddhhhhhhcccc.  ",
+".c,---id+dd++++++$ccb.  ",
+".ci,--dd+dhhhhchcccbb.  ",
+".bi-,-dddhh+++$cbcbbb.  ",
+".b-4d3dhhhhhccccbbbbb.  ",
+".b-ddhhhhhhccccbbbNNN.  ",
+".b-ddhhhhccccbbbbNNNN.  ",
+".b;-whh6$0cccbbbbNNNN.  ",
+".bd2-5h+c$b:$$$$$=NNZ.  ",
+".bhhhhccq$bbbbbNNNNZZ.  ",
+".bhhhcc0$qb$$$$==NZZZ.  ",
+".Nccccc$$$bNNNNNZZZZZ.  ",
+".NcccbbbbbNNNZZZZZZZZ.  ",
+".ccbbbbbbNNNZZZZZZZZh.  ",
+".7hNbbbNNNNNZZZZZZZh>.  ",
+" ....................   ",
+"                        ",
+"                        ",
+"                        "
+};
diff --git a/etc/org.gnu.emacs.defaults.gschema.xml 
b/etc/org.gnu.emacs.defaults.gschema.xml
index 06ff42c438f..9fedadb92c6 100644
--- a/etc/org.gnu.emacs.defaults.gschema.xml
+++ b/etc/org.gnu.emacs.defaults.gschema.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019-2020, 2022-2023 Free Software Foundation, Inc. -->
+<!-- Copyright (C) 2019-2020, 2022-2024 Free Software Foundation, Inc. -->
 <schemalist>
 
   <schema id="org.gnu.emacs.defaults">
diff --git a/etc/org/README b/etc/org/README
index 3737c8df9ac..7944bcb207c 100644
--- a/etc/org/README
+++ b/etc/org/README
@@ -1,7 +1,7 @@
 The files OrgOdtContentTemplate.xml and OrgOdtStyles.xml have the
 following copyright information:
 
-Copyright (C) 2010-2023 Free Software Foundation, Inc.
+Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 These files are part of GNU Emacs.
 
diff --git a/etc/ps-prin0.ps b/etc/ps-prin0.ps
index ba35337e4e4..a9471de2093 100644
--- a/etc/ps-prin0.ps
+++ b/etc/ps-prin0.ps
@@ -1,7 +1,7 @@
 % === BEGIN ps-print prologue 0
 % version: 6.0
 
-% Copyright (C) 2000-2023 Free Software Foundation, Inc.
+% Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 % This file is part of GNU Emacs.
 
diff --git a/etc/ps-prin1.ps b/etc/ps-prin1.ps
index 37512a86ab9..34bde99c420 100644
--- a/etc/ps-prin1.ps
+++ b/etc/ps-prin1.ps
@@ -1,7 +1,7 @@
 % === BEGIN ps-print prologue 1
 % version: 6.1
 
-% Copyright (C) 2000-2023 Free Software Foundation, Inc.
+% Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 % This file is part of GNU Emacs.
 
diff --git a/etc/publicsuffix.txt b/etc/publicsuffix.txt
index 956110851a4..79248a73f04 100644
--- a/etc/publicsuffix.txt
+++ b/etc/publicsuffix.txt
@@ -6710,7 +6710,7 @@ org.zw
 
 // newGTLDs
 
-// List of new gTLDs imported from 
https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 
2023-09-30T15:11:25Z
+// List of new gTLDs imported from 
https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 
2023-12-06T15:14:09Z
 // This list is auto-generated, don't edit it manually.
 // aaa : American Automobile Association, Inc.
 // https://www.iana.org/domains/root/db/aaa.html
@@ -7400,10 +7400,6 @@ cbn
 // https://www.iana.org/domains/root/db/cbre.html
 cbre
 
-// cbs : CBS Domains Inc.
-// https://www.iana.org/domains/root/db/cbs.html
-cbs
-
 // center : Binky Moon, LLC
 // https://www.iana.org/domains/root/db/center.html
 center
@@ -7492,10 +7488,6 @@ citic
 // https://www.iana.org/domains/root/db/city.html
 city
 
-// cityeats : Lifestyle Domain Holdings, Inc.
-// https://www.iana.org/domains/root/db/cityeats.html
-cityeats
-
 // claims : Binky Moon, LLC
 // https://www.iana.org/domains/root/db/claims.html
 claims
@@ -7760,7 +7752,7 @@ dental
 // https://www.iana.org/domains/root/db/dentist.html
 dentist
 
-// desi : Desi Networks LLC
+// desi
 // https://www.iana.org/domains/root/db/desi.html
 desi
 
@@ -7808,7 +7800,7 @@ discover
 // https://www.iana.org/domains/root/db/dish.html
 dish
 
-// diy : Lifestyle Domain Holdings, Inc.
+// diy : Internet Naming Company LLC
 // https://www.iana.org/domains/root/db/diy.html
 diy
 
@@ -7940,10 +7932,6 @@ esq
 // https://www.iana.org/domains/root/db/estate.html
 estate
 
-// etisalat : Emirates Telecommunications Corporation (trading as Etisalat)
-// https://www.iana.org/domains/root/db/etisalat.html
-etisalat
-
 // eurovision : European Broadcasting Union (EBU)
 // https://www.iana.org/domains/root/db/eurovision.html
 eurovision
@@ -8116,7 +8104,7 @@ fly
 // https://www.iana.org/domains/root/db/foo.html
 foo
 
-// food : Lifestyle Domain Holdings, Inc.
+// food : Internet Naming Company LLC
 // https://www.iana.org/domains/root/db/food.html
 food
 
@@ -8164,10 +8152,6 @@ frl
 // https://www.iana.org/domains/root/db/frogans.html
 frogans
 
-// frontdoor : Lifestyle Domain Holdings, Inc.
-// https://www.iana.org/domains/root/db/frontdoor.html
-frontdoor
-
 // frontier : Frontier Communications Corporation
 // https://www.iana.org/domains/root/db/frontier.html
 frontier
@@ -8328,7 +8312,7 @@ goldpoint
 // https://www.iana.org/domains/root/db/golf.html
 golf
 
-// goo : NTT Resonant Inc.
+// goo : NTT DOCOMO, INC.
 // https://www.iana.org/domains/root/db/goo.html
 goo
 
@@ -8780,10 +8764,6 @@ kids
 // https://www.iana.org/domains/root/db/kim.html
 kim
 
-// kinder : Ferrero Trading Lux S.A.
-// https://www.iana.org/domains/root/db/kinder.html
-kinder
-
 // kindle : Amazon Registry Services, Inc.
 // https://www.iana.org/domains/root/db/kindle.html
 kindle
@@ -8928,7 +8908,7 @@ life
 // https://www.iana.org/domains/root/db/lifeinsurance.html
 lifeinsurance
 
-// lifestyle : Lifestyle Domain Holdings, Inc.
+// lifestyle : Internet Naming Company LLC
 // https://www.iana.org/domains/root/db/lifestyle.html
 lifestyle
 
@@ -8968,7 +8948,7 @@ lipsy
 // https://www.iana.org/domains/root/db/live.html
 live
 
-// living : Lifestyle Domain Holdings, Inc.
+// living : Internet Naming Company LLC
 // https://www.iana.org/domains/root/db/living.html
 living
 
@@ -9672,7 +9652,7 @@ promo
 // https://www.iana.org/domains/root/db/properties.html
 properties
 
-// property : Internet Naming Company LLC
+// property : Digital Property Infrastructure Limited
 // https://www.iana.org/domains/root/db/property.html
 property
 
@@ -9836,10 +9816,6 @@ rio
 // https://www.iana.org/domains/root/db/rip.html
 rip
 
-// rocher : Ferrero Trading Lux S.A.
-// https://www.iana.org/domains/root/db/rocher.html
-rocher
-
 // rocks : Dog Beach, LLC
 // https://www.iana.org/domains/root/db/rocks.html
 rocks
@@ -10088,10 +10064,6 @@ shouji
 // https://www.iana.org/domains/root/db/show.html
 show
 
-// showtime : CBS Domains Inc.
-// https://www.iana.org/domains/root/db/showtime.html
-showtime
-
 // silk : Amazon Registry Services, Inc.
 // https://www.iana.org/domains/root/db/silk.html
 silk
@@ -10552,7 +10524,7 @@ ups
 // https://www.iana.org/domains/root/db/vacations.html
 vacations
 
-// vana : Lifestyle Domain Holdings, Inc.
+// vana : Internet Naming Company LLC
 // https://www.iana.org/domains/root/db/vana.html
 vana
 
@@ -10636,10 +10608,6 @@ vlaanderen
 // https://www.iana.org/domains/root/db/vodka.html
 vodka
 
-// volkswagen : Volkswagen Group of America Inc.
-// https://www.iana.org/domains/root/db/volkswagen.html
-volkswagen
-
 // volvo : Volvo Holding Sverige Aktiebolag
 // https://www.iana.org/domains/root/db/volvo.html
 volvo
@@ -10708,6 +10676,10 @@ weber
 // https://www.iana.org/domains/root/db/website.html
 website
 
+// wed
+// https://www.iana.org/domains/root/db/wed.html
+wed
+
 // wedding : Registry Services, LLC
 // https://www.iana.org/domains/root/db/wedding.html
 wedding
@@ -11040,10 +11012,6 @@ xin
 // https://www.iana.org/domains/root/db/xn--mgba7c0bbn0a.html
 العليان
 
-// xn--mgbaakc7dvf : Emirates Telecommunications Corporation (trading as 
Etisalat)
-// https://www.iana.org/domains/root/db/xn--mgbaakc7dvf.html
-اتصالات
-
 // xn--mgbab2bd : CORE Association
 // https://www.iana.org/domains/root/db/xn--mgbab2bd.html
 بازار
@@ -11345,11 +11313,78 @@ myamaze.net
 // Submitted by AWS Security <psl-maintainers@amazon.com>
 // Subsections of Amazon/subsidiaries will appear until "concludes" tag
 
+// Amazon API Gateway
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 4d863337-ff98-4501-a6f2-361eba8445d6
+execute-api.cn-north-1.amazonaws.com.cn
+execute-api.cn-northwest-1.amazonaws.com.cn
+execute-api.af-south-1.amazonaws.com
+execute-api.ap-east-1.amazonaws.com
+execute-api.ap-northeast-1.amazonaws.com
+execute-api.ap-northeast-2.amazonaws.com
+execute-api.ap-northeast-3.amazonaws.com
+execute-api.ap-south-1.amazonaws.com
+execute-api.ap-south-2.amazonaws.com
+execute-api.ap-southeast-1.amazonaws.com
+execute-api.ap-southeast-2.amazonaws.com
+execute-api.ap-southeast-3.amazonaws.com
+execute-api.ap-southeast-4.amazonaws.com
+execute-api.ca-central-1.amazonaws.com
+execute-api.eu-central-1.amazonaws.com
+execute-api.eu-central-2.amazonaws.com
+execute-api.eu-north-1.amazonaws.com
+execute-api.eu-south-1.amazonaws.com
+execute-api.eu-south-2.amazonaws.com
+execute-api.eu-west-1.amazonaws.com
+execute-api.eu-west-2.amazonaws.com
+execute-api.eu-west-3.amazonaws.com
+execute-api.il-central-1.amazonaws.com
+execute-api.me-central-1.amazonaws.com
+execute-api.me-south-1.amazonaws.com
+execute-api.sa-east-1.amazonaws.com
+execute-api.us-east-1.amazonaws.com
+execute-api.us-east-2.amazonaws.com
+execute-api.us-gov-east-1.amazonaws.com
+execute-api.us-gov-west-1.amazonaws.com
+execute-api.us-west-1.amazonaws.com
+execute-api.us-west-2.amazonaws.com
+
 // Amazon CloudFront
 // Submitted by Donavan Miller <donavanm@amazon.com>
 // Reference: 54144616-fd49-4435-8535-19c6a601bdb3
 cloudfront.net
 
+// Amazon Cognito
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 7bee1013-f456-47df-bfe8-03c78d946d61
+auth.af-south-1.amazoncognito.com
+auth.ap-northeast-1.amazoncognito.com
+auth.ap-northeast-2.amazoncognito.com
+auth.ap-northeast-3.amazoncognito.com
+auth.ap-south-1.amazoncognito.com
+auth.ap-southeast-1.amazoncognito.com
+auth.ap-southeast-2.amazoncognito.com
+auth.ap-southeast-3.amazoncognito.com
+auth.ca-central-1.amazoncognito.com
+auth.eu-central-1.amazoncognito.com
+auth.eu-north-1.amazoncognito.com
+auth.eu-south-1.amazoncognito.com
+auth.eu-west-1.amazoncognito.com
+auth.eu-west-2.amazoncognito.com
+auth.eu-west-3.amazoncognito.com
+auth.il-central-1.amazoncognito.com
+auth.me-south-1.amazoncognito.com
+auth.sa-east-1.amazoncognito.com
+auth.us-east-1.amazoncognito.com
+auth-fips.us-east-1.amazoncognito.com
+auth.us-east-2.amazoncognito.com
+auth-fips.us-east-2.amazoncognito.com
+auth-fips.us-gov-west-1.amazoncognito.com
+auth.us-west-1.amazoncognito.com
+auth-fips.us-west-1.amazoncognito.com
+auth.us-west-2.amazoncognito.com
+auth-fips.us-west-2.amazoncognito.com
+
 // Amazon EC2
 // Submitted by Luke Wells <psl-maintainers@amazon.com>
 // Reference: 4c38fa71-58ac-4768-99e5-689c1767e537
@@ -11358,47 +11393,307 @@ cloudfront.net
 *.compute.amazonaws.com.cn
 us-east-1.amazonaws.com
 
+// Amazon EMR
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 597f3f8e-9283-4e48-8e32-7ee25a1ff6ab
+emrappui-prod.cn-north-1.amazonaws.com.cn
+emrnotebooks-prod.cn-north-1.amazonaws.com.cn
+emrstudio-prod.cn-north-1.amazonaws.com.cn
+emrappui-prod.cn-northwest-1.amazonaws.com.cn
+emrnotebooks-prod.cn-northwest-1.amazonaws.com.cn
+emrstudio-prod.cn-northwest-1.amazonaws.com.cn
+emrappui-prod.af-south-1.amazonaws.com
+emrnotebooks-prod.af-south-1.amazonaws.com
+emrstudio-prod.af-south-1.amazonaws.com
+emrappui-prod.ap-east-1.amazonaws.com
+emrnotebooks-prod.ap-east-1.amazonaws.com
+emrstudio-prod.ap-east-1.amazonaws.com
+emrappui-prod.ap-northeast-1.amazonaws.com
+emrnotebooks-prod.ap-northeast-1.amazonaws.com
+emrstudio-prod.ap-northeast-1.amazonaws.com
+emrappui-prod.ap-northeast-2.amazonaws.com
+emrnotebooks-prod.ap-northeast-2.amazonaws.com
+emrstudio-prod.ap-northeast-2.amazonaws.com
+emrappui-prod.ap-northeast-3.amazonaws.com
+emrnotebooks-prod.ap-northeast-3.amazonaws.com
+emrstudio-prod.ap-northeast-3.amazonaws.com
+emrappui-prod.ap-south-1.amazonaws.com
+emrnotebooks-prod.ap-south-1.amazonaws.com
+emrstudio-prod.ap-south-1.amazonaws.com
+emrappui-prod.ap-southeast-1.amazonaws.com
+emrnotebooks-prod.ap-southeast-1.amazonaws.com
+emrstudio-prod.ap-southeast-1.amazonaws.com
+emrappui-prod.ap-southeast-2.amazonaws.com
+emrnotebooks-prod.ap-southeast-2.amazonaws.com
+emrstudio-prod.ap-southeast-2.amazonaws.com
+emrappui-prod.ap-southeast-3.amazonaws.com
+emrnotebooks-prod.ap-southeast-3.amazonaws.com
+emrstudio-prod.ap-southeast-3.amazonaws.com
+emrappui-prod.ca-central-1.amazonaws.com
+emrnotebooks-prod.ca-central-1.amazonaws.com
+emrstudio-prod.ca-central-1.amazonaws.com
+emrappui-prod.eu-central-1.amazonaws.com
+emrnotebooks-prod.eu-central-1.amazonaws.com
+emrstudio-prod.eu-central-1.amazonaws.com
+emrappui-prod.eu-north-1.amazonaws.com
+emrnotebooks-prod.eu-north-1.amazonaws.com
+emrstudio-prod.eu-north-1.amazonaws.com
+emrappui-prod.eu-south-1.amazonaws.com
+emrnotebooks-prod.eu-south-1.amazonaws.com
+emrstudio-prod.eu-south-1.amazonaws.com
+emrappui-prod.eu-west-1.amazonaws.com
+emrnotebooks-prod.eu-west-1.amazonaws.com
+emrstudio-prod.eu-west-1.amazonaws.com
+emrappui-prod.eu-west-2.amazonaws.com
+emrnotebooks-prod.eu-west-2.amazonaws.com
+emrstudio-prod.eu-west-2.amazonaws.com
+emrappui-prod.eu-west-3.amazonaws.com
+emrnotebooks-prod.eu-west-3.amazonaws.com
+emrstudio-prod.eu-west-3.amazonaws.com
+emrappui-prod.me-central-1.amazonaws.com
+emrnotebooks-prod.me-central-1.amazonaws.com
+emrstudio-prod.me-central-1.amazonaws.com
+emrappui-prod.me-south-1.amazonaws.com
+emrnotebooks-prod.me-south-1.amazonaws.com
+emrstudio-prod.me-south-1.amazonaws.com
+emrappui-prod.sa-east-1.amazonaws.com
+emrnotebooks-prod.sa-east-1.amazonaws.com
+emrstudio-prod.sa-east-1.amazonaws.com
+emrappui-prod.us-east-1.amazonaws.com
+emrnotebooks-prod.us-east-1.amazonaws.com
+emrstudio-prod.us-east-1.amazonaws.com
+emrappui-prod.us-east-2.amazonaws.com
+emrnotebooks-prod.us-east-2.amazonaws.com
+emrstudio-prod.us-east-2.amazonaws.com
+emrappui-prod.us-gov-east-1.amazonaws.com
+emrnotebooks-prod.us-gov-east-1.amazonaws.com
+emrstudio-prod.us-gov-east-1.amazonaws.com
+emrappui-prod.us-gov-west-1.amazonaws.com
+emrnotebooks-prod.us-gov-west-1.amazonaws.com
+emrstudio-prod.us-gov-west-1.amazonaws.com
+emrappui-prod.us-west-1.amazonaws.com
+emrnotebooks-prod.us-west-1.amazonaws.com
+emrstudio-prod.us-west-1.amazonaws.com
+emrappui-prod.us-west-2.amazonaws.com
+emrnotebooks-prod.us-west-2.amazonaws.com
+emrstudio-prod.us-west-2.amazonaws.com
+
+// Amazon Managed Workflows for Apache Airflow
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 4ab55e6f-90c0-4a8d-b6a0-52ca5dbb1c2e
+*.cn-north-1.airflow.amazonaws.com.cn
+*.cn-northwest-1.airflow.amazonaws.com.cn
+*.ap-northeast-1.airflow.amazonaws.com
+*.ap-northeast-2.airflow.amazonaws.com
+*.ap-south-1.airflow.amazonaws.com
+*.ap-southeast-1.airflow.amazonaws.com
+*.ap-southeast-2.airflow.amazonaws.com
+*.ca-central-1.airflow.amazonaws.com
+*.eu-central-1.airflow.amazonaws.com
+*.eu-north-1.airflow.amazonaws.com
+*.eu-west-1.airflow.amazonaws.com
+*.eu-west-2.airflow.amazonaws.com
+*.eu-west-3.airflow.amazonaws.com
+*.sa-east-1.airflow.amazonaws.com
+*.us-east-1.airflow.amazonaws.com
+*.us-east-2.airflow.amazonaws.com
+*.us-west-2.airflow.amazonaws.com
+
 // Amazon S3
-// Submitted by Luke Wells <psl-maintainers@amazon.com>
-// Reference: d068bd97-f0a9-4838-a6d8-954b622ef4ae
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 0e801048-08f2-4064-9cb8-e7373e0b57f4
+s3.dualstack.cn-north-1.amazonaws.com.cn
+s3-accesspoint.dualstack.cn-north-1.amazonaws.com.cn
+s3-website.dualstack.cn-north-1.amazonaws.com.cn
 s3.cn-north-1.amazonaws.com.cn
+s3-accesspoint.cn-north-1.amazonaws.com.cn
+s3-deprecated.cn-north-1.amazonaws.com.cn
+s3-object-lambda.cn-north-1.amazonaws.com.cn
+s3-website.cn-north-1.amazonaws.com.cn
+s3.dualstack.cn-northwest-1.amazonaws.com.cn
+s3-accesspoint.dualstack.cn-northwest-1.amazonaws.com.cn
+s3.cn-northwest-1.amazonaws.com.cn
+s3-accesspoint.cn-northwest-1.amazonaws.com.cn
+s3-object-lambda.cn-northwest-1.amazonaws.com.cn
+s3-website.cn-northwest-1.amazonaws.com.cn
+s3.dualstack.af-south-1.amazonaws.com
+s3-accesspoint.dualstack.af-south-1.amazonaws.com
+s3-website.dualstack.af-south-1.amazonaws.com
+s3.af-south-1.amazonaws.com
+s3-accesspoint.af-south-1.amazonaws.com
+s3-object-lambda.af-south-1.amazonaws.com
+s3-website.af-south-1.amazonaws.com
+s3.dualstack.ap-east-1.amazonaws.com
+s3-accesspoint.dualstack.ap-east-1.amazonaws.com
+s3.ap-east-1.amazonaws.com
+s3-accesspoint.ap-east-1.amazonaws.com
+s3-object-lambda.ap-east-1.amazonaws.com
+s3-website.ap-east-1.amazonaws.com
 s3.dualstack.ap-northeast-1.amazonaws.com
+s3-accesspoint.dualstack.ap-northeast-1.amazonaws.com
+s3-website.dualstack.ap-northeast-1.amazonaws.com
+s3.ap-northeast-1.amazonaws.com
+s3-accesspoint.ap-northeast-1.amazonaws.com
+s3-object-lambda.ap-northeast-1.amazonaws.com
+s3-website.ap-northeast-1.amazonaws.com
 s3.dualstack.ap-northeast-2.amazonaws.com
+s3-accesspoint.dualstack.ap-northeast-2.amazonaws.com
+s3-website.dualstack.ap-northeast-2.amazonaws.com
 s3.ap-northeast-2.amazonaws.com
+s3-accesspoint.ap-northeast-2.amazonaws.com
+s3-object-lambda.ap-northeast-2.amazonaws.com
 s3-website.ap-northeast-2.amazonaws.com
+s3.dualstack.ap-northeast-3.amazonaws.com
+s3-accesspoint.dualstack.ap-northeast-3.amazonaws.com
+s3-website.dualstack.ap-northeast-3.amazonaws.com
+s3.ap-northeast-3.amazonaws.com
+s3-accesspoint.ap-northeast-3.amazonaws.com
+s3-object-lambda.ap-northeast-3.amazonaws.com
+s3-website.ap-northeast-3.amazonaws.com
 s3.dualstack.ap-south-1.amazonaws.com
+s3-accesspoint.dualstack.ap-south-1.amazonaws.com
+s3-website.dualstack.ap-south-1.amazonaws.com
 s3.ap-south-1.amazonaws.com
+s3-accesspoint.ap-south-1.amazonaws.com
+s3-object-lambda.ap-south-1.amazonaws.com
 s3-website.ap-south-1.amazonaws.com
+s3.dualstack.ap-south-2.amazonaws.com
+s3-accesspoint.dualstack.ap-south-2.amazonaws.com
+s3.ap-south-2.amazonaws.com
+s3-accesspoint.ap-south-2.amazonaws.com
+s3-object-lambda.ap-south-2.amazonaws.com
+s3-website.ap-south-2.amazonaws.com
 s3.dualstack.ap-southeast-1.amazonaws.com
+s3-accesspoint.dualstack.ap-southeast-1.amazonaws.com
+s3-website.dualstack.ap-southeast-1.amazonaws.com
+s3.ap-southeast-1.amazonaws.com
+s3-accesspoint.ap-southeast-1.amazonaws.com
+s3-object-lambda.ap-southeast-1.amazonaws.com
+s3-website.ap-southeast-1.amazonaws.com
 s3.dualstack.ap-southeast-2.amazonaws.com
+s3-accesspoint.dualstack.ap-southeast-2.amazonaws.com
+s3-website.dualstack.ap-southeast-2.amazonaws.com
+s3.ap-southeast-2.amazonaws.com
+s3-accesspoint.ap-southeast-2.amazonaws.com
+s3-object-lambda.ap-southeast-2.amazonaws.com
+s3-website.ap-southeast-2.amazonaws.com
+s3.dualstack.ap-southeast-3.amazonaws.com
+s3-accesspoint.dualstack.ap-southeast-3.amazonaws.com
+s3.ap-southeast-3.amazonaws.com
+s3-accesspoint.ap-southeast-3.amazonaws.com
+s3-object-lambda.ap-southeast-3.amazonaws.com
+s3-website.ap-southeast-3.amazonaws.com
+s3.dualstack.ap-southeast-4.amazonaws.com
+s3-accesspoint.dualstack.ap-southeast-4.amazonaws.com
+s3.ap-southeast-4.amazonaws.com
+s3-accesspoint.ap-southeast-4.amazonaws.com
+s3-object-lambda.ap-southeast-4.amazonaws.com
+s3-website.ap-southeast-4.amazonaws.com
 s3.dualstack.ca-central-1.amazonaws.com
+s3-accesspoint.dualstack.ca-central-1.amazonaws.com
+s3-accesspoint-fips.dualstack.ca-central-1.amazonaws.com
+s3-fips.dualstack.ca-central-1.amazonaws.com
+s3-website.dualstack.ca-central-1.amazonaws.com
 s3.ca-central-1.amazonaws.com
+s3-accesspoint.ca-central-1.amazonaws.com
+s3-accesspoint-fips.ca-central-1.amazonaws.com
+s3-fips.ca-central-1.amazonaws.com
+s3-object-lambda.ca-central-1.amazonaws.com
 s3-website.ca-central-1.amazonaws.com
 s3.dualstack.eu-central-1.amazonaws.com
+s3-accesspoint.dualstack.eu-central-1.amazonaws.com
+s3-website.dualstack.eu-central-1.amazonaws.com
 s3.eu-central-1.amazonaws.com
+s3-accesspoint.eu-central-1.amazonaws.com
+s3-object-lambda.eu-central-1.amazonaws.com
 s3-website.eu-central-1.amazonaws.com
+s3.dualstack.eu-central-2.amazonaws.com
+s3-accesspoint.dualstack.eu-central-2.amazonaws.com
+s3.eu-central-2.amazonaws.com
+s3-accesspoint.eu-central-2.amazonaws.com
+s3-object-lambda.eu-central-2.amazonaws.com
+s3-website.eu-central-2.amazonaws.com
+s3.dualstack.eu-north-1.amazonaws.com
+s3-accesspoint.dualstack.eu-north-1.amazonaws.com
+s3.eu-north-1.amazonaws.com
+s3-accesspoint.eu-north-1.amazonaws.com
+s3-object-lambda.eu-north-1.amazonaws.com
+s3-website.eu-north-1.amazonaws.com
+s3.dualstack.eu-south-1.amazonaws.com
+s3-accesspoint.dualstack.eu-south-1.amazonaws.com
+s3-website.dualstack.eu-south-1.amazonaws.com
+s3.eu-south-1.amazonaws.com
+s3-accesspoint.eu-south-1.amazonaws.com
+s3-object-lambda.eu-south-1.amazonaws.com
+s3-website.eu-south-1.amazonaws.com
+s3.dualstack.eu-south-2.amazonaws.com
+s3-accesspoint.dualstack.eu-south-2.amazonaws.com
+s3.eu-south-2.amazonaws.com
+s3-accesspoint.eu-south-2.amazonaws.com
+s3-object-lambda.eu-south-2.amazonaws.com
+s3-website.eu-south-2.amazonaws.com
 s3.dualstack.eu-west-1.amazonaws.com
+s3-accesspoint.dualstack.eu-west-1.amazonaws.com
+s3-website.dualstack.eu-west-1.amazonaws.com
+s3.eu-west-1.amazonaws.com
+s3-accesspoint.eu-west-1.amazonaws.com
+s3-deprecated.eu-west-1.amazonaws.com
+s3-object-lambda.eu-west-1.amazonaws.com
+s3-website.eu-west-1.amazonaws.com
 s3.dualstack.eu-west-2.amazonaws.com
+s3-accesspoint.dualstack.eu-west-2.amazonaws.com
 s3.eu-west-2.amazonaws.com
+s3-accesspoint.eu-west-2.amazonaws.com
+s3-object-lambda.eu-west-2.amazonaws.com
 s3-website.eu-west-2.amazonaws.com
 s3.dualstack.eu-west-3.amazonaws.com
+s3-accesspoint.dualstack.eu-west-3.amazonaws.com
+s3-website.dualstack.eu-west-3.amazonaws.com
 s3.eu-west-3.amazonaws.com
+s3-accesspoint.eu-west-3.amazonaws.com
+s3-object-lambda.eu-west-3.amazonaws.com
 s3-website.eu-west-3.amazonaws.com
+s3.dualstack.il-central-1.amazonaws.com
+s3-accesspoint.dualstack.il-central-1.amazonaws.com
+s3.il-central-1.amazonaws.com
+s3-accesspoint.il-central-1.amazonaws.com
+s3-object-lambda.il-central-1.amazonaws.com
+s3-website.il-central-1.amazonaws.com
+s3.dualstack.me-central-1.amazonaws.com
+s3-accesspoint.dualstack.me-central-1.amazonaws.com
+s3.me-central-1.amazonaws.com
+s3-accesspoint.me-central-1.amazonaws.com
+s3-object-lambda.me-central-1.amazonaws.com
+s3-website.me-central-1.amazonaws.com
+s3.dualstack.me-south-1.amazonaws.com
+s3-accesspoint.dualstack.me-south-1.amazonaws.com
+s3.me-south-1.amazonaws.com
+s3-accesspoint.me-south-1.amazonaws.com
+s3-object-lambda.me-south-1.amazonaws.com
+s3-website.me-south-1.amazonaws.com
 s3.amazonaws.com
+s3-1.amazonaws.com
+s3-ap-east-1.amazonaws.com
 s3-ap-northeast-1.amazonaws.com
 s3-ap-northeast-2.amazonaws.com
+s3-ap-northeast-3.amazonaws.com
 s3-ap-south-1.amazonaws.com
 s3-ap-southeast-1.amazonaws.com
 s3-ap-southeast-2.amazonaws.com
 s3-ca-central-1.amazonaws.com
 s3-eu-central-1.amazonaws.com
+s3-eu-north-1.amazonaws.com
 s3-eu-west-1.amazonaws.com
 s3-eu-west-2.amazonaws.com
 s3-eu-west-3.amazonaws.com
 s3-external-1.amazonaws.com
+s3-fips-us-gov-east-1.amazonaws.com
 s3-fips-us-gov-west-1.amazonaws.com
+mrap.accesspoint.s3-global.amazonaws.com
+s3-me-south-1.amazonaws.com
 s3-sa-east-1.amazonaws.com
 s3-us-east-2.amazonaws.com
+s3-us-gov-east-1.amazonaws.com
 s3-us-gov-west-1.amazonaws.com
 s3-us-west-1.amazonaws.com
 s3-us-west-2.amazonaws.com
@@ -11408,23 +11703,182 @@ s3-website-ap-southeast-2.amazonaws.com
 s3-website-eu-west-1.amazonaws.com
 s3-website-sa-east-1.amazonaws.com
 s3-website-us-east-1.amazonaws.com
+s3-website-us-gov-west-1.amazonaws.com
 s3-website-us-west-1.amazonaws.com
 s3-website-us-west-2.amazonaws.com
 s3.dualstack.sa-east-1.amazonaws.com
+s3-accesspoint.dualstack.sa-east-1.amazonaws.com
+s3-website.dualstack.sa-east-1.amazonaws.com
+s3.sa-east-1.amazonaws.com
+s3-accesspoint.sa-east-1.amazonaws.com
+s3-object-lambda.sa-east-1.amazonaws.com
+s3-website.sa-east-1.amazonaws.com
 s3.dualstack.us-east-1.amazonaws.com
+s3-accesspoint.dualstack.us-east-1.amazonaws.com
+s3-accesspoint-fips.dualstack.us-east-1.amazonaws.com
+s3-fips.dualstack.us-east-1.amazonaws.com
+s3-website.dualstack.us-east-1.amazonaws.com
+s3.us-east-1.amazonaws.com
+s3-accesspoint.us-east-1.amazonaws.com
+s3-accesspoint-fips.us-east-1.amazonaws.com
+s3-deprecated.us-east-1.amazonaws.com
+s3-fips.us-east-1.amazonaws.com
+s3-object-lambda.us-east-1.amazonaws.com
+s3-website.us-east-1.amazonaws.com
 s3.dualstack.us-east-2.amazonaws.com
+s3-accesspoint.dualstack.us-east-2.amazonaws.com
+s3-accesspoint-fips.dualstack.us-east-2.amazonaws.com
+s3-fips.dualstack.us-east-2.amazonaws.com
 s3.us-east-2.amazonaws.com
+s3-accesspoint.us-east-2.amazonaws.com
+s3-accesspoint-fips.us-east-2.amazonaws.com
+s3-deprecated.us-east-2.amazonaws.com
+s3-fips.us-east-2.amazonaws.com
+s3-object-lambda.us-east-2.amazonaws.com
 s3-website.us-east-2.amazonaws.com
+s3.dualstack.us-gov-east-1.amazonaws.com
+s3-accesspoint.dualstack.us-gov-east-1.amazonaws.com
+s3-accesspoint-fips.dualstack.us-gov-east-1.amazonaws.com
+s3-fips.dualstack.us-gov-east-1.amazonaws.com
+s3.us-gov-east-1.amazonaws.com
+s3-accesspoint.us-gov-east-1.amazonaws.com
+s3-accesspoint-fips.us-gov-east-1.amazonaws.com
+s3-fips.us-gov-east-1.amazonaws.com
+s3-object-lambda.us-gov-east-1.amazonaws.com
+s3-website.us-gov-east-1.amazonaws.com
+s3.dualstack.us-gov-west-1.amazonaws.com
+s3-accesspoint.dualstack.us-gov-west-1.amazonaws.com
+s3-accesspoint-fips.dualstack.us-gov-west-1.amazonaws.com
+s3-fips.dualstack.us-gov-west-1.amazonaws.com
+s3.us-gov-west-1.amazonaws.com
+s3-accesspoint.us-gov-west-1.amazonaws.com
+s3-accesspoint-fips.us-gov-west-1.amazonaws.com
+s3-fips.us-gov-west-1.amazonaws.com
+s3-object-lambda.us-gov-west-1.amazonaws.com
+s3-website.us-gov-west-1.amazonaws.com
+s3.dualstack.us-west-1.amazonaws.com
+s3-accesspoint.dualstack.us-west-1.amazonaws.com
+s3-accesspoint-fips.dualstack.us-west-1.amazonaws.com
+s3-fips.dualstack.us-west-1.amazonaws.com
+s3-website.dualstack.us-west-1.amazonaws.com
+s3.us-west-1.amazonaws.com
+s3-accesspoint.us-west-1.amazonaws.com
+s3-accesspoint-fips.us-west-1.amazonaws.com
+s3-fips.us-west-1.amazonaws.com
+s3-object-lambda.us-west-1.amazonaws.com
+s3-website.us-west-1.amazonaws.com
+s3.dualstack.us-west-2.amazonaws.com
+s3-accesspoint.dualstack.us-west-2.amazonaws.com
+s3-accesspoint-fips.dualstack.us-west-2.amazonaws.com
+s3-fips.dualstack.us-west-2.amazonaws.com
+s3-website.dualstack.us-west-2.amazonaws.com
+s3.us-west-2.amazonaws.com
+s3-accesspoint.us-west-2.amazonaws.com
+s3-accesspoint-fips.us-west-2.amazonaws.com
+s3-deprecated.us-west-2.amazonaws.com
+s3-fips.us-west-2.amazonaws.com
+s3-object-lambda.us-west-2.amazonaws.com
+s3-website.us-west-2.amazonaws.com
+
+// Amazon SageMaker Notebook Instances
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: fe8c9e94-5a22-486d-8750-991a3a9b13c6
+notebook.af-south-1.sagemaker.aws
+notebook.ap-east-1.sagemaker.aws
+notebook.ap-northeast-1.sagemaker.aws
+notebook.ap-northeast-2.sagemaker.aws
+notebook.ap-northeast-3.sagemaker.aws
+notebook.ap-south-1.sagemaker.aws
+notebook.ap-south-2.sagemaker.aws
+notebook.ap-southeast-1.sagemaker.aws
+notebook.ap-southeast-2.sagemaker.aws
+notebook.ap-southeast-3.sagemaker.aws
+notebook.ap-southeast-4.sagemaker.aws
+notebook.ca-central-1.sagemaker.aws
+notebook.eu-central-1.sagemaker.aws
+notebook.eu-central-2.sagemaker.aws
+notebook.eu-north-1.sagemaker.aws
+notebook.eu-south-1.sagemaker.aws
+notebook.eu-south-2.sagemaker.aws
+notebook.eu-west-1.sagemaker.aws
+notebook.eu-west-2.sagemaker.aws
+notebook.eu-west-3.sagemaker.aws
+notebook.il-central-1.sagemaker.aws
+notebook.me-central-1.sagemaker.aws
+notebook.me-south-1.sagemaker.aws
+notebook.sa-east-1.sagemaker.aws
+notebook.us-east-1.sagemaker.aws
+notebook-fips.us-east-1.sagemaker.aws
+notebook.us-east-2.sagemaker.aws
+notebook-fips.us-east-2.sagemaker.aws
+notebook.us-gov-east-1.sagemaker.aws
+notebook-fips.us-gov-east-1.sagemaker.aws
+notebook.us-gov-west-1.sagemaker.aws
+notebook-fips.us-gov-west-1.sagemaker.aws
+notebook.us-west-1.sagemaker.aws
+notebook.us-west-2.sagemaker.aws
+notebook-fips.us-west-2.sagemaker.aws
+notebook.cn-north-1.sagemaker.com.cn
+notebook.cn-northwest-1.sagemaker.com.cn
+
+// Amazon SageMaker Studio
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 057ee397-6bf8-4f20-b807-d7bc145ac980
+studio.af-south-1.sagemaker.aws
+studio.ap-east-1.sagemaker.aws
+studio.ap-northeast-1.sagemaker.aws
+studio.ap-northeast-2.sagemaker.aws
+studio.ap-northeast-3.sagemaker.aws
+studio.ap-south-1.sagemaker.aws
+studio.ap-southeast-1.sagemaker.aws
+studio.ap-southeast-2.sagemaker.aws
+studio.ap-southeast-3.sagemaker.aws
+studio.ca-central-1.sagemaker.aws
+studio.eu-central-1.sagemaker.aws
+studio.eu-north-1.sagemaker.aws
+studio.eu-south-1.sagemaker.aws
+studio.eu-west-1.sagemaker.aws
+studio.eu-west-2.sagemaker.aws
+studio.eu-west-3.sagemaker.aws
+studio.il-central-1.sagemaker.aws
+studio.me-central-1.sagemaker.aws
+studio.me-south-1.sagemaker.aws
+studio.sa-east-1.sagemaker.aws
+studio.us-east-1.sagemaker.aws
+studio.us-east-2.sagemaker.aws
+studio.us-gov-east-1.sagemaker.aws
+studio-fips.us-gov-east-1.sagemaker.aws
+studio.us-gov-west-1.sagemaker.aws
+studio-fips.us-gov-west-1.sagemaker.aws
+studio.us-west-1.sagemaker.aws
+studio.us-west-2.sagemaker.aws
+studio.cn-north-1.sagemaker.com.cn
+studio.cn-northwest-1.sagemaker.com.cn
 
 // Analytics on AWS
 // Submitted by AWS Security <psl-maintainers@amazon.com>
-// Reference: c02c3a80-f8a0-4fd2-b719-48ea8b7c28de
+// Reference: 955f9f40-a495-4e73-ae85-67b77ac9cadd
 analytics-gateway.ap-northeast-1.amazonaws.com
+analytics-gateway.ap-northeast-2.amazonaws.com
+analytics-gateway.ap-south-1.amazonaws.com
+analytics-gateway.ap-southeast-1.amazonaws.com
+analytics-gateway.ap-southeast-2.amazonaws.com
+analytics-gateway.eu-central-1.amazonaws.com
 analytics-gateway.eu-west-1.amazonaws.com
 analytics-gateway.us-east-1.amazonaws.com
 analytics-gateway.us-east-2.amazonaws.com
 analytics-gateway.us-west-2.amazonaws.com
 
+// AWS Amplify
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 5ecce854-c033-4fc4-a755-1a9916d9a9bb
+*.amplifyapp.com
+
+// AWS App Runner
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 6828c008-ba5d-442f-ade5-48da4e7c2316
+*.awsapprunner.com
+
 // AWS Cloud9
 // Submitted by: AWS Security <psl-maintainers@amazon.com>
 // Reference: 05c44955-977c-4b57-938a-f2af92733f9f
@@ -11493,25 +11947,33 @@ vfs.cloud9.us-west-2.amazonaws.com
 webview-assets.cloud9.us-west-2.amazonaws.com
 
 // AWS Elastic Beanstalk
-// Submitted by Luke Wells <psl-maintainers@amazon.com>
-// Reference: aa202394-43a0-4857-b245-8db04549137e
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: bb5a965c-dec3-4967-aa22-e306ad064797
 cn-north-1.eb.amazonaws.com.cn
 cn-northwest-1.eb.amazonaws.com.cn
 elasticbeanstalk.com
+af-south-1.elasticbeanstalk.com
+ap-east-1.elasticbeanstalk.com
 ap-northeast-1.elasticbeanstalk.com
 ap-northeast-2.elasticbeanstalk.com
 ap-northeast-3.elasticbeanstalk.com
 ap-south-1.elasticbeanstalk.com
 ap-southeast-1.elasticbeanstalk.com
 ap-southeast-2.elasticbeanstalk.com
+ap-southeast-3.elasticbeanstalk.com
 ca-central-1.elasticbeanstalk.com
 eu-central-1.elasticbeanstalk.com
+eu-north-1.elasticbeanstalk.com
+eu-south-1.elasticbeanstalk.com
 eu-west-1.elasticbeanstalk.com
 eu-west-2.elasticbeanstalk.com
 eu-west-3.elasticbeanstalk.com
+il-central-1.elasticbeanstalk.com
+me-south-1.elasticbeanstalk.com
 sa-east-1.elasticbeanstalk.com
 us-east-1.elasticbeanstalk.com
 us-east-2.elasticbeanstalk.com
+us-gov-east-1.elasticbeanstalk.com
 us-gov-west-1.elasticbeanstalk.com
 us-west-1.elasticbeanstalk.com
 us-west-2.elasticbeanstalk.com
@@ -12727,7 +13189,7 @@ shw.io
 // Submitted by Jonathan Rudenberg <jonathan@flynn.io>
 flynnhosting.net
 
-// Forgerock : https://www.forgerock.com
+// Forgerock : https://www.forgerock.com
 // Submitted by Roderick Parr <roderick.parr@forgerock.com>
 forgeblocks.com
 id.forgerock.io
@@ -12774,7 +13236,7 @@ freemyip.com
 // Submitted by Daniel A. Maierhofer <vorstand@funkfeuer.at>
 wien.funkfeuer.at
 
-// Futureweb OG : http://www.futureweb.at
+// Futureweb GmbH : https://www.futureweb.at
 // Submitted by Andreas Schnederle-Wagner <schnederle@futureweb.at>
 *.futurecms.at
 *.ex.futurecms.at
@@ -13619,6 +14081,10 @@ azurestaticapps.net
 1.azurestaticapps.net
 2.azurestaticapps.net
 3.azurestaticapps.net
+4.azurestaticapps.net
+5.azurestaticapps.net
+6.azurestaticapps.net
+7.azurestaticapps.net
 centralus.azurestaticapps.net
 eastasia.azurestaticapps.net
 eastus2.azurestaticapps.net
@@ -13699,6 +14165,9 @@ sa.ngrok.io
 us.ngrok.io
 ngrok.pizza
 
+// Nicolaus Copernicus University in Torun - MSK TORMAN 
(https://www.man.torun.pl)
+torun.pl
+
 // Nimbus Hosting Ltd. : https://www.nimbushosting.co.uk/
 // Submitted by Nicholas Ford <nick@nimbushosting.co.uk>
 nh-serv.co.uk
diff --git a/etc/refcards/Makefile b/etc/refcards/Makefile
index 9bc7564395a..c80c55a60cf 100644
--- a/etc/refcards/Makefile
+++ b/etc/refcards/Makefile
@@ -1,6 +1,6 @@
 ### Makefile for Emacs refcards
 
-## Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+## Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 ## This file is part of GNU Emacs.
 #
diff --git a/etc/refcards/README b/etc/refcards/README
index 7e3c7d65d6c..9521c9e0c2a 100644
--- a/etc/refcards/README
+++ b/etc/refcards/README
@@ -1,4 +1,4 @@
-Copyright (C) 2013-2023 Free Software Foundation, Inc.
+Copyright (C) 2013-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
@@ -77,7 +77,7 @@ it is reproduced here for convenience.
 
 File: gnus-logo.eps, gnus-logo.pdf
   Author: Luis Fernandes <elf@ee.ryerson.ca>
-  Copyright (C) 2001-2022 Free Software Foundation, Inc.
+  Copyright (C) 2001-2024 Free Software Foundation, Inc.
   License: GNU General Public License version 3 or later (see COPYING)
 
 
diff --git a/etc/refcards/calccard.tex b/etc/refcards/calccard.tex
index ce70b6271e5..1684240f9cf 100644
--- a/etc/refcards/calccard.tex
+++ b/etc/refcards/calccard.tex
@@ -20,7 +20,7 @@
 % Typical command to format:  tex calccard.tex
 % Typical command to print (3 cols):  dvips -t landscape calccard.dvi
 
-% Copyright (C) 1987, 1992, 2001--2023 Free Software Foundation, Inc.
+% Copyright (C) 1987, 1992, 2001--2024 Free Software Foundation, Inc.
 
 % This document is free software: you can redistribute it and/or modify
 % it under the terms of the GNU General Public License as published by
diff --git a/etc/refcards/cs-dired-ref.tex b/etc/refcards/cs-dired-ref.tex
index 6f865ca26c7..028df7ee33b 100644
--- a/etc/refcards/cs-dired-ref.tex
+++ b/etc/refcards/cs-dired-ref.tex
@@ -1,6 +1,6 @@
 % Reference Card for Dired -*- coding: utf-8 -*-
 
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
 
 % Author: Evgeny Roubinchtein <eroubinc@u.washington.edu>
 % Czech translation: Pavel Janík <Pavel@Janik.cz>, March 2001
diff --git a/etc/refcards/cs-refcard.tex b/etc/refcards/cs-refcard.tex
index a949b3d19d2..85383d0ac4b 100644
--- a/etc/refcards/cs-refcard.tex
+++ b/etc/refcards/cs-refcard.tex
@@ -1,6 +1,6 @@
 % Reference Card for GNU Emacs -*- coding: utf-8 -*-
 
-% Copyright (C) 1987, 1993, 1996--1997, 2001--2023 Free Software
+% Copyright (C) 1987, 1993, 1996--1997, 2001--2024 Free Software
 % Foundation, Inc.
 
 % Author: Stephen Gildea <stepheng+emacs@gildea.com>
diff --git a/etc/refcards/cs-survival.tex b/etc/refcards/cs-survival.tex
index 59885e92654..bd6206152de 100644
--- a/etc/refcards/cs-survival.tex
+++ b/etc/refcards/cs-survival.tex
@@ -1,6 +1,6 @@
 % Title:  GNU Emacs Survival Card -*- coding: utf-8 -*-
 
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
 
 % Author: Włodek Bzyl <matwb@univ.gda.pl>
 % Czech translation: Pavel Janík <Pavel@Janik.cz>, March 2001
diff --git a/etc/refcards/de-refcard.tex b/etc/refcards/de-refcard.tex
index e0088bc6c7c..da11ac4aa8e 100644
--- a/etc/refcards/de-refcard.tex
+++ b/etc/refcards/de-refcard.tex
@@ -1,6 +1,6 @@
 % Reference Card for GNU Emacs
 
-% Copyright (C) 1987, 1993, 1996, 2000--2023 Free Software Foundation,
+% Copyright (C) 1987, 1993, 1996, 2000--2024 Free Software Foundation,
 % Inc.
 
 % Author: Stephen Gildea <stepheng+emacs@gildea.com>
diff --git a/etc/refcards/dired-ref.tex b/etc/refcards/dired-ref.tex
index 3ebd422ed09..ffe1bbb50ff 100644
--- a/etc/refcards/dired-ref.tex
+++ b/etc/refcards/dired-ref.tex
@@ -1,6 +1,6 @@
 % Reference Card for Dired
 
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
 
 % Author: Evgeny Roubinchtein <eroubinc@u.washington.edu>
 
diff --git a/etc/refcards/emacsver.tex.in b/etc/refcards/emacsver.tex.in
index d1f15f18c85..31d1aa95eff 100644
--- a/etc/refcards/emacsver.tex.in
+++ b/etc/refcards/emacsver.tex.in
@@ -2,4 +2,4 @@
 \def\versionemacs{@majorversion@}           % major version of emacs
 %% This one should not be automatically updated;
 %% M-x set-copyright in admin.el handles it.
-\def\year{2023}                             % latest copyright year
+\def\year{2024}                             % latest copyright year
diff --git a/etc/refcards/fr-dired-ref.tex b/etc/refcards/fr-dired-ref.tex
index 9a0df984ad1..7f9d32901c7 100644
--- a/etc/refcards/fr-dired-ref.tex
+++ b/etc/refcards/fr-dired-ref.tex
@@ -1,6 +1,6 @@
 % Reference Card for Dired -*- coding: utf-8 -*-
 
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
 
 % Author: Evgeny Roubinchtein <eroubinc@u.washington.edu>
 % French translation: Eric Jacoboni
diff --git a/etc/refcards/fr-refcard.tex b/etc/refcards/fr-refcard.tex
index b7b70721f90..cce866d634d 100644
--- a/etc/refcards/fr-refcard.tex
+++ b/etc/refcards/fr-refcard.tex
@@ -1,6 +1,6 @@
 % Reference Card for GNU Emacs
 
-% Copyright (C) 1987, 1993, 1996--1997, 2001--2023 Free Software
+% Copyright (C) 1987, 1993, 1996--1997, 2001--2024 Free Software
 % Foundation, Inc.
 
 % Author: Stephen Gildea <stepheng+emacs@gildea.com>
diff --git a/etc/refcards/fr-survival.tex b/etc/refcards/fr-survival.tex
index abc49b61895..149268c20b0 100644
--- a/etc/refcards/fr-survival.tex
+++ b/etc/refcards/fr-survival.tex
@@ -1,7 +1,7 @@
 %&tex
 % Title:  GNU Emacs Survival Card
 
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
 
 % Author: Włodek Bzyl <matwb@univ.gda.pl>
 % French translation:  \'Eric Jacoboni <jaco@teaser.fr>, November 2001
diff --git a/etc/refcards/gnus-logo.eps b/etc/refcards/gnus-logo.eps
index 3bd785d6825..44a43ab65c9 100644
--- a/etc/refcards/gnus-logo.eps
+++ b/etc/refcards/gnus-logo.eps
@@ -1,5 +1,5 @@
 %!PS-Adobe-2.0 EPSF-2.0
-% Copyright (C) 2000-2023 Free Software Foundation, Inc.
+% Copyright (C) 2000-2024 Free Software Foundation, Inc.
 %
 % Author: Luis Fernandes <elf@ee.ryerson.ca>
 %
diff --git a/etc/refcards/gnus-refcard.tex b/etc/refcards/gnus-refcard.tex
index 1064af089a4..ee3fff2d3e3 100644
--- a/etc/refcards/gnus-refcard.tex
+++ b/etc/refcards/gnus-refcard.tex
@@ -120,7 +120,7 @@
 %% Gnus logo by Luis Fernandes.
 \newcommand{\Copyright}{%
   \begin{center}
-    Copyright \copyright\ 1995, 2000, 2002--2023 Free Software Foundation, 
Inc.\\*
+    Copyright \copyright\ 1995, 2000, 2002--2024 Free Software Foundation, 
Inc.\\*
   \end{center}
 
   Released under the terms of the GNU General Public License version 3 or 
later.
diff --git a/etc/refcards/orgcard.tex b/etc/refcards/orgcard.tex
index 4b73a544e80..705ab62d69d 100644
--- a/etc/refcards/orgcard.tex
+++ b/etc/refcards/orgcard.tex
@@ -1,5 +1,5 @@
 % Reference Card for Org Mode
-\def\orgversionnumber{9.6.11}
+\def\orgversionnumber{9.6.15}
 \def\versionyear{2023}          % latest update
 \input emacsver.tex
 
@@ -17,7 +17,7 @@
 \pdflayout=(0l)
 
 % Nothing else needs to be changed below this line.
-% Copyright (C) 1987, 1993, 1996--1997, 2001--2023 Free Software
+% Copyright (C) 1987, 1993, 1996--1997, 2001--2024 Free Software
 % Foundation, Inc.
 
 % This document is free software: you can redistribute it and/or modify
diff --git a/etc/refcards/pdflayout.sty b/etc/refcards/pdflayout.sty
index 284f4d74cc7..050dee2f9ca 100644
--- a/etc/refcards/pdflayout.sty
+++ b/etc/refcards/pdflayout.sty
@@ -1,4 +1,4 @@
-% Copyright (C) 2007-2023 Free Software Foundation, Inc.
+% Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 % This file is part of GNU Emacs.
 
diff --git a/etc/refcards/pl-refcard.tex b/etc/refcards/pl-refcard.tex
index 1fbdeab1be9..dabef6d91c8 100644
--- a/etc/refcards/pl-refcard.tex
+++ b/etc/refcards/pl-refcard.tex
@@ -1,7 +1,7 @@
 %&mex
 % Reference Card for GNU Emacs
 
-% Copyright (C) 1999, 2001--2023 Free Software Foundation, Inc.
+% Copyright (C) 1999, 2001--2024 Free Software Foundation, Inc.
 
 % Author: Stephen Gildea <stepheng+emacs@gildea.com>
 % Polish translation: Włodek Bzyl <matwb@univ.gda.pl>
diff --git a/etc/refcards/pt-br-refcard.tex b/etc/refcards/pt-br-refcard.tex
index 20f7e16d230..47064e7365d 100644
--- a/etc/refcards/pt-br-refcard.tex
+++ b/etc/refcards/pt-br-refcard.tex
@@ -1,6 +1,6 @@
 % Reference Card for GNU Emacs
 
-% Copyright (C) 1987, 1993, 1996--1997, 2002--2004, 2006--2023 Free
+% Copyright (C) 1987, 1993, 1996--1997, 2002--2004, 2006--2024 Free
 % Software Foundation, Inc.
 
 % Author: Stephen Gildea <stepheng+emacs@gildea.com>
diff --git a/etc/refcards/refcard.tex b/etc/refcards/refcard.tex
index ac802fdc4c3..8e8ee846291 100644
--- a/etc/refcards/refcard.tex
+++ b/etc/refcards/refcard.tex
@@ -1,6 +1,6 @@
 % Reference Card for GNU Emacs
 
-% Copyright (C) 1987, 1993, 1996--1997, 2001--2023 Free Software
+% Copyright (C) 1987, 1993, 1996--1997, 2001--2024 Free Software
 % Foundation, Inc.
 
 % Author: Stephen Gildea <stepheng+emacs@gildea.com>
diff --git a/etc/refcards/ru-refcard.tex b/etc/refcards/ru-refcard.tex
index 815a2db2f6d..0fc4363ec05 100644
--- a/etc/refcards/ru-refcard.tex
+++ b/etc/refcards/ru-refcard.tex
@@ -1,4 +1,4 @@
-% Copyright (C) 1997, 2002--2023 Free Software Foundation, Inc.
+% Copyright (C) 1997, 2002--2024 Free Software Foundation, Inc.
 
 % Author: Stephen Gildea <stepheng+emacs@gildea.com>
 % Russian translation: Alex Ott <alexott@gmail.com>
@@ -40,8 +40,8 @@
 \newlength{\ColThreeWidth}
 \setlength{\ColThreeWidth}{25mm}
 
-\newcommand{\versionemacs}[0]{30} % version of Emacs this is for
-\newcommand{\cyear}[0]{2023}       % copyright year
+\newcommand{\versionemacs}[0]{29} % version of Emacs this is for
+\newcommand{\cyear}[0]{2024}       % copyright year
 
 \newcommand\shortcopyrightnotice[0]{\vskip 1ex plus 2 fill
   \centerline{\footnotesize \copyright\ \cyear\ Free Software Foundation, Inc.
diff --git a/etc/refcards/sk-dired-ref.tex b/etc/refcards/sk-dired-ref.tex
index b353bd74404..cc15f3edf3b 100644
--- a/etc/refcards/sk-dired-ref.tex
+++ b/etc/refcards/sk-dired-ref.tex
@@ -1,6 +1,6 @@
 % Reference Card for Dired -*- coding: utf-8 -*-
 
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
 
 % Author: Evgeny Roubinchtein <eroubinc@u.washington.edu>
 % Czech translation: Pavel Janík <Pavel@Janik.cz>, March 2001
diff --git a/etc/refcards/sk-refcard.tex b/etc/refcards/sk-refcard.tex
index fe3d352c5b4..30dc61e9bc5 100644
--- a/etc/refcards/sk-refcard.tex
+++ b/etc/refcards/sk-refcard.tex
@@ -1,6 +1,6 @@
 % Reference Card for GNU Emacs -*- coding: utf-8 -*-
 
-% Copyright (C) 1987, 1993, 1996--1997, 2001--2023 Free Software
+% Copyright (C) 1987, 1993, 1996--1997, 2001--2024 Free Software
 % Foundation, Inc.
 
 % Author: Stephen Gildea <stepheng+emacs@gildea.com>
diff --git a/etc/refcards/sk-survival.tex b/etc/refcards/sk-survival.tex
index f7a9ee20722..5adc16ef667 100644
--- a/etc/refcards/sk-survival.tex
+++ b/etc/refcards/sk-survival.tex
@@ -1,6 +1,6 @@
 % Title:  GNU Emacs Survival Card -*- coding: utf-8 -*-
 
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
 
 % Author: Włodek Bzyl <matwb@univ.gda.pl>
 % Czech translation: Pavel Janík <Pavel@Janik.cz>, March 2001
diff --git a/etc/refcards/survival.tex b/etc/refcards/survival.tex
index cfa1be8b915..9f071b2aac3 100644
--- a/etc/refcards/survival.tex
+++ b/etc/refcards/survival.tex
@@ -1,7 +1,7 @@
 %&tex
 % Title:  GNU Emacs Survival Card
 
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
 
 % Author: Włodek Bzyl <matwb@univ.gda.pl>
 
diff --git a/etc/refcards/vipcard.tex b/etc/refcards/vipcard.tex
index d780a8b1ae8..7e5e0bdcb74 100644
--- a/etc/refcards/vipcard.tex
+++ b/etc/refcards/vipcard.tex
@@ -1,6 +1,6 @@
 % Quick Reference Card for VIP
 
-% Copyright (C) 1987, 2001--2023 Free Software Foundation, Inc.
+% Copyright (C) 1987, 2001--2024 Free Software Foundation, Inc.
 
 % Author: Masahiko Sato <ms@sail.stanford.edu>, 
<masahiko@sato.riec.tohoku.junet>
 
diff --git a/etc/refcards/viperCard.tex b/etc/refcards/viperCard.tex
index 8376179be09..3675c024a98 100644
--- a/etc/refcards/viperCard.tex
+++ b/etc/refcards/viperCard.tex
@@ -1,6 +1,6 @@
 % ViperCard -- The Reference Card for Viper under GNU Emacs
 
-% Copyright (C) 1995--1997, 2001--2023 Free Software Foundation, Inc.
+% Copyright (C) 1995--1997, 2001--2024 Free Software Foundation, Inc.
 
 % Author: Michael Kifer <kifer@cs.stonybrook.edu> (Viper)
 %      Aamod Sane <sane@cs.uiuc.edu> (VIP 4.3)
diff --git a/etc/schema/locate.rnc b/etc/schema/locate.rnc
index 10addaeaa33..bb80aa186e3 100644
--- a/etc/schema/locate.rnc
+++ b/etc/schema/locate.rnc
@@ -1,4 +1,4 @@
-# Copyright (C) 2003-2004, 2007-2023 Free Software Foundation, Inc.
+# Copyright (C) 2003-2004, 2007-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/etc/schema/relaxng.rnc b/etc/schema/relaxng.rnc
index 7489dd58c40..451548ac260 100644
--- a/etc/schema/relaxng.rnc
+++ b/etc/schema/relaxng.rnc
@@ -1,6 +1,6 @@
 # RELAX NG XML syntax expressed in RELAX NG Compact syntax.
 
-# Copyright (C) 2003-2004, 2007-2023 Free Software Foundation, Inc.
+# Copyright (C) 2003-2004, 2007-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/etc/schema/schemas.xml b/etc/schema/schemas.xml
index 8ac208790bf..f04bba849b4 100644
--- a/etc/schema/schemas.xml
+++ b/etc/schema/schemas.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<!-- Copyright (C) 2003-2004, 2007-2023 Free Software Foundation, Inc.
+<!-- Copyright (C) 2003-2004, 2007-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/etc/ses-example.ses b/etc/ses-example.ses
index 43793721d7c..ababd9f897f 100644
--- a/etc/ses-example.ses
+++ b/etc/ses-example.ses
@@ -205,7 +205,7 @@ Sales summary - Acme fundraising
 ;;; ses--symbolic-formulas: (("Eastern area") ("West-district") 
("North&South") ("Other"))
 ;;; End:
 
-;;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;;; COPYING PERMISSIONS:
 ;;; 
diff --git a/etc/srecode/c.srt b/etc/srecode/c.srt
index 398e9b559b3..73f3ae4a43e 100644
--- a/etc/srecode/c.srt
+++ b/etc/srecode/c.srt
@@ -1,6 +1,6 @@
 ;;; c.srt --- SRecode templates for c-mode
 
-;; Copyright (C) 2007-2010, 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2010, 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/cpp.srt b/etc/srecode/cpp.srt
index ad8618b51be..b2ef5c2ef3c 100644
--- a/etc/srecode/cpp.srt
+++ b/etc/srecode/cpp.srt
@@ -1,6 +1,6 @@
 ;;; cpp.srt --- SRecode templates for c++-mode
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/default.srt b/etc/srecode/default.srt
index d07f7abf562..dd14334f69c 100644
--- a/etc/srecode/default.srt
+++ b/etc/srecode/default.srt
@@ -1,6 +1,6 @@
 ;;; default.srt --- SRecode templates for srecode-template-mode
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/doc-cpp.srt b/etc/srecode/doc-cpp.srt
index ea2370e089d..2c43b734ed8 100644
--- a/etc/srecode/doc-cpp.srt
+++ b/etc/srecode/doc-cpp.srt
@@ -1,6 +1,6 @@
 ;; doc-c.srt --- SRecode templates for "document" applications
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/doc-default.srt b/etc/srecode/doc-default.srt
index cbaa599147d..54f78ac3966 100644
--- a/etc/srecode/doc-default.srt
+++ b/etc/srecode/doc-default.srt
@@ -1,6 +1,6 @@
 ;; doc-default.srt --- SRecode templates for "document" applications
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/doc-java.srt b/etc/srecode/doc-java.srt
index a1015572507..cf720316dcf 100644
--- a/etc/srecode/doc-java.srt
+++ b/etc/srecode/doc-java.srt
@@ -1,6 +1,6 @@
 ;; doc-java.srt --- SRecode templates for "document" applications
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/ede-autoconf.srt b/etc/srecode/ede-autoconf.srt
index 833cd6359ea..a31bcf387d1 100644
--- a/etc/srecode/ede-autoconf.srt
+++ b/etc/srecode/ede-autoconf.srt
@@ -1,6 +1,6 @@
 ;;; ede/templates/autoconf.srt --- Templates for autoconf used by EDE
 
-;; Copyright (C) 2010, 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010, 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/ede-make.srt b/etc/srecode/ede-make.srt
index 5f16dfc9baa..3d36f230e40 100644
--- a/etc/srecode/ede-make.srt
+++ b/etc/srecode/ede-make.srt
@@ -1,6 +1,6 @@
 ;; ede-make.srt --- SRecode templates for Makefiles used by EDE.
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/el.srt b/etc/srecode/el.srt
index 44c7aff6d7e..f765ae41926 100644
--- a/etc/srecode/el.srt
+++ b/etc/srecode/el.srt
@@ -1,6 +1,6 @@
 ;;; el.srt --- SRecode templates for Emacs Lisp mode
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/getset-cpp.srt b/etc/srecode/getset-cpp.srt
index f000680ab40..b193e8361ed 100644
--- a/etc/srecode/getset-cpp.srt
+++ b/etc/srecode/getset-cpp.srt
@@ -1,6 +1,6 @@
 ;;; getset-cpp.srt --- SRecode templates for C++ class getter/setters.
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/java.srt b/etc/srecode/java.srt
index 23210b85dfa..70ff87893fd 100644
--- a/etc/srecode/java.srt
+++ b/etc/srecode/java.srt
@@ -1,6 +1,6 @@
 ;; java.srt
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/make.srt b/etc/srecode/make.srt
index 8857de87b5a..1248f6e85a6 100644
--- a/etc/srecode/make.srt
+++ b/etc/srecode/make.srt
@@ -1,6 +1,6 @@
 ;; make.srt
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/proj-test.srt b/etc/srecode/proj-test.srt
index b8469542119..d1ff081d980 100644
--- a/etc/srecode/proj-test.srt
+++ b/etc/srecode/proj-test.srt
@@ -1,6 +1,6 @@
 ;; proj-test.srt --- SRecode template for testing project scoping.
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/template.srt b/etc/srecode/template.srt
index ded8ce3f705..ebc9f076495 100644
--- a/etc/srecode/template.srt
+++ b/etc/srecode/template.srt
@@ -1,6 +1,6 @@
 ;;; template.srt --- Templates for Semantic Recoders
 
-;; Copyright (C) 2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/test.srt b/etc/srecode/test.srt
index 127c4f47672..3fe877096e9 100644
--- a/etc/srecode/test.srt
+++ b/etc/srecode/test.srt
@@ -1,6 +1,6 @@
 ;; test.srt --- SRecode templates for testing
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/texi.srt b/etc/srecode/texi.srt
index 4a0a20a2267..427a0df4c05 100644
--- a/etc/srecode/texi.srt
+++ b/etc/srecode/texi.srt
@@ -1,6 +1,6 @@
 ;; texi.srt --- SRecode templates for Texinfo
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/srecode/wisent.srt b/etc/srecode/wisent.srt
index e42ca5c979c..a816495a23e 100644
--- a/etc/srecode/wisent.srt
+++ b/etc/srecode/wisent.srt
@@ -1,6 +1,6 @@
 ;; wisent.srt --- SRecode templates for Emacs/WISENT grammar files.
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/etc/themes/adwaita-theme.el b/etc/themes/adwaita-theme.el
index 108a9165961..cea8f85c081 100644
--- a/etc/themes/adwaita-theme.el
+++ b/etc/themes/adwaita-theme.el
@@ -1,6 +1,6 @@
 ;;; adwaita-theme.el --- Tango-based custom theme for faces  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: William Stevenson <yhvh2000@gmail.com>
 
diff --git a/etc/themes/deeper-blue-theme.el b/etc/themes/deeper-blue-theme.el
index 20da432c75a..ab769281eb6 100644
--- a/etc/themes/deeper-blue-theme.el
+++ b/etc/themes/deeper-blue-theme.el
@@ -1,6 +1,6 @@
 ;;; deeper-blue-theme.el --- Custom theme for faces  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Scott Frazer <frazer.scott@gmail.com>
 
diff --git a/etc/themes/dichromacy-theme.el b/etc/themes/dichromacy-theme.el
index c59fe8e0dfa..1e9802bd0ea 100644
--- a/etc/themes/dichromacy-theme.el
+++ b/etc/themes/dichromacy-theme.el
@@ -1,6 +1,6 @@
 ;;; dichromacy-theme.el --- color theme suitable for color-blind users  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Chong Yidong <cyd@stupidchicken>
 
diff --git a/etc/themes/leuven-dark-theme.el b/etc/themes/leuven-dark-theme.el
index 33a15945e71..e5427f77909 100644
--- a/etc/themes/leuven-dark-theme.el
+++ b/etc/themes/leuven-dark-theme.el
@@ -1,6 +1,6 @@
 ;;; leuven-dark-theme.el --- Awesome Emacs color theme on dark background  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")>
 ;; Contributor: Thibault Polge <(concat "thibault" at-sign "thb.lt")>
diff --git a/etc/themes/leuven-theme.el b/etc/themes/leuven-theme.el
index f7d454381d7..2f20dc39859 100644
--- a/etc/themes/leuven-theme.el
+++ b/etc/themes/leuven-theme.el
@@ -1,6 +1,6 @@
 ;;; leuven-theme.el --- Awesome Emacs color theme on white background  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")>
 ;; URL: https://github.com/fniessen/emacs-leuven-theme
diff --git a/etc/themes/light-blue-theme.el b/etc/themes/light-blue-theme.el
index f3850537617..ce98b53378e 100644
--- a/etc/themes/light-blue-theme.el
+++ b/etc/themes/light-blue-theme.el
@@ -1,6 +1,6 @@
 ;;; light-blue-theme.el --- Custom theme for faces  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Drew Adams <drew.adams@oracle.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/etc/themes/manoj-dark-theme.el b/etc/themes/manoj-dark-theme.el
index 26627a29c70..81dac1902f0 100644
--- a/etc/themes/manoj-dark-theme.el
+++ b/etc/themes/manoj-dark-theme.el
@@ -1,6 +1,6 @@
 ;;; manoj-dark-theme.el --- A dark theme from Manoj  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Manoj Srivastava <srivasta@ieee.org>
 ;; Keywords: lisp, faces
@@ -411,10 +411,10 @@ jarring angry fruit salad look to reduce eye fatigue."
 
  '(cursor ((t (:background "orchid"))))
  '(custom-button-face ((t (:background "lightgrey" :foreground "black"
-                                       :box '(:line-width 2 :style 
released-button)))))
+                                       :box (:line-width 2 :style 
released-button)))))
  '(custom-button-pressed-face ((t (:background "lightgrey"
                                                :foreground "black"
-                                               :box '(:line-width 2 :style 
pressed-button)))))
+                                               :box (:line-width 2 :style 
pressed-button)))))
  '(custom-changed-face ((t (:foreground "wheat" :background "blue"))))
  '(custom-comment-face ((t (:background "dim gray"))))
  '(custom-comment-tag-face ((t (:foreground "gray80"))))
@@ -430,7 +430,7 @@ jarring angry fruit salad look to reduce eye fatigue."
  '(custom-variable-button-face ((t (:bold t :underline t :weight bold
                                           :background "lightgrey"
                                           :foreground "black"
-                                          :box '(:line-width 2 :style 
released-button)))))
+                                          :box (:line-width 2 :style 
released-button)))))
  '(custom-variable-tag-face ((t (:bold t :foreground "light blue"
                                          :weight bold :height 1.2))))
 
@@ -586,15 +586,16 @@ jarring angry fruit salad look to reduce eye fatigue."
  '(match ((t (:background "RoyalBlue3"))))
  '(minibuffer-prompt ((t (:foreground "cyan"))))
  '(mode-line ((t (:background "grey75" :foreground "Blue"
-                  :box '(:line-width -1 :style released-button)
+                  :box (:line-width -1 :style released-button)
                   :height 0.9))))
  '(mode-line-buffer-id ((t (:background "grey65" :foreground "red"
                                         :bold t :weight bold :height 0.9))))
  '(mode-line-emphasis ((t (:bold t :weight bold))))
  '(mode-line-highlight ((t (:box (:line-width 2 :color "grey40"
-                                              :style released-button :height 
0.9)))))
+                                              :style released-button)
+                                 :height 0.9))))
  '(mode-line-inactive ((t (:background "grey30" :foreground "grey80"
-                                       :box '(:line-width -1 :color "grey40")
+                                       :box (:line-width -1 :color "grey40")
                                        :weight light :height 0.9))))
  '(mouse ((t (:background "OrangeRed"))))
 
diff --git a/etc/themes/misterioso-theme.el b/etc/themes/misterioso-theme.el
index 685951ce1a7..75693b59016 100644
--- a/etc/themes/misterioso-theme.el
+++ b/etc/themes/misterioso-theme.el
@@ -1,6 +1,6 @@
 ;;; misterioso-theme.el --- Custom face theme for Emacs  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Sebastian Hermida
 
diff --git a/etc/themes/modus-operandi-deuteranopia-theme.el 
b/etc/themes/modus-operandi-deuteranopia-theme.el
index 6a2105a1c4d..4d210b977eb 100644
--- a/etc/themes/modus-operandi-deuteranopia-theme.el
+++ b/etc/themes/modus-operandi-deuteranopia-theme.el
@@ -1,6 +1,6 @@
 ;;; modus-operandi-deuteranopia-theme.el --- Deuteranopia-optimized theme with 
a white background -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023  Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Protesilaos Stavrou <info@protesilaos.com>
 ;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
diff --git a/etc/themes/modus-operandi-theme.el 
b/etc/themes/modus-operandi-theme.el
index b9f9ee3834a..b41d5491c2e 100644
--- a/etc/themes/modus-operandi-theme.el
+++ b/etc/themes/modus-operandi-theme.el
@@ -1,6 +1,6 @@
 ;;; modus-operandi-theme.el --- Elegant, highly legible theme with a white 
background -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023  Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Protesilaos Stavrou <info@protesilaos.com>
 ;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
diff --git a/etc/themes/modus-operandi-tinted-theme.el 
b/etc/themes/modus-operandi-tinted-theme.el
index e66a030650c..7e0ad3d7ea8 100644
--- a/etc/themes/modus-operandi-tinted-theme.el
+++ b/etc/themes/modus-operandi-tinted-theme.el
@@ -1,6 +1,6 @@
-;;; modus-operandi-tinted-theme.el --- Elegant, highly legible theme with a 
light ochre background -*- lexical-binding:t -*-
+;;; modus-operandi-tinted-theme.el --- Elegant, highly legible theme with a 
light ocher background -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023  Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Protesilaos Stavrou <info@protesilaos.com>
 ;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
@@ -44,7 +44,7 @@
 
 ;;;###theme-autoload
   (deftheme modus-operandi-tinted
-    "Elegant, highly legible theme with a light ochre background.
+    "Elegant, highly legible theme with a light ocher background.
 Conforms with the highest legibility standard for color contrast
 between background and foreground in any given piece of text,
 which corresponds to a minimum contrast in relative luminance of
diff --git a/etc/themes/modus-operandi-tritanopia-theme.el 
b/etc/themes/modus-operandi-tritanopia-theme.el
index b7e9aa99748..968a6526ca3 100644
--- a/etc/themes/modus-operandi-tritanopia-theme.el
+++ b/etc/themes/modus-operandi-tritanopia-theme.el
@@ -1,6 +1,6 @@
 ;;; modus-operandi-tritanopia-theme.el --- Tritanopia-optimized theme with a 
white background -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023  Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Protesilaos Stavrou <info@protesilaos.com>
 ;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
diff --git a/etc/themes/modus-themes.el b/etc/themes/modus-themes.el
index 34130a05515..44f25182a30 100644
--- a/etc/themes/modus-themes.el
+++ b/etc/themes/modus-themes.el
@@ -1,6 +1,6 @@
 ;;; modus-themes.el --- Elegant, highly legible and customizable themes -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023  Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Protesilaos Stavrou <info@protesilaos.com>
 ;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
@@ -1535,7 +1535,7 @@ color that is combined with FG-FOR-BG."
           :foreground fg
           :weight
           ;; If we have `bold' specifically, we inherit the face of
-          ;; the same name.  This allows the user to customise that
+          ;; the same name.  This allows the user to customize that
           ;; face, such as to change its font family.
           (if (and weight (not (eq weight 'bold)))
               weight
diff --git a/etc/themes/modus-vivendi-deuteranopia-theme.el 
b/etc/themes/modus-vivendi-deuteranopia-theme.el
index 6de293ad5bc..62715e20e51 100644
--- a/etc/themes/modus-vivendi-deuteranopia-theme.el
+++ b/etc/themes/modus-vivendi-deuteranopia-theme.el
@@ -1,6 +1,6 @@
 ;;; modus-vivendi-deuteranopia-theme.el --- Deuteranopia-optimized theme with 
a black background -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023  Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Protesilaos Stavrou <info@protesilaos.com>
 ;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
diff --git a/etc/themes/modus-vivendi-theme.el 
b/etc/themes/modus-vivendi-theme.el
index b193a96524f..238484206bb 100644
--- a/etc/themes/modus-vivendi-theme.el
+++ b/etc/themes/modus-vivendi-theme.el
@@ -1,6 +1,6 @@
 ;;; modus-vivendi-theme.el --- Elegant, highly legible theme with a black 
background -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023  Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Protesilaos Stavrou <info@protesilaos.com>
 ;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
diff --git a/etc/themes/modus-vivendi-tinted-theme.el 
b/etc/themes/modus-vivendi-tinted-theme.el
index bf72f88d8e0..025257ef01c 100644
--- a/etc/themes/modus-vivendi-tinted-theme.el
+++ b/etc/themes/modus-vivendi-tinted-theme.el
@@ -1,6 +1,6 @@
 ;;; modus-vivendi-tinted-theme.el --- Elegant, highly legible theme with a 
night sky background -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023  Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Protesilaos Stavrou <info@protesilaos.com>
 ;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
diff --git a/etc/themes/modus-vivendi-tritanopia-theme.el 
b/etc/themes/modus-vivendi-tritanopia-theme.el
index d808d0250fc..bfd6d63b844 100644
--- a/etc/themes/modus-vivendi-tritanopia-theme.el
+++ b/etc/themes/modus-vivendi-tritanopia-theme.el
@@ -1,6 +1,6 @@
 ;;; modus-vivendi-tritanopia-theme.el --- Tritanopia-optimized theme with a 
black background -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023  Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Protesilaos Stavrou <info@protesilaos.com>
 ;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
diff --git a/etc/themes/tango-dark-theme.el b/etc/themes/tango-dark-theme.el
index e79c14d734f..a744ec2fc32 100644
--- a/etc/themes/tango-dark-theme.el
+++ b/etc/themes/tango-dark-theme.el
@@ -1,6 +1,6 @@
 ;;; tango-dark-theme.el --- Tango-based custom theme for faces  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Authors: Chong Yidong <cyd@stupidchicken>
 ;;          Jan Moringen <jan.moringen@uni-bielefeld.de>
diff --git a/etc/themes/tango-theme.el b/etc/themes/tango-theme.el
index 4fecb60bc6e..63f869d281f 100644
--- a/etc/themes/tango-theme.el
+++ b/etc/themes/tango-theme.el
@@ -1,6 +1,6 @@
 ;;; tango-theme.el --- Tango-based custom theme for faces  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Authors: Chong Yidong <cyd@stupidchicken>
 ;;          Jan Moringen <jan.moringen@uni-bielefeld.de>
diff --git a/etc/themes/tsdh-dark-theme.el b/etc/themes/tsdh-dark-theme.el
index 2451ee9666d..213cd8edb70 100644
--- a/etc/themes/tsdh-dark-theme.el
+++ b/etc/themes/tsdh-dark-theme.el
@@ -1,6 +1,6 @@
 ;;; tsdh-dark-theme.el --- Tassilo's dark custom theme  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/etc/themes/tsdh-light-theme.el b/etc/themes/tsdh-light-theme.el
index 4d11f5cc32f..5314f3c1b82 100644
--- a/etc/themes/tsdh-light-theme.el
+++ b/etc/themes/tsdh-light-theme.el
@@ -1,6 +1,6 @@
 ;;; tsdh-light-theme.el --- Tassilo's light custom theme  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/etc/themes/wheatgrass-theme.el b/etc/themes/wheatgrass-theme.el
index 812fd623f1a..9e785596c10 100644
--- a/etc/themes/wheatgrass-theme.el
+++ b/etc/themes/wheatgrass-theme.el
@@ -1,6 +1,6 @@
 ;;; wheatgrass-theme.el --- custom theme for faces  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/etc/themes/whiteboard-theme.el b/etc/themes/whiteboard-theme.el
index b52996c24c0..2db11fcb4b8 100644
--- a/etc/themes/whiteboard-theme.el
+++ b/etc/themes/whiteboard-theme.el
@@ -1,6 +1,6 @@
 ;;; whiteboard-theme.el --- Custom theme for faces  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Scott Frazer <frazer.scott@gmail.com>
 
diff --git a/etc/themes/wombat-theme.el b/etc/themes/wombat-theme.el
index 5b8b4d19907..3399d637811 100644
--- a/etc/themes/wombat-theme.el
+++ b/etc/themes/wombat-theme.el
@@ -1,6 +1,6 @@
 ;;; wombat-theme.el --- Custom face theme for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Kristoffer Grönlund <krig@koru.se>
 
diff --git a/etc/tutorials/TUTORIAL b/etc/tutorials/TUTORIAL
index 4e6d7b9b287..4718e0d9430 100644
--- a/etc/tutorials/TUTORIAL
+++ b/etc/tutorials/TUTORIAL
@@ -1131,7 +1131,7 @@ starting with the one written by Stuart Cracraft for the 
original Emacs.
 This version of the tutorial is a part of GNU Emacs.  It is copyrighted
 and comes with permission to distribute copies on certain conditions:
 
-  Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation,
+  Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation,
   Inc.
 
   This file is part of GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.bg b/etc/tutorials/TUTORIAL.bg
index 60c1e07272d..c5b8c6dd983 100644
--- a/etc/tutorials/TUTORIAL.bg
+++ b/etc/tutorials/TUTORIAL.bg
@@ -1162,7 +1162,7 @@ Dired ви позволява да гледате списъка от файло
 This version of the tutorial, like GNU Emacs, is copyrighted, and
 comes with permission to distribute copies on certain conditions:
 
-  Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation,
+  Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation,
   Inc.
 
   This file is part of GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.cn b/etc/tutorials/TUTORIAL.cn
index e4c90102f53..02d9aadd318 100644
--- a/etc/tutorials/TUTORIAL.cn
+++ b/etc/tutorials/TUTORIAL.cn
@@ -1026,7 +1026,7 @@ starting with the one written by Stuart Cracraft for the 
original Emacs.
 This version of the tutorial is a part of GNU Emacs.  It is copyrighted
 and comes with permission to distribute copies on certain conditions:
 
-  Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation,
+  Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation,
   Inc.
 
   This file is part of GNU Emacs.
@@ -1055,7 +1055,7 @@ using, writing, and sharing free software!
 
 本篇指南是 GNU Emacs 的一部分,并允许在下列条件的约束下发行其拷贝:
 
-   Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation,
+   Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation,
    Inc.
 
    本文件为 GNU Emacs 的一部分。
diff --git a/etc/tutorials/TUTORIAL.cs b/etc/tutorials/TUTORIAL.cs
index be3b92f8ffd..b2a709e6415 100644
--- a/etc/tutorials/TUTORIAL.cs
+++ b/etc/tutorials/TUTORIAL.cs
@@ -1015,7 +1015,7 @@ tutoriálem napsaným Stuartem Cracraftem pro původní Emacs.
 Tato verze tutoriálu je, podobně jako GNU Emacs, chráněna copyrightem a
 je šířena se svolením distribuovat kopie za jistých podmínek:
 
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
 
    Každému je zaručeno právo vytvářet a distribuovat přesné kopie tohoto
    dokumentu tak, jak jej obdržel, na jakémkoliv médiu, s tím, že bude
diff --git a/etc/tutorials/TUTORIAL.de b/etc/tutorials/TUTORIAL.de
index 03716dd7de4..c5a60185a70 100644
--- a/etc/tutorials/TUTORIAL.de
+++ b/etc/tutorials/TUTORIAL.de
@@ -1488,7 +1488,7 @@ Beachten Sie bitte, dass im Zweifelsfalle das englische 
Original
 dieser Urheberrechtsnotiz gültig ist (zu finden in der Datei
 TUTORIAL).
 
-   Copyright (C) 1985, 1996-1997, 2001-2023 Free Software Foundation,
+   Copyright (C) 1985, 1996-1997, 2001-2024 Free Software Foundation,
    Inc.
 
    Diese Datei ist ein Bestandteil von GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.el_GR b/etc/tutorials/TUTORIAL.el_GR
index 33b87cb99e9..577010dae8b 100644
--- a/etc/tutorials/TUTORIAL.el_GR
+++ b/etc/tutorials/TUTORIAL.el_GR
@@ -1239,7 +1239,7 @@ list-packages.  Στη σχετική λίστα, μπορείς να εγκατ
 πνευματικά δικαιώματα και δίνεται με την άδεια διανομής αντιγράφων υπό
 κάποιους όρους.
 
-  Πνευματικά Δικαιώματα (C) 1985, 1996, 1998, 2001-2023 Free Software
+  Πνευματικά Δικαιώματα (C) 1985, 1996, 1998, 2001-2024 Free Software
   Foundation, Inc.
 
   Αυτό το αρχείο είναι μέρος του GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.eo b/etc/tutorials/TUTORIAL.eo
index a92edf267fe..01423a04f50 100644
--- a/etc/tutorials/TUTORIAL.eo
+++ b/etc/tutorials/TUTORIAL.eo
@@ -1081,7 +1081,7 @@ la dosiero verkita de Stuart Cracraft por la originala 
Emakso.
 kopirajton, kaj venas kun permeso por disdoni kopiojn se certaj
 kondiĉoj estas observataj:
 
-   Copyright (C) 1985, 1999, 2001-2002, 2005, 2007-2023 Free Software
+   Copyright (C) 1985, 1999, 2001-2002, 2005, 2007-2024 Free Software
    Foundation, Inc.
 
    Ĉi tiu dosiero estas parto de "GNU Emacs".
diff --git a/etc/tutorials/TUTORIAL.es b/etc/tutorials/TUTORIAL.es
index b0d176d27cc..86944bf341e 100644
--- a/etc/tutorials/TUTORIAL.es
+++ b/etc/tutorials/TUTORIAL.es
@@ -1204,7 +1204,7 @@ Por favor, en caso de duda, solo es válido el original en 
inglés de la
 siguiente nota de derechos de reproducción (que puede encontrar en el
 archivo TUTORIAL).
 
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
 
    Se permite a cualquiera hacer o distribuir copias literales de este
    documento como se recibe, en cualquier medio, siempre que la nota
diff --git a/etc/tutorials/TUTORIAL.fa b/etc/tutorials/TUTORIAL.fa
index 1333b47cae2..e2afcbe638d 100644
--- a/etc/tutorials/TUTORIAL.fa
+++ b/etc/tutorials/TUTORIAL.fa
@@ -1131,7 +1131,8 @@ Stuart Cracraft  سر چشمه گرفت.
 این نسخه از آموزش بخشی از GNU Emacs است. دارای حق چاپ است
 و با مجوز برای توزیع کپی در شرایط خاص همراه است:
 
-  Copyright (C) 1985, 1996, 1998, 2001-2022 Free Software Foundation, Inc.
+  Copyright (C) 1985, 1996, 1998, 2001-2022, 2024 Free Software
+  Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/etc/tutorials/TUTORIAL.fr b/etc/tutorials/TUTORIAL.fr
index 1e4260acf0a..55a00f43e86 100644
--- a/etc/tutorials/TUTORIAL.fr
+++ b/etc/tutorials/TUTORIAL.fr
@@ -1202,7 +1202,7 @@ Cette version du didacticiel, comme GNU Emacs, est placée 
sous
 droit d'auteur, et vous pouvez en distribuer des copies sous certaines
 conditions :
 
-Copyright (C) 1985, 1996, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 2001-2024 Free Software Foundation, Inc.
 
    Chacun peut créer ou distribuer des copies de ce document tel qu'il
    l'a reçu, sur n'importe quel support, pourvu que la note de
diff --git a/etc/tutorials/TUTORIAL.he b/etc/tutorials/TUTORIAL.he
index 4257f94edcf..0a4222a6fdc 100644
--- a/etc/tutorials/TUTORIAL.he
+++ b/etc/tutorials/TUTORIAL.he
@@ -1015,7 +1015,7 @@ find-file.
 גירסה זו של השיעור הינה חלק מחבילת GNU Emacs. היא מוגנת בזכויות יוצרים
 וניתנת להעתקה והפצת עותקים בתנאים מסויימים כדלקמן:
 
-                       Copyright (C) 2010-2023 Free Software Foundation, Inc.
+                       Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ‏GNU Emacs הינו תכנה חפשית; זכותכם להפיצו ו\או לשנותו בכפוף לתנאי
 הרשיון GNU General Public License, כפי שהוא יוצא לאור ע״י Free
diff --git a/etc/tutorials/TUTORIAL.it b/etc/tutorials/TUTORIAL.it
index f97446d01c6..0baa54a40ad 100644
--- a/etc/tutorials/TUTORIAL.it
+++ b/etc/tutorials/TUTORIAL.it
@@ -1219,7 +1219,7 @@ distribuito con il permesso di farne copie a determinate 
condizioni:
    indicativo, restando comunque inteso il fatto che è quella
    originale a fare fede.
 
-Copyright (C) 2003-2023 Free Software Foundation, Inc.
+Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
    È permesso a chiunque copiare e distribuire attraverso ogni mezzo
    copie fedeli di questo documento così come viene ricevuto, a
diff --git a/etc/tutorials/TUTORIAL.ja b/etc/tutorials/TUTORIAL.ja
index eb77faf0cf2..7f18e251a0c 100644
--- a/etc/tutorials/TUTORIAL.ja
+++ b/etc/tutorials/TUTORIAL.ja
@@ -1062,7 +1062,7 @@ starting with the one written by Stuart Cracraft for the 
original Emacs.
 This version of the tutorial, like GNU Emacs, is copyrighted, and
 comes with permission to distribute copies on certain conditions:
 
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
 
    Permission is granted to anyone to make or distribute verbatim copies
    of this document as received, in any medium, provided that the
diff --git a/etc/tutorials/TUTORIAL.ko b/etc/tutorials/TUTORIAL.ko
index 8252a91e179..a8c97e8db9c 100644
--- a/etc/tutorials/TUTORIAL.ko
+++ b/etc/tutorials/TUTORIAL.ko
@@ -981,7 +981,7 @@ C-x C-s와 (META쇠나 EDIT쇠 혹은 교체쇠가 있으면) <ESC>v와 같은 
 GNU 이맥스와 같이 이 지침서 판은 저작권이 있으며 특정한 조건을 만족할
 때에 복사본을 배포할 수 있는 허가를 갖고 나온 것이다:
 
-Copyright (C) 1985, 1996, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 2001-2024 Free Software Foundation, Inc.
 
    이 문서는 이 저작권 공고와 허용 공고가 그대로 유지되고, 배포자가
    수취자에게 이 공고에 따라 허용되는 것처럼 또 재분배하는 것을
diff --git a/etc/tutorials/TUTORIAL.nl b/etc/tutorials/TUTORIAL.nl
index ce777e29e4f..73acaba73e4 100644
--- a/etc/tutorials/TUTORIAL.nl
+++ b/etc/tutorials/TUTORIAL.nl
@@ -1209,7 +1209,7 @@ Deze versie van de inleiding is onderdeel van GNU Emacs.  
Het valt
 onder copyright.  Je mag deze inleiding verspreiden onder bepaalde
 voorwaarden:
 
-  Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation,
+  Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation,
   Inc.
 
   Dit bestand is onderdeel van GNU Emacs.
@@ -1239,7 +1239,7 @@ Engels origineel van de copyrightmelding en condities:
 This version of the tutorial is a part of GNU Emacs.  It is copyrighted
 and comes with permission to distribute copies on certain conditions:
 
-  Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/etc/tutorials/TUTORIAL.pl b/etc/tutorials/TUTORIAL.pl
index 388e4cf692b..462fdcd835e 100644
--- a/etc/tutorials/TUTORIAL.pl
+++ b/etc/tutorials/TUTORIAL.pl
@@ -218,17 +218,11 @@ Na przykład C-u 4 C-v przewija ekran o 4 linie.
 To powinno było przewinąć ekran do góry o 8 linii. Jeśli chciałbyś
 przewinąć ekran w dół, to powinieneś podać argument przed poleceniem M-v.
 
-Jeśli pracujesz w systemie z okienkowym trybem graficznym, jak X11
-lub MS-Windows, to prawdopodobnie po lewej stronie okna Emacsa znajduje
-się prostokątny obszar nazywany po angielsku "scrollbar", a po polsku
-suwakiem. Za jego pomocą możesz przewijać tekst, używając do tego myszy.
+W środowisku graficznym, takim jak X lub Microsoft Windows, po jednej
+stronie okna Emacs znajdzie się długi prostokątny obszar, nazywany
+prowadnicą przewijacza.  Można przewijać treść, stukając myszą w prowadnicę.
 
->> Spróbuj nacisnąć środkowy klawisz myszy u góry podświetlonego
-   obszaru na suwaku. To powinno przewinąć tekst do miejsca
-   określonego przez wysokość, na której nacisnąłeś klawisz myszy.
-
->> Przesuń mysz do miejsca oddalonego od górnego końca suwaka o mniej
-   więcej trzy linie i naciśnij lewy klawisz myszy kilka razy.
+Można również używać kółeczka myszy do przewijania, jeśli jest dostępne.
 
 
 * GDY EMACS JEST ZABLOKOWANY
@@ -1209,7 +1203,7 @@ z pomocą Ryszarda Kubiaka i Janusza S. Bienia 
<jsbien@mail.uw.edu.pl>.
 Ta wersja samouczka, podobnie jak GNU Emacs, jest chroniona prawem
 autorskim, ale wolno ją kopiować pod następującymi warunkami:
 
-Copyright (C) 1985, 1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1994, 2001-2024 Free Software Foundation, Inc.
 
 Zezwala się na wykonywanie lub rozpowszechnianie
 wiernych kopii tego dokumentu w otrzymanej formie, na dowolnym
diff --git a/etc/tutorials/TUTORIAL.pt_BR b/etc/tutorials/TUTORIAL.pt_BR
index a7d6dcb9204..1afc82748d4 100644
--- a/etc/tutorials/TUTORIAL.pt_BR
+++ b/etc/tutorials/TUTORIAL.pt_BR
@@ -1056,7 +1056,7 @@ Essa versão do tutorial foi originalmente traduzida por 
Marcelo Toledo
 <marcelo@gnu.org> e como o GNU Emacs, tem um copyright, e vem
 com uma permissão de distribuição de cópias nas seguintes condições:
 
-Copyright (C) 2004-2023 Free Software Foundation, Inc.
+Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
    Permissão é garantida a qualquer um para fazer ou distribuir cópias
    integrais deste documento como recebido, em qualquer meio, deixando
diff --git a/etc/tutorials/TUTORIAL.ro b/etc/tutorials/TUTORIAL.ro
index ee3a1426239..849374ee706 100644
--- a/etc/tutorials/TUTORIAL.ro
+++ b/etc/tutorials/TUTORIAL.ro
@@ -4,7 +4,7 @@ Mulţumiri Aidei Hulubei <aida@chang.pub.ro> pentru corecturi şi 
sugestii.
 
 Această versiune a fost produsă plecând de la versiunea în limba
 engleză, care este
-Copyright (c) 1985, 2013-2023 Free Software Foundation, Inc.
+Copyright (c) 1985, 2013-2024 Free Software Foundation, Inc.
 
 Citiţi acum versiunea românească a tutorialului de Emacs.
 
@@ -1082,7 +1082,7 @@ continuare noţita de copyright originală în limba engleză.
 This version of the tutorial, like GNU Emacs, is copyrighted, and
 comes with permission to distribute copies on certain conditions:
 
-Copyright (C) 1998, 2001-2022 Free Software Foundation, Inc.
+Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 
    Permission is granted to anyone to make or distribute verbatim copies
    of this document as received, in any medium, provided that the
diff --git a/etc/tutorials/TUTORIAL.ru b/etc/tutorials/TUTORIAL.ru
index 8018b36cc38..a5c76321acc 100644
--- a/etc/tutorials/TUTORIAL.ru
+++ b/etc/tutorials/TUTORIAL.ru
@@ -1105,7 +1105,7 @@ Dired позволяет вам отображать список файлов 
 (copyrighted) и приходит с ограничениями распространения копий со
 следующими соглашениями:
 
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
 
    Permission is granted to anyone to make or distribute verbatim copies
    of this document as received, in any medium, provided that the
diff --git a/etc/tutorials/TUTORIAL.sk b/etc/tutorials/TUTORIAL.sk
index e5033a822dc..2186f1716de 100644
--- a/etc/tutorials/TUTORIAL.sk
+++ b/etc/tutorials/TUTORIAL.sk
@@ -1074,7 +1074,7 @@ tútorialom napísaným Stuartom Cracraftom pre pôvodný 
Emacs.
 Táto verzia tútorialu je, podobne ako GNU Emacs, chránená copyrightom
 a je šírená s povolením distribuovať kópie za istých podmienok:
 
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
 
    Každému je zaručené právo vytvárať a distribuovať presné kópie tohto
    dokumentu tak, ako ho dostal, na akomkoľvek médiu, s tým, že bude
diff --git a/etc/tutorials/TUTORIAL.sl b/etc/tutorials/TUTORIAL.sl
index ae594b99332..28dfdcb71fd 100644
--- a/etc/tutorials/TUTORIAL.sl
+++ b/etc/tutorials/TUTORIAL.sl
@@ -1119,7 +1119,7 @@ Emacs. V slovenščino ga je prevedel Primož Peterlin.
 To besedilo, kot sam GNU Emacs, je avtorsko delo, in njegovo
 razmnoževanje in razširjanje je dovoljeno pod naslednjimi pogoji:
 
-Copyright © 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright © 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
 
   Ta datoteka je del paketa GNU Emacs.
 
diff --git a/etc/tutorials/TUTORIAL.sv b/etc/tutorials/TUTORIAL.sv
index 9b38fa0c6fe..f13799ad369 100644
--- a/etc/tutorials/TUTORIAL.sv
+++ b/etc/tutorials/TUTORIAL.sv
@@ -1153,7 +1153,7 @@ Lidell översatte den till svenska.
 This version of the tutorial, like GNU Emacs, is copyrighted, and
 comes with permission to distribute copies on certain conditions:
 
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/etc/tutorials/TUTORIAL.th b/etc/tutorials/TUTORIAL.th
index 9c2ee1e5b90..3913791b8b2 100644
--- a/etc/tutorials/TUTORIAL.th
+++ b/etc/tutorials/TUTORIAL.th
@@ -964,7 +964,7 @@ starting with the one written by Stuart Cracraft for the 
original Emacs.
 This version of the tutorial, like GNU Emacs, is copyrighted, and
 comes with permission to distribute copies on certain conditions:
 
-Copyright (C) 1985, 1996, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 2001-2024 Free Software Foundation, Inc.
 
    Permission is granted to anyone to make or distribute verbatim copies
    of this document as received, in any medium, provided that the
diff --git a/etc/tutorials/TUTORIAL.uk b/etc/tutorials/TUTORIAL.uk
index 6d4772cf0ad..c09ba7de7d6 100644
--- a/etc/tutorials/TUTORIAL.uk
+++ b/etc/tutorials/TUTORIAL.uk
@@ -1126,7 +1126,7 @@ list-packages.  З'явиться екран, за допомогою якого
 Ця версія посібника — складник GNU Emacs.  Її захищено авторським
 правом.  Розповсюджувати копії дозволено за певних умов:
 
-  Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation,
+  Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation,
   Inc.  (Фонд вільного програмного забезпечення, Inc.)
 
   Цей файл — складник GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.zh b/etc/tutorials/TUTORIAL.zh
index f938ed693d8..15698cfb688 100644
--- a/etc/tutorials/TUTORIAL.zh
+++ b/etc/tutorials/TUTORIAL.zh
@@ -1049,7 +1049,7 @@ issue here>」。
 這個版本的快速指南和 GNU Emacs 一樣都是版權化的,並且允許在某些條件下
 散佈其拷貝:
 
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
 
    Permission is granted to anyone to make or distribute verbatim copies
    of this document as received, in any medium, provided that the
diff --git a/etc/w32-feature.el b/etc/w32-feature.el
index 97a7a5f729d..8d36e32e0fb 100644
--- a/etc/w32-feature.el
+++ b/etc/w32-feature.el
@@ -1,6 +1,6 @@
 ;;; w32-feature.el --- Check Availability of Emacs Features  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Phillip Lord <phillip.lord@russet.org.uk>
 
diff --git a/exec/Makefile.in b/exec/Makefile.in
index 00e59771337..36f0c0c74a9 100644
--- a/exec/Makefile.in
+++ b/exec/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
@@ -131,9 +131,12 @@ maintainer-clean: distclean
 ### the coding standards seem to come from.  It's like distclean, but
 ### it deletes backup and autosave files too.
 
+# config.* and install-sh are copied from build-aux in the root of
+# this repository by autogen.sh.
 extraclean: maintainer-clean
        -rm -f config-tmp-* $(srcdir)/aclocal.m4 $(srcdir)/configure \
-         $(srcdir)/src/config.in
+         $(srcdir)/src/config.in $(srcdir)/config.guess             \
+         $(srcdir)/config.sub $(srcdir)/install-sh
        -[ "$(srcdir)" = "." ] || \
          find $(srcdir) '(' -name '*~' -o -name '#*' ')' $(FIND_DELETE)
        -find . '(' -name '*~' -o -name '#*' ')' $(FIND_DELETE)
diff --git a/exec/config-mips.m4.in b/exec/config-mips.m4.in
index 72632765bd0..67a14e36b61 100644
--- a/exec/config-mips.m4.in
+++ b/exec/config-mips.m4.in
@@ -1,6 +1,6 @@
 dnl  Assembler templates for MIPS computers.
 dnl
-dnl Copyright (C) 2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2023-2024 Free Software Foundation, Inc.
 dnl
 dnl  This file is part of GNU Emacs.
 dnl
diff --git a/exec/config.guess b/exec/config.guess
deleted file mode 100755
index b187213930f..00000000000
--- a/exec/config.guess
+++ /dev/null
@@ -1,1803 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-#   Copyright 1992-2023 Free Software Foundation, Inc.
-
-# shellcheck disable=SC2006,SC2268 # see below for rationale
-
-timestamp='2023-07-20'
-
-# 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
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program 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 this program; if not, see <https://www.gnu.org/licenses/>.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that
-# program.  This Exception is an additional permission under section 7
-# of the GNU General Public License, version 3 ("GPLv3").
-#
-# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
-#
-# You can get the latest version of this script from:
-# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
-#
-# Please send patches to <config-patches@gnu.org>.
-
-
-# The "shellcheck disable" line above the timestamp inhibits complaints
-# about features and limitations of the classic Bourne shell that were
-# superseded or lifted in POSIX.  However, this script identifies a wide
-# variety of pre-POSIX systems that do not have POSIX shells at all, and
-# even some reasonably current systems (Solaris 10 as case-in-point) still
-# have a pre-POSIX /bin/sh.
-
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION]
-
-Output the configuration name of the system '$me' is run on.
-
-Options:
-  -h, --help         print this help, then exit
-  -t, --time-stamp   print date of last modification, then exit
-  -v, --version      print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.guess ($timestamp)
-
-Originally written by Per Bothner.
-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."
-
-help="
-Try '$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
-  case $1 in
-    --time-stamp | --time* | -t )
-       echo "$timestamp" ; exit ;;
-    --version | -v )
-       echo "$version" ; exit ;;
-    --help | --h* | -h )
-       echo "$usage"; exit ;;
-    -- )     # Stop option processing
-       shift; break ;;
-    - )        # Use stdin as input.
-       break ;;
-    -* )
-       echo "$me: invalid option $1$help" >&2
-       exit 1 ;;
-    * )
-       break ;;
-  esac
-done
-
-if test $# != 0; then
-  echo "$me: too many arguments$help" >&2
-  exit 1
-fi
-
-# Just in case it came from the environment.
-GUESS=
-
-# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
-# compiler to aid in system detection is discouraged as it requires
-# temporary files to be created and, as you can see below, it is a
-# headache to deal with in a portable fashion.
-
-# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still
-# use 'HOST_CC' if defined, but it is deprecated.
-
-# Portable tmp directory creation inspired by the Autoconf team.
-
-tmp=
-# shellcheck disable=SC2172
-trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
-
-set_cc_for_build() {
-    # prevent multiple calls if $tmp is already set
-    test "$tmp" && return 0
-    : "${TMPDIR=/tmp}"
-    # shellcheck disable=SC2039,SC3028
-    { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n 
"$tmp" && test -d "$tmp" ; } ||
-       { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir 
"$tmp" 2>/dev/null) ; } ||
-       { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo 
"Warning: creating insecure temp directory" >&2 ; } ||
-       { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 
1 ; }
-    dummy=$tmp/dummy
-    case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
-       ,,)    echo "int x;" > "$dummy.c"
-              for driver in cc gcc c89 c99 ; do
-                  if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; 
then
-                      CC_FOR_BUILD=$driver
-                      break
-                  fi
-              done
-              if test x"$CC_FOR_BUILD" = x ; then
-                  CC_FOR_BUILD=no_compiler_found
-              fi
-              ;;
-       ,,*)   CC_FOR_BUILD=$CC ;;
-       ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
-    esac
-}
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 1994-08-24)
-if test -f /.attbin/uname ; then
-       PATH=$PATH:/.attbin ; export PATH
-fi
-
-UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-
-case $UNAME_SYSTEM in
-Linux|GNU|GNU/*)
-       LIBC=unknown
-
-       set_cc_for_build
-       cat <<-EOF > "$dummy.c"
-       #include <features.h>
-       #if defined(__UCLIBC__)
-       LIBC=uclibc
-       #elif defined(__dietlibc__)
-       LIBC=dietlibc
-       #elif defined(__GLIBC__)
-       LIBC=gnu
-       #else
-       #include <stdarg.h>
-       /* First heuristic to detect musl libc.  */
-       #ifdef __DEFINED_va_list
-       LIBC=musl
-       #endif
-       #endif
-       EOF
-       cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | 
sed 's, ,,g'`
-       eval "$cc_set_libc"
-
-       # Second heuristic to detect musl libc.
-       if [ "$LIBC" = unknown ] &&
-          command -v ldd >/dev/null &&
-          ldd --version 2>&1 | grep -q ^musl; then
-               LIBC=musl
-       fi
-
-       # If the system lacks a compiler, then just pick glibc.
-       # We could probably try harder.
-       if [ "$LIBC" = unknown ]; then
-               LIBC=gnu
-       fi
-       ;;
-esac
-
-# Note: order is significant - the case branches are not exclusive.
-
-case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
-    *:NetBSD:*:*)
-       # NetBSD (nbsd) targets should (where applicable) match one or
-       # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
-       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
-       # switched to ELF, *-*-netbsd* would select the old
-       # object file format.  This provides both forward
-       # compatibility and a consistent mechanism for selecting the
-       # object file format.
-       #
-       # Note: NetBSD doesn't particularly care about the vendor
-       # portion of the name.  We always set it to "unknown".
-       UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
-           /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
-           /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
-           echo unknown)`
-       case $UNAME_MACHINE_ARCH in
-           aarch64eb) machine=aarch64_be-unknown ;;
-           armeb) machine=armeb-unknown ;;
-           arm*) machine=arm-unknown ;;
-           sh3el) machine=shl-unknown ;;
-           sh3eb) machine=sh-unknown ;;
-           sh5el) machine=sh5le-unknown ;;
-           earmv*)
-               arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 
's,^e\(armv[0-9]\).*$,\1,'`
-               endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 
's,^.*\(eb\)$,\1,p'`
-               machine=${arch}${endian}-unknown
-               ;;
-           *) machine=$UNAME_MACHINE_ARCH-unknown ;;
-       esac
-       # The Operating System including object format, if it has switched
-       # to ELF recently (or will in the future) and ABI.
-       case $UNAME_MACHINE_ARCH in
-           earm*)
-               os=netbsdelf
-               ;;
-           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
-               set_cc_for_build
-               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
-                       | grep -q __ELF__
-               then
-                   # Once all utilities can be ECOFF (netbsdecoff) or a.out 
(netbsdaout).
-                   # Return netbsd for either.  FIX?
-                   os=netbsd
-               else
-                   os=netbsdelf
-               fi
-               ;;
-           *)
-               os=netbsd
-               ;;
-       esac
-       # Determine ABI tags.
-       case $UNAME_MACHINE_ARCH in
-           earm*)
-               expr='s/^earmv[0-9]/-eabi/;s/eb$//'
-               abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
-               ;;
-       esac
-       # The OS release
-       # Debian GNU/NetBSD machines have a different userland, and
-       # thus, need a distinct triplet. However, they do not need
-       # kernel version information, so it can be replaced with a
-       # suitable tag, in the style of linux-gnu.
-       case $UNAME_VERSION in
-           Debian*)
-               release='-gnu'
-               ;;
-           *)
-               release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. 
-f1,2`
-               ;;
-       esac
-       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
-       # contains redundant information, the shorter form:
-       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
-       GUESS=$machine-${os}${release}${abi-}
-       ;;
-    *:Bitrig:*:*)
-       UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
-       GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE
-       ;;
-    *:OpenBSD:*:*)
-       UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
-       GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE
-       ;;
-    *:SecBSD:*:*)
-       UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`
-       GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE
-       ;;
-    *:LibertyBSD:*:*)
-       UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
-       GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE
-       ;;
-    *:MidnightBSD:*:*)
-       GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE
-       ;;
-    *:ekkoBSD:*:*)
-       GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE
-       ;;
-    *:SolidBSD:*:*)
-       GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE
-       ;;
-    *:OS108:*:*)
-       GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE
-       ;;
-    macppc:MirBSD:*:*)
-       GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE
-       ;;
-    *:MirBSD:*:*)
-       GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE
-       ;;
-    *:Sortix:*:*)
-       GUESS=$UNAME_MACHINE-unknown-sortix
-       ;;
-    *:Twizzler:*:*)
-       GUESS=$UNAME_MACHINE-unknown-twizzler
-       ;;
-    *:Redox:*:*)
-       GUESS=$UNAME_MACHINE-unknown-redox
-       ;;
-    mips:OSF1:*.*)
-       GUESS=mips-dec-osf1
-       ;;
-    alpha:OSF1:*:*)
-       # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
-       trap '' 0
-       case $UNAME_RELEASE in
-       *4.0)
-               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
-               ;;
-       *5.*)
-               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
-               ;;
-       esac
-       # According to Compaq, /usr/sbin/psrinfo has been available on
-       # OSF/1 and Tru64 systems produced since 1995.  I hope that
-       # covers most systems running today.  This code pipes the CPU
-       # types through head -n 1, so we only detect the type of CPU 0.
-       ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) 
processor.*$/\1/p' | head -n 1`
-       case $ALPHA_CPU_TYPE in
-           "EV4 (21064)")
-               UNAME_MACHINE=alpha ;;
-           "EV4.5 (21064)")
-               UNAME_MACHINE=alpha ;;
-           "LCA4 (21066/21068)")
-               UNAME_MACHINE=alpha ;;
-           "EV5 (21164)")
-               UNAME_MACHINE=alphaev5 ;;
-           "EV5.6 (21164A)")
-               UNAME_MACHINE=alphaev56 ;;
-           "EV5.6 (21164PC)")
-               UNAME_MACHINE=alphapca56 ;;
-           "EV5.7 (21164PC)")
-               UNAME_MACHINE=alphapca57 ;;
-           "EV6 (21264)")
-               UNAME_MACHINE=alphaev6 ;;
-           "EV6.7 (21264A)")
-               UNAME_MACHINE=alphaev67 ;;
-           "EV6.8CB (21264C)")
-               UNAME_MACHINE=alphaev68 ;;
-           "EV6.8AL (21264B)")
-               UNAME_MACHINE=alphaev68 ;;
-           "EV6.8CX (21264D)")
-               UNAME_MACHINE=alphaev68 ;;
-           "EV6.9A (21264/EV69A)")
-               UNAME_MACHINE=alphaev69 ;;
-           "EV7 (21364)")
-               UNAME_MACHINE=alphaev7 ;;
-           "EV7.9 (21364A)")
-               UNAME_MACHINE=alphaev79 ;;
-       esac
-       # A Pn.n version is a patched version.
-       # A Vn.n version is a released version.
-       # A Tn.n version is a released field test version.
-       # A Xn.n version is an unreleased experimental baselevel.
-       # 1.2 uses "1.2" for uname -r.
-       OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr 
ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
-       GUESS=$UNAME_MACHINE-dec-osf$OSF_REL
-       ;;
-    Amiga*:UNIX_System_V:4.0:*)
-       GUESS=m68k-unknown-sysv4
-       ;;
-    *:[Aa]miga[Oo][Ss]:*:*)
-       GUESS=$UNAME_MACHINE-unknown-amigaos
-       ;;
-    *:[Mm]orph[Oo][Ss]:*:*)
-       GUESS=$UNAME_MACHINE-unknown-morphos
-       ;;
-    *:OS/390:*:*)
-       GUESS=i370-ibm-openedition
-       ;;
-    *:z/VM:*:*)
-       GUESS=s390-ibm-zvmoe
-       ;;
-    *:OS400:*:*)
-       GUESS=powerpc-ibm-os400
-       ;;
-    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
-       GUESS=arm-acorn-riscix$UNAME_RELEASE
-       ;;
-    arm*:riscos:*:*|arm*:RISCOS:*:*)
-       GUESS=arm-unknown-riscos
-       ;;
-    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
-       GUESS=hppa1.1-hitachi-hiuxmpp
-       ;;
-    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
-       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
-       case `(/bin/universe) 2>/dev/null` in
-           att) GUESS=pyramid-pyramid-sysv3 ;;
-           *)   GUESS=pyramid-pyramid-bsd   ;;
-       esac
-       ;;
-    NILE*:*:*:dcosx)
-       GUESS=pyramid-pyramid-svr4
-       ;;
-    DRS?6000:unix:4.0:6*)
-       GUESS=sparc-icl-nx6
-       ;;
-    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
-       case `/usr/bin/uname -p` in
-           sparc) GUESS=sparc-icl-nx7 ;;
-       esac
-       ;;
-    s390x:SunOS:*:*)
-       SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
-       GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL
-       ;;
-    sun4H:SunOS:5.*:*)
-       SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
-       GUESS=sparc-hal-solaris2$SUN_REL
-       ;;
-    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
-       SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
-       GUESS=sparc-sun-solaris2$SUN_REL
-       ;;
-    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
-       GUESS=i386-pc-auroraux$UNAME_RELEASE
-       ;;
-    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
-       set_cc_for_build
-       SUN_ARCH=i386
-       # If there is a compiler, see if it is configured for 64-bit objects.
-       # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
-       # This test works for both compilers.
-       if test "$CC_FOR_BUILD" != no_compiler_found; then
-           if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
-               (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \
-               grep IS_64BIT_ARCH >/dev/null
-           then
-               SUN_ARCH=x86_64
-           fi
-       fi
-       SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
-       GUESS=$SUN_ARCH-pc-solaris2$SUN_REL
-       ;;
-    sun4*:SunOS:6*:*)
-       # According to config.sub, this is the proper way to canonicalize
-       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
-       # it's likely to be more like Solaris than SunOS4.
-       SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
-       GUESS=sparc-sun-solaris3$SUN_REL
-       ;;
-    sun4*:SunOS:*:*)
-       case `/usr/bin/arch -k` in
-           Series*|S4*)
-               UNAME_RELEASE=`uname -v`
-               ;;
-       esac
-       # Japanese Language versions have a version number like '4.1.3-JL'.
-       SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
-       GUESS=sparc-sun-sunos$SUN_REL
-       ;;
-    sun3*:SunOS:*:*)
-       GUESS=m68k-sun-sunos$UNAME_RELEASE
-       ;;
-    sun*:*:4.2BSD:*)
-       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 
2>/dev/null`
-       test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
-       case `/bin/arch` in
-           sun3)
-               GUESS=m68k-sun-sunos$UNAME_RELEASE
-               ;;
-           sun4)
-               GUESS=sparc-sun-sunos$UNAME_RELEASE
-               ;;
-       esac
-       ;;
-    aushp:SunOS:*:*)
-       GUESS=sparc-auspex-sunos$UNAME_RELEASE
-       ;;
-    # The situation for MiNT is a little confusing.  The machine name
-    # can be virtually everything (everything which is not
-    # "atarist" or "atariste" at least should have a processor
-    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
-    # to the lowercase version "mint" (or "freemint").  Finally
-    # the system name "TOS" denotes a system which is actually not
-    # MiNT.  But MiNT is downward compatible to TOS, so this should
-    # be no problem.
-    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-       GUESS=m68k-atari-mint$UNAME_RELEASE
-       ;;
-    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
-       GUESS=m68k-atari-mint$UNAME_RELEASE
-       ;;
-    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-       GUESS=m68k-atari-mint$UNAME_RELEASE
-       ;;
-    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-       GUESS=m68k-milan-mint$UNAME_RELEASE
-       ;;
-    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-       GUESS=m68k-hades-mint$UNAME_RELEASE
-       ;;
-    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-       GUESS=m68k-unknown-mint$UNAME_RELEASE
-       ;;
-    m68k:machten:*:*)
-       GUESS=m68k-apple-machten$UNAME_RELEASE
-       ;;
-    powerpc:machten:*:*)
-       GUESS=powerpc-apple-machten$UNAME_RELEASE
-       ;;
-    RISC*:Mach:*:*)
-       GUESS=mips-dec-mach_bsd4.3
-       ;;
-    RISC*:ULTRIX:*:*)
-       GUESS=mips-dec-ultrix$UNAME_RELEASE
-       ;;
-    VAX*:ULTRIX*:*:*)
-       GUESS=vax-dec-ultrix$UNAME_RELEASE
-       ;;
-    2020:CLIX:*:* | 2430:CLIX:*:*)
-       GUESS=clipper-intergraph-clix$UNAME_RELEASE
-       ;;
-    mips:*:*:UMIPS | mips:*:*:RISCos)
-       set_cc_for_build
-       sed 's/^        //' << EOF > "$dummy.c"
-#ifdef __cplusplus
-#include <stdio.h>  /* for printf() prototype */
-       int main (int argc, char *argv[]) {
-#else
-       int main (argc, argv) int argc; char *argv[]; {
-#endif
-       #if defined (host_mips) && defined (MIPSEB)
-       #if defined (SYSTYPE_SYSV)
-         printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
-       #endif
-       #if defined (SYSTYPE_SVR4)
-         printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
-       #endif
-       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
-         printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
-       #endif
-       #endif
-         exit (-1);
-       }
-EOF
-       $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
-         dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
-         SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
-           { echo "$SYSTEM_NAME"; exit; }
-       GUESS=mips-mips-riscos$UNAME_RELEASE
-       ;;
-    Motorola:PowerMAX_OS:*:*)
-       GUESS=powerpc-motorola-powermax
-       ;;
-    Motorola:*:4.3:PL8-*)
-       GUESS=powerpc-harris-powermax
-       ;;
-    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
-       GUESS=powerpc-harris-powermax
-       ;;
-    Night_Hawk:Power_UNIX:*:*)
-       GUESS=powerpc-harris-powerunix
-       ;;
-    m88k:CX/UX:7*:*)
-       GUESS=m88k-harris-cxux7
-       ;;
-    m88k:*:4*:R4*)
-       GUESS=m88k-motorola-sysv4
-       ;;
-    m88k:*:3*:R3*)
-       GUESS=m88k-motorola-sysv3
-       ;;
-    AViiON:dgux:*:*)
-       # DG/UX returns AViiON for all architectures
-       UNAME_PROCESSOR=`/usr/bin/uname -p`
-       if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = 
mc88110
-       then
-           if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
-              test "$TARGET_BINARY_INTERFACE"x = x
-           then
-               GUESS=m88k-dg-dgux$UNAME_RELEASE
-           else
-               GUESS=m88k-dg-dguxbcs$UNAME_RELEASE
-           fi
-       else
-           GUESS=i586-dg-dgux$UNAME_RELEASE
-       fi
-       ;;
-    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
-       GUESS=m88k-dolphin-sysv3
-       ;;
-    M88*:*:R3*:*)
-       # Delta 88k system running SVR3
-       GUESS=m88k-motorola-sysv3
-       ;;
-    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
-       GUESS=m88k-tektronix-sysv3
-       ;;
-    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
-       GUESS=m68k-tektronix-bsd
-       ;;
-    *:IRIX*:*:*)
-       IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'`
-       GUESS=mips-sgi-irix$IRIX_REL
-       ;;
-    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
-       GUESS=romp-ibm-aix    # uname -m gives an 8 hex-code CPU id
-       ;;                    # Note that: echo "'`uname -s`'" gives 'AIX '
-    i*86:AIX:*:*)
-       GUESS=i386-ibm-aix
-       ;;
-    ia64:AIX:*:*)
-       if test -x /usr/bin/oslevel ; then
-               IBM_REV=`/usr/bin/oslevel`
-       else
-               IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
-       fi
-       GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV
-       ;;
-    *:AIX:2:3)
-       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
-               set_cc_for_build
-               sed 's/^                //' << EOF > "$dummy.c"
-               #include <sys/systemcfg.h>
-
-               main()
-                       {
-                       if (!__power_pc())
-                               exit(1);
-                       puts("powerpc-ibm-aix3.2.5");
-                       exit(0);
-                       }
-EOF
-               if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && 
SYSTEM_NAME=`"$dummy"`
-               then
-                       GUESS=$SYSTEM_NAME
-               else
-                       GUESS=rs6000-ibm-aix3.2.5
-               fi
-       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
-               GUESS=rs6000-ibm-aix3.2.4
-       else
-               GUESS=rs6000-ibm-aix3.2
-       fi
-       ;;
-    *:AIX:*:[4567])
-       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk 
'{ print $1 }'`
-       if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; 
then
-               IBM_ARCH=rs6000
-       else
-               IBM_ARCH=powerpc
-       fi
-       if test -x /usr/bin/lslpp ; then
-               IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \
-                          awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
-       else
-               IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
-       fi
-       GUESS=$IBM_ARCH-ibm-aix$IBM_REV
-       ;;
-    *:AIX:*:*)
-       GUESS=rs6000-ibm-aix
-       ;;
-    ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
-       GUESS=romp-ibm-bsd4.4
-       ;;
-    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
-       GUESS=romp-ibm-bsd$UNAME_RELEASE    # 4.3 with uname added to
-       ;;                                  # report: romp-ibm BSD 4.3
-    *:BOSX:*:*)
-       GUESS=rs6000-bull-bosx
-       ;;
-    DPX/2?00:B.O.S.:*:*)
-       GUESS=m68k-bull-sysv3
-       ;;
-    9000/[34]??:4.3bsd:1.*:*)
-       GUESS=m68k-hp-bsd
-       ;;
-    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
-       GUESS=m68k-hp-bsd4.4
-       ;;
-    9000/[34678]??:HP-UX:*:*)
-       HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
-       case $UNAME_MACHINE in
-           9000/31?)            HP_ARCH=m68000 ;;
-           9000/[34]??)         HP_ARCH=m68k ;;
-           9000/[678][0-9][0-9])
-               if test -x /usr/bin/getconf; then
-                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
-                   sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
-                   case $sc_cpu_version in
-                     523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
-                     528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
-                     532)                      # CPU_PA_RISC2_0
-                       case $sc_kernel_bits in
-                         32) HP_ARCH=hppa2.0n ;;
-                         64) HP_ARCH=hppa2.0w ;;
-                         '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
-                       esac ;;
-                   esac
-               fi
-               if test "$HP_ARCH" = ""; then
-                   set_cc_for_build
-                   sed 's/^            //' << EOF > "$dummy.c"
-
-               #define _HPUX_SOURCE
-               #include <stdlib.h>
-               #include <unistd.h>
-
-               int main ()
-               {
-               #if defined(_SC_KERNEL_BITS)
-                   long bits = sysconf(_SC_KERNEL_BITS);
-               #endif
-                   long cpu  = sysconf (_SC_CPU_VERSION);
-
-                   switch (cpu)
-                       {
-                       case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
-                       case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
-                       case CPU_PA_RISC2_0:
-               #if defined(_SC_KERNEL_BITS)
-                           switch (bits)
-                               {
-                               case 64: puts ("hppa2.0w"); break;
-                               case 32: puts ("hppa2.0n"); break;
-                               default: puts ("hppa2.0"); break;
-                               } break;
-               #else  /* !defined(_SC_KERNEL_BITS) */
-                           puts ("hppa2.0"); break;
-               #endif
-                       default: puts ("hppa1.0"); break;
-                       }
-                   exit (0);
-               }
-EOF
-                   (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 
2>/dev/null) && HP_ARCH=`"$dummy"`
-                   test -z "$HP_ARCH" && HP_ARCH=hppa
-               fi ;;
-       esac
-       if test "$HP_ARCH" = hppa2.0w
-       then
-           set_cc_for_build
-
-           # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
-           # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
-           # generating 64-bit code.  GNU and HP use different nomenclature:
-           #
-           # $ CC_FOR_BUILD=cc ./config.guess
-           # => hppa2.0w-hp-hpux11.23
-           # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
-           # => hppa64-hp-hpux11.23
-
-           if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
-               grep -q __LP64__
-           then
-               HP_ARCH=hppa2.0w
-           else
-               HP_ARCH=hppa64
-           fi
-       fi
-       GUESS=$HP_ARCH-hp-hpux$HPUX_REV
-       ;;
-    ia64:HP-UX:*:*)
-       HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
-       GUESS=ia64-hp-hpux$HPUX_REV
-       ;;
-    3050*:HI-UX:*:*)
-       set_cc_for_build
-       sed 's/^        //' << EOF > "$dummy.c"
-       #include <unistd.h>
-       int
-       main ()
-       {
-         long cpu = sysconf (_SC_CPU_VERSION);
-         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
-            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
-            results, however.  */
-         if (CPU_IS_PA_RISC (cpu))
-           {
-             switch (cpu)
-               {
-                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
-                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
-                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
-                 default: puts ("hppa-hitachi-hiuxwe2"); break;
-               }
-           }
-         else if (CPU_IS_HP_MC68K (cpu))
-           puts ("m68k-hitachi-hiuxwe2");
-         else puts ("unknown-hitachi-hiuxwe2");
-         exit (0);
-       }
-EOF
-       $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
-               { echo "$SYSTEM_NAME"; exit; }
-       GUESS=unknown-hitachi-hiuxwe2
-       ;;
-    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
-       GUESS=hppa1.1-hp-bsd
-       ;;
-    9000/8??:4.3bsd:*:*)
-       GUESS=hppa1.0-hp-bsd
-       ;;
-    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
-       GUESS=hppa1.0-hp-mpeix
-       ;;
-    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
-       GUESS=hppa1.1-hp-osf
-       ;;
-    hp8??:OSF1:*:*)
-       GUESS=hppa1.0-hp-osf
-       ;;
-    i*86:OSF1:*:*)
-       if test -x /usr/sbin/sysversion ; then
-           GUESS=$UNAME_MACHINE-unknown-osf1mk
-       else
-           GUESS=$UNAME_MACHINE-unknown-osf1
-       fi
-       ;;
-    parisc*:Lites*:*:*)
-       GUESS=hppa1.1-hp-lites
-       ;;
-    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
-       GUESS=c1-convex-bsd
-       ;;
-    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
-       if getsysinfo -f scalar_acc
-       then echo c32-convex-bsd
-       else echo c2-convex-bsd
-       fi
-       exit ;;
-    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
-       GUESS=c34-convex-bsd
-       ;;
-    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
-       GUESS=c38-convex-bsd
-       ;;
-    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
-       GUESS=c4-convex-bsd
-       ;;
-    CRAY*Y-MP:*:*:*)
-       CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
-       GUESS=ymp-cray-unicos$CRAY_REL
-       ;;
-    CRAY*[A-Z]90:*:*:*)
-       echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
-       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-             -e 's/\.[^.]*$/.X/'
-       exit ;;
-    CRAY*TS:*:*:*)
-       CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
-       GUESS=t90-cray-unicos$CRAY_REL
-       ;;
-    CRAY*T3E:*:*:*)
-       CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
-       GUESS=alphaev5-cray-unicosmk$CRAY_REL
-       ;;
-    CRAY*SV1:*:*:*)
-       CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
-       GUESS=sv1-cray-unicos$CRAY_REL
-       ;;
-    *:UNICOS/mp:*:*)
-       CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
-       GUESS=craynv-cray-unicosmp$CRAY_REL
-       ;;
-    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
-       FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ 
abcdefghijklmnopqrstuvwxyz`
-       FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ 
abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
-       FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
-       GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
-       ;;
-    5000:UNIX_System_V:4.*:*)
-       FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ 
abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
-       FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ 
abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
-       GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
-       ;;
-    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
-       GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE
-       ;;
-    sparc*:BSD/OS:*:*)
-       GUESS=sparc-unknown-bsdi$UNAME_RELEASE
-       ;;
-    *:BSD/OS:*:*)
-       GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE
-       ;;
-    arm:FreeBSD:*:*)
-       UNAME_PROCESSOR=`uname -p`
-       set_cc_for_build
-       if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
-           | grep -q __ARM_PCS_VFP
-       then
-           FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
-           GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi
-       else
-           FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
-           GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf
-       fi
-       ;;
-    *:FreeBSD:*:*)
-       UNAME_PROCESSOR=`/usr/bin/uname -p`
-       case $UNAME_PROCESSOR in
-           amd64)
-               UNAME_PROCESSOR=x86_64 ;;
-           i386)
-               UNAME_PROCESSOR=i586 ;;
-       esac
-       FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
-       GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL
-       ;;
-    i*:CYGWIN*:*)
-       GUESS=$UNAME_MACHINE-pc-cygwin
-       ;;
-    *:MINGW64*:*)
-       GUESS=$UNAME_MACHINE-pc-mingw64
-       ;;
-    *:MINGW*:*)
-       GUESS=$UNAME_MACHINE-pc-mingw32
-       ;;
-    *:MSYS*:*)
-       GUESS=$UNAME_MACHINE-pc-msys
-       ;;
-    i*:PW*:*)
-       GUESS=$UNAME_MACHINE-pc-pw32
-       ;;
-    *:SerenityOS:*:*)
-        GUESS=$UNAME_MACHINE-pc-serenity
-        ;;
-    *:Interix*:*)
-       case $UNAME_MACHINE in
-           x86)
-               GUESS=i586-pc-interix$UNAME_RELEASE
-               ;;
-           authenticamd | genuineintel | EM64T)
-               GUESS=x86_64-unknown-interix$UNAME_RELEASE
-               ;;
-           IA64)
-               GUESS=ia64-unknown-interix$UNAME_RELEASE
-               ;;
-       esac ;;
-    i*:UWIN*:*)
-       GUESS=$UNAME_MACHINE-pc-uwin
-       ;;
-    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
-       GUESS=x86_64-pc-cygwin
-       ;;
-    prep*:SunOS:5.*:*)
-       SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
-       GUESS=powerpcle-unknown-solaris2$SUN_REL
-       ;;
-    *:GNU:*:*)
-       # the GNU system
-       GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'`
-       GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'`
-       GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL
-       ;;
-    *:GNU/*:*:*)
-       # other systems with GNU libc and userland
-       GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" 
"[:lower:]"`
-       GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
-       GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
-       ;;
-    x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*)
-       GUESS="$UNAME_MACHINE-pc-managarm-mlibc"
-       ;;
-    *:[Mm]anagarm:*:*)
-       GUESS="$UNAME_MACHINE-unknown-managarm-mlibc"
-       ;;
-    *:Minix:*:*)
-       GUESS=$UNAME_MACHINE-unknown-minix
-       ;;
-    aarch64:Linux:*:*)
-       set_cc_for_build
-       CPU=$UNAME_MACHINE
-       LIBCABI=$LIBC
-       if test "$CC_FOR_BUILD" != no_compiler_found; then
-           ABI=64
-           sed 's/^        //' << EOF > "$dummy.c"
-           #ifdef __ARM_EABI__
-           #ifdef __ARM_PCS_VFP
-           ABI=eabihf
-           #else
-           ABI=eabi
-           #endif
-           #endif
-EOF
-           cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | 
sed 's, ,,g'`
-           eval "$cc_set_abi"
-           case $ABI in
-               eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;;
-           esac
-       fi
-       GUESS=$CPU-unknown-linux-$LIBCABI
-       ;;
-    aarch64_be:Linux:*:*)
-       UNAME_MACHINE=aarch64_be
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    alpha:Linux:*:*)
-       case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 
2>/dev/null` in
-         EV5)   UNAME_MACHINE=alphaev5 ;;
-         EV56)  UNAME_MACHINE=alphaev56 ;;
-         PCA56) UNAME_MACHINE=alphapca56 ;;
-         PCA57) UNAME_MACHINE=alphapca56 ;;
-         EV6)   UNAME_MACHINE=alphaev6 ;;
-         EV67)  UNAME_MACHINE=alphaev67 ;;
-         EV68*) UNAME_MACHINE=alphaev68 ;;
-       esac
-       objdump --private-headers /bin/sh | grep -q ld.so.1
-       if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    arm*:Linux:*:*)
-       set_cc_for_build
-       if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
-           | grep -q __ARM_EABI__
-       then
-           GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       else
-           if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
-               | grep -q __ARM_PCS_VFP
-           then
-               GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi
-           else
-               GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf
-           fi
-       fi
-       ;;
-    avr32*:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    cris:Linux:*:*)
-       GUESS=$UNAME_MACHINE-axis-linux-$LIBC
-       ;;
-    crisv32:Linux:*:*)
-       GUESS=$UNAME_MACHINE-axis-linux-$LIBC
-       ;;
-    e2k:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    frv:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    hexagon:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    i*86:Linux:*:*)
-       GUESS=$UNAME_MACHINE-pc-linux-$LIBC
-       ;;
-    ia64:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    k1om:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    kvx:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    kvx:cos:*:*)
-       GUESS=$UNAME_MACHINE-unknown-cos
-       ;;
-    kvx:mbr:*:*)
-       GUESS=$UNAME_MACHINE-unknown-mbr
-       ;;
-    loongarch32:Linux:*:* | loongarch64:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    m32r*:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    m68*:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    mips:Linux:*:* | mips64:Linux:*:*)
-       set_cc_for_build
-       IS_GLIBC=0
-       test x"${LIBC}" = xgnu && IS_GLIBC=1
-       sed 's/^        //' << EOF > "$dummy.c"
-       #undef CPU
-       #undef mips
-       #undef mipsel
-       #undef mips64
-       #undef mips64el
-       #if ${IS_GLIBC} && defined(_ABI64)
-       LIBCABI=gnuabi64
-       #else
-       #if ${IS_GLIBC} && defined(_ABIN32)
-       LIBCABI=gnuabin32
-       #else
-       LIBCABI=${LIBC}
-       #endif
-       #endif
-
-       #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && 
__mips_isa_rev>=6
-       CPU=mipsisa64r6
-       #else
-       #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && 
__mips_isa_rev>=6
-       CPU=mipsisa32r6
-       #else
-       #if defined(__mips64)
-       CPU=mips64
-       #else
-       CPU=mips
-       #endif
-       #endif
-       #endif
-
-       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || 
defined(MIPSEL)
-       MIPS_ENDIAN=el
-       #else
-       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || 
defined(MIPSEB)
-       MIPS_ENDIAN=
-       #else
-       MIPS_ENDIAN=
-       #endif
-       #endif
-EOF
-       cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep 
'^CPU\|^MIPS_ENDIAN\|^LIBCABI'`
-       eval "$cc_set_vars"
-       test "x$CPU" != x && { echo 
"$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
-       ;;
-    mips64el:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    openrisc*:Linux:*:*)
-       GUESS=or1k-unknown-linux-$LIBC
-       ;;
-    or32:Linux:*:* | or1k*:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    padre:Linux:*:*)
-       GUESS=sparc-unknown-linux-$LIBC
-       ;;
-    parisc64:Linux:*:* | hppa64:Linux:*:*)
-       GUESS=hppa64-unknown-linux-$LIBC
-       ;;
-    parisc:Linux:*:* | hppa:Linux:*:*)
-       # Look for CPU level
-       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
-         PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;
-         PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;
-         *)    GUESS=hppa-unknown-linux-$LIBC ;;
-       esac
-       ;;
-    ppc64:Linux:*:*)
-       GUESS=powerpc64-unknown-linux-$LIBC
-       ;;
-    ppc:Linux:*:*)
-       GUESS=powerpc-unknown-linux-$LIBC
-       ;;
-    ppc64le:Linux:*:*)
-       GUESS=powerpc64le-unknown-linux-$LIBC
-       ;;
-    ppcle:Linux:*:*)
-       GUESS=powerpcle-unknown-linux-$LIBC
-       ;;
-    riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | 
riscv64be:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    s390:Linux:*:* | s390x:Linux:*:*)
-       GUESS=$UNAME_MACHINE-ibm-linux-$LIBC
-       ;;
-    sh64*:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    sh*:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    sparc:Linux:*:* | sparc64:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    tile*:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    vax:Linux:*:*)
-       GUESS=$UNAME_MACHINE-dec-linux-$LIBC
-       ;;
-    x86_64:Linux:*:*)
-       set_cc_for_build
-       CPU=$UNAME_MACHINE
-       LIBCABI=$LIBC
-       if test "$CC_FOR_BUILD" != no_compiler_found; then
-           ABI=64
-           sed 's/^        //' << EOF > "$dummy.c"
-           #ifdef __i386__
-           ABI=x86
-           #else
-           #ifdef __ILP32__
-           ABI=x32
-           #endif
-           #endif
-EOF
-           cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | 
sed 's, ,,g'`
-           eval "$cc_set_abi"
-           case $ABI in
-               x86) CPU=i686 ;;
-               x32) LIBCABI=${LIBC}x32 ;;
-           esac
-       fi
-       GUESS=$CPU-pc-linux-$LIBCABI
-       ;;
-    xtensa*:Linux:*:*)
-       GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
-       ;;
-    i*86:DYNIX/ptx:4*:*)
-       # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
-       # earlier versions are messed up and put the nodename in both
-       # sysname and nodename.
-       GUESS=i386-sequent-sysv4
-       ;;
-    i*86:UNIX_SV:4.2MP:2.*)
-       # Unixware is an offshoot of SVR4, but it has its own version
-       # number series starting with 2...
-       # I am not positive that other SVR4 systems won't match this,
-       # I just have to hope.  -- rms.
-       # Use sysv4.2uw... so that sysv4* matches it.
-       GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
-       ;;
-    i*86:OS/2:*:*)
-       # If we were able to find 'uname', then EMX Unix compatibility
-       # is probably installed.
-       GUESS=$UNAME_MACHINE-pc-os2-emx
-       ;;
-    i*86:XTS-300:*:STOP)
-       GUESS=$UNAME_MACHINE-unknown-stop
-       ;;
-    i*86:atheos:*:*)
-       GUESS=$UNAME_MACHINE-unknown-atheos
-       ;;
-    i*86:syllable:*:*)
-       GUESS=$UNAME_MACHINE-pc-syllable
-       ;;
-    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
-       GUESS=i386-unknown-lynxos$UNAME_RELEASE
-       ;;
-    i*86:*DOS:*:*)
-       GUESS=$UNAME_MACHINE-pc-msdosdjgpp
-       ;;
-    i*86:*:4.*:*)
-       UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
-       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
-               GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL
-       else
-               GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL
-       fi
-       ;;
-    i*86:*:5:[678]*)
-       # UnixWare 7.x, OpenUNIX and OpenServer 6.
-       case `/bin/uname -X | grep "^Machine"` in
-           *486*)           UNAME_MACHINE=i486 ;;
-           *Pentium)        UNAME_MACHINE=i586 ;;
-           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
-       esac
-       
GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
-       ;;
-    i*86:*:3.2:*)
-       if test -f /usr/options/cb.name; then
-               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
-               GUESS=$UNAME_MACHINE-pc-isc$UNAME_REL
-       elif /bin/uname -X 2>/dev/null >/dev/null ; then
-               UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
-               (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
-               (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
-                       && UNAME_MACHINE=i586
-               (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
-                       && UNAME_MACHINE=i686
-               (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
-                       && UNAME_MACHINE=i686
-               GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL
-       else
-               GUESS=$UNAME_MACHINE-pc-sysv32
-       fi
-       ;;
-    pc:*:*:*)
-       # Left here for compatibility:
-       # uname -m prints for DJGPP always 'pc', but it prints nothing about
-       # the processor, so we play safe by assuming i586.
-       # Note: whatever this is, it MUST be the same as what config.sub
-       # prints for the "djgpp" host, or else GDB configure will decide that
-       # this is a cross-build.
-       GUESS=i586-pc-msdosdjgpp
-       ;;
-    Intel:Mach:3*:*)
-       GUESS=i386-pc-mach3
-       ;;
-    paragon:*:*:*)
-       GUESS=i860-intel-osf1
-       ;;
-    i860:*:4.*:*) # i860-SVR4
-       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
-         GUESS=i860-stardent-sysv$UNAME_RELEASE    # Stardent Vistra i860-SVR4
-       else # Add other i860-SVR4 vendors below as they are discovered.
-         GUESS=i860-unknown-sysv$UNAME_RELEASE     # Unknown i860-SVR4
-       fi
-       ;;
-    mini*:CTIX:SYS*5:*)
-       # "miniframe"
-       GUESS=m68010-convergent-sysv
-       ;;
-    mc68k:UNIX:SYSTEM5:3.51m)
-       GUESS=m68k-convergent-sysv
-       ;;
-    M680?0:D-NIX:5.3:*)
-       GUESS=m68k-diab-dnix
-       ;;
-    M68*:*:R3V[5678]*:*)
-       test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
-    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 
3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | 
SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
-       OS_REL=''
-       test -r /etc/.relid \
-       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
-       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-         && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
-       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-         && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
-    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
-       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-         && { echo i486-ncr-sysv4; exit; } ;;
-    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
-       OS_REL='.3'
-       test -r /etc/.relid \
-           && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < 
/etc/.relid`
-       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-           && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
-       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-           && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
-       /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
-           && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
-    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
-       GUESS=m68k-unknown-lynxos$UNAME_RELEASE
-       ;;
-    mc68030:UNIX_System_V:4.*:*)
-       GUESS=m68k-atari-sysv4
-       ;;
-    TSUNAMI:LynxOS:2.*:*)
-       GUESS=sparc-unknown-lynxos$UNAME_RELEASE
-       ;;
-    rs6000:LynxOS:2.*:*)
-       GUESS=rs6000-unknown-lynxos$UNAME_RELEASE
-       ;;
-    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
-       GUESS=powerpc-unknown-lynxos$UNAME_RELEASE
-       ;;
-    SM[BE]S:UNIX_SV:*:*)
-       GUESS=mips-dde-sysv$UNAME_RELEASE
-       ;;
-    RM*:ReliantUNIX-*:*:*)
-       GUESS=mips-sni-sysv4
-       ;;
-    RM*:SINIX-*:*:*)
-       GUESS=mips-sni-sysv4
-       ;;
-    *:SINIX-*:*:*)
-       if uname -p 2>/dev/null >/dev/null ; then
-               UNAME_MACHINE=`(uname -p) 2>/dev/null`
-               GUESS=$UNAME_MACHINE-sni-sysv4
-       else
-               GUESS=ns32k-sni-sysv
-       fi
-       ;;
-    PENTIUM:*:4.0*:*)  # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort
-                       # says <Richard.M.Bartel@ccMail.Census.GOV>
-       GUESS=i586-unisys-sysv4
-       ;;
-    *:UNIX_System_V:4*:FTX*)
-       # From Gerald Hewes <hewes@openmarket.com>.
-       # How about differentiating between stratus architectures? -djm
-       GUESS=hppa1.1-stratus-sysv4
-       ;;
-    *:*:*:FTX*)
-       # From seanf@swdc.stratus.com.
-       GUESS=i860-stratus-sysv4
-       ;;
-    i*86:VOS:*:*)
-       # From Paul.Green@stratus.com.
-       GUESS=$UNAME_MACHINE-stratus-vos
-       ;;
-    *:VOS:*:*)
-       # From Paul.Green@stratus.com.
-       GUESS=hppa1.1-stratus-vos
-       ;;
-    mc68*:A/UX:*:*)
-       GUESS=m68k-apple-aux$UNAME_RELEASE
-       ;;
-    news*:NEWS-OS:6*:*)
-       GUESS=mips-sony-newsos6
-       ;;
-    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
-       if test -d /usr/nec; then
-               GUESS=mips-nec-sysv$UNAME_RELEASE
-       else
-               GUESS=mips-unknown-sysv$UNAME_RELEASE
-       fi
-       ;;
-    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
-       GUESS=powerpc-be-beos
-       ;;
-    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
-       GUESS=powerpc-apple-beos
-       ;;
-    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
-       GUESS=i586-pc-beos
-       ;;
-    BePC:Haiku:*:*)    # Haiku running on Intel PC compatible.
-       GUESS=i586-pc-haiku
-       ;;
-    ppc:Haiku:*:*)     # Haiku running on Apple PowerPC
-       GUESS=powerpc-apple-haiku
-       ;;
-    *:Haiku:*:*)       # Haiku modern gcc (not bound by BeOS compat)
-       GUESS=$UNAME_MACHINE-unknown-haiku
-       ;;
-    SX-4:SUPER-UX:*:*)
-       GUESS=sx4-nec-superux$UNAME_RELEASE
-       ;;
-    SX-5:SUPER-UX:*:*)
-       GUESS=sx5-nec-superux$UNAME_RELEASE
-       ;;
-    SX-6:SUPER-UX:*:*)
-       GUESS=sx6-nec-superux$UNAME_RELEASE
-       ;;
-    SX-7:SUPER-UX:*:*)
-       GUESS=sx7-nec-superux$UNAME_RELEASE
-       ;;
-    SX-8:SUPER-UX:*:*)
-       GUESS=sx8-nec-superux$UNAME_RELEASE
-       ;;
-    SX-8R:SUPER-UX:*:*)
-       GUESS=sx8r-nec-superux$UNAME_RELEASE
-       ;;
-    SX-ACE:SUPER-UX:*:*)
-       GUESS=sxace-nec-superux$UNAME_RELEASE
-       ;;
-    Power*:Rhapsody:*:*)
-       GUESS=powerpc-apple-rhapsody$UNAME_RELEASE
-       ;;
-    *:Rhapsody:*:*)
-       GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE
-       ;;
-    arm64:Darwin:*:*)
-       GUESS=aarch64-apple-darwin$UNAME_RELEASE
-       ;;
-    *:Darwin:*:*)
-       UNAME_PROCESSOR=`uname -p`
-       case $UNAME_PROCESSOR in
-           unknown) UNAME_PROCESSOR=powerpc ;;
-       esac
-       if command -v xcode-select > /dev/null 2> /dev/null && \
-               ! xcode-select --print-path > /dev/null 2> /dev/null ; then
-           # Avoid executing cc if there is no toolchain installed as
-           # cc will be a stub that puts up a graphical alert
-           # prompting the user to install developer tools.
-           CC_FOR_BUILD=no_compiler_found
-       else
-           set_cc_for_build
-       fi
-       if test "$CC_FOR_BUILD" != no_compiler_found; then
-           if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
-                  (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-                  grep IS_64BIT_ARCH >/dev/null
-           then
-               case $UNAME_PROCESSOR in
-                   i386) UNAME_PROCESSOR=x86_64 ;;
-                   powerpc) UNAME_PROCESSOR=powerpc64 ;;
-               esac
-           fi
-           # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
-           if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
-                  (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-                  grep IS_PPC >/dev/null
-           then
-               UNAME_PROCESSOR=powerpc
-           fi
-       elif test "$UNAME_PROCESSOR" = i386 ; then
-           # uname -m returns i386 or x86_64
-           UNAME_PROCESSOR=$UNAME_MACHINE
-       fi
-       GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE
-       ;;
-    *:procnto*:*:* | *:QNX:[0123456789]*:*)
-       UNAME_PROCESSOR=`uname -p`
-       if test "$UNAME_PROCESSOR" = x86; then
-               UNAME_PROCESSOR=i386
-               UNAME_MACHINE=pc
-       fi
-       GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE
-       ;;
-    *:QNX:*:4*)
-       GUESS=i386-pc-qnx
-       ;;
-    NEO-*:NONSTOP_KERNEL:*:*)
-       GUESS=neo-tandem-nsk$UNAME_RELEASE
-       ;;
-    NSE-*:NONSTOP_KERNEL:*:*)
-       GUESS=nse-tandem-nsk$UNAME_RELEASE
-       ;;
-    NSR-*:NONSTOP_KERNEL:*:*)
-       GUESS=nsr-tandem-nsk$UNAME_RELEASE
-       ;;
-    NSV-*:NONSTOP_KERNEL:*:*)
-       GUESS=nsv-tandem-nsk$UNAME_RELEASE
-       ;;
-    NSX-*:NONSTOP_KERNEL:*:*)
-       GUESS=nsx-tandem-nsk$UNAME_RELEASE
-       ;;
-    *:NonStop-UX:*:*)
-       GUESS=mips-compaq-nonstopux
-       ;;
-    BS2000:POSIX*:*:*)
-       GUESS=bs2000-siemens-sysv
-       ;;
-    DS/*:UNIX_System_V:*:*)
-       GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE
-       ;;
-    *:Plan9:*:*)
-       # "uname -m" is not consistent, so use $cputype instead. 386
-       # is converted to i386 for consistency with other x86
-       # operating systems.
-       if test "${cputype-}" = 386; then
-           UNAME_MACHINE=i386
-       elif test "x${cputype-}" != x; then
-           UNAME_MACHINE=$cputype
-       fi
-       GUESS=$UNAME_MACHINE-unknown-plan9
-       ;;
-    *:TOPS-10:*:*)
-       GUESS=pdp10-unknown-tops10
-       ;;
-    *:TENEX:*:*)
-       GUESS=pdp10-unknown-tenex
-       ;;
-    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
-       GUESS=pdp10-dec-tops20
-       ;;
-    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
-       GUESS=pdp10-xkl-tops20
-       ;;
-    *:TOPS-20:*:*)
-       GUESS=pdp10-unknown-tops20
-       ;;
-    *:ITS:*:*)
-       GUESS=pdp10-unknown-its
-       ;;
-    SEI:*:*:SEIUX)
-       GUESS=mips-sei-seiux$UNAME_RELEASE
-       ;;
-    *:DragonFly:*:*)
-       DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
-       GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL
-       ;;
-    *:*VMS:*:*)
-       UNAME_MACHINE=`(uname -p) 2>/dev/null`
-       case $UNAME_MACHINE in
-           A*) GUESS=alpha-dec-vms ;;
-           I*) GUESS=ia64-dec-vms ;;
-           V*) GUESS=vax-dec-vms ;;
-       esac ;;
-    *:XENIX:*:SysV)
-       GUESS=i386-pc-xenix
-       ;;
-    i*86:skyos:*:*)
-       SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`
-       GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL
-       ;;
-    i*86:rdos:*:*)
-       GUESS=$UNAME_MACHINE-pc-rdos
-       ;;
-    i*86:Fiwix:*:*)
-       GUESS=$UNAME_MACHINE-pc-fiwix
-       ;;
-    *:AROS:*:*)
-       GUESS=$UNAME_MACHINE-unknown-aros
-       ;;
-    x86_64:VMkernel:*:*)
-       GUESS=$UNAME_MACHINE-unknown-esx
-       ;;
-    amd64:Isilon\ OneFS:*:*)
-       GUESS=x86_64-unknown-onefs
-       ;;
-    *:Unleashed:*:*)
-       GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
-       ;;
-esac
-
-# Do we have a guess based on uname results?
-if test "x$GUESS" != x; then
-    echo "$GUESS"
-    exit
-fi
-
-# No uname command or uname output not recognized.
-set_cc_for_build
-cat > "$dummy.c" <<EOF
-#ifdef _SEQUENT_
-#include <sys/types.h>
-#include <sys/utsname.h>
-#endif
-#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || 
defined(__ultrix__)
-#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || 
defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
-#include <signal.h>
-#if defined(_SIZE_T_) || defined(SIGLOST)
-#include <sys/utsname.h>
-#endif
-#endif
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
-  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
-     I don't know....  */
-  printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
-  printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
-  "4"
-#else
-  ""
-#endif
-  ); exit (0);
-#endif
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
-  int version;
-  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
-  if (version < 4)
-    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
-  else
-    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
-  exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
-  printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
-  printf ("ns32k-encore-mach\n"); exit (0);
-#else
-  printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
-  printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
-  printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
-  printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
-  struct utsname un;
-
-  uname(&un);
-  if (strncmp(un.version, "V2", 2) == 0) {
-    printf ("i386-sequent-ptx2\n"); exit (0);
-  }
-  if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
-    printf ("i386-sequent-ptx1\n"); exit (0);
-  }
-  printf ("i386-sequent-ptx\n"); exit (0);
-#endif
-
-#if defined (vax)
-#if !defined (ultrix)
-#include <sys/param.h>
-#if defined (BSD)
-#if BSD == 43
-  printf ("vax-dec-bsd4.3\n"); exit (0);
-#else
-#if BSD == 199006
-  printf ("vax-dec-bsd4.3reno\n"); exit (0);
-#else
-  printf ("vax-dec-bsd\n"); exit (0);
-#endif
-#endif
-#else
-  printf ("vax-dec-bsd\n"); exit (0);
-#endif
-#else
-#if defined(_SIZE_T_) || defined(SIGLOST)
-  struct utsname un;
-  uname (&un);
-  printf ("vax-dec-ultrix%s\n", un.release); exit (0);
-#else
-  printf ("vax-dec-ultrix\n"); exit (0);
-#endif
-#endif
-#endif
-#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || 
defined(__ultrix__)
-#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || 
defined(__MIPS__)
-#if defined(_SIZE_T_) || defined(SIGLOST)
-  struct utsname *un;
-  uname (&un);
-  printf ("mips-dec-ultrix%s\n", un.release); exit (0);
-#else
-  printf ("mips-dec-ultrix\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (alliant) && defined (i860)
-  printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
-  exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` &&
-       { echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
-
-echo "$0: unable to guess system type" >&2
-
-case $UNAME_MACHINE:$UNAME_SYSTEM in
-    mips:Linux | mips64:Linux)
-       # If we got here on MIPS GNU/Linux, output extra information.
-       cat >&2 <<EOF
-
-NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
-the system type. Please install a C compiler and try again.
-EOF
-       ;;
-esac
-
-cat >&2 <<EOF
-
-This script (version $timestamp), has failed to recognize the
-operating system you are using. If your script is old, overwrite *all*
-copies of config.guess and config.sub with the latest versions from:
-
-  https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
-and
-  https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
-EOF
-
-our_year=`echo $timestamp | sed 's,-.*,,'`
-thisyear=`date +%Y`
-# shellcheck disable=SC2003
-script_age=`expr "$thisyear" - "$our_year"`
-if test "$script_age" -lt 3 ; then
-   cat >&2 <<EOF
-
-If $0 has already been updated, send the following data and any
-information you think might be pertinent to config-patches@gnu.org to
-provide the necessary information to handle your system.
-
-config.guess timestamp = $timestamp
-
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
-/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
-
-hostinfo               = `(hostinfo) 2>/dev/null`
-/bin/universe          = `(/bin/universe) 2>/dev/null`
-/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
-/bin/arch              = `(/bin/arch) 2>/dev/null`
-/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
-
-UNAME_MACHINE = "$UNAME_MACHINE"
-UNAME_RELEASE = "$UNAME_RELEASE"
-UNAME_SYSTEM  = "$UNAME_SYSTEM"
-UNAME_VERSION = "$UNAME_VERSION"
-EOF
-fi
-
-exit 1
-
-# Local variables:
-# eval: (add-hook 'before-save-hook 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/exec/config.sub b/exec/config.sub
deleted file mode 100755
index 6ae25027537..00000000000
--- a/exec/config.sub
+++ /dev/null
@@ -1,1895 +0,0 @@
-#! /bin/sh
-# Configuration validation subroutine script.
-#   Copyright 1992-2023 Free Software Foundation, Inc.
-
-# shellcheck disable=SC2006,SC2268 # see below for rationale
-
-timestamp='2023-07-31'
-
-# 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
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program 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 this program; if not, see <https://www.gnu.org/licenses/>.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that
-# program.  This Exception is an additional permission under section 7
-# of the GNU General Public License, version 3 ("GPLv3").
-
-
-# Please send patches to <config-patches@gnu.org>.
-#
-# Configuration subroutine to validate and canonicalize a configuration type.
-# Supply the specified configuration type as an argument.
-# If it is invalid, we print an error message on stderr and exit with code 1.
-# Otherwise, we print the canonical config type on stdout and succeed.
-
-# You can get the latest version of this script from:
-# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
-
-# This file is supposed to be the same for all GNU packages
-# and recognize all the CPU types, system types and aliases
-# that are meaningful with *any* GNU software.
-# Each package is responsible for reporting which valid configurations
-# it does not support.  The user should be able to distinguish
-# a failure to support a valid configuration from a meaningless
-# configuration.
-
-# The goal of this file is to map all the various variations of a given
-# machine specification into a single specification in the form:
-#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
-# or in some cases, the newer four-part form:
-#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
-# It is wrong to echo any other type of specification.
-
-# The "shellcheck disable" line above the timestamp inhibits complaints
-# about features and limitations of the classic Bourne shell that were
-# superseded or lifted in POSIX.  However, this script identifies a wide
-# variety of pre-POSIX systems that do not have POSIX shells at all, and
-# even some reasonably current systems (Solaris 10 as case-in-point) still
-# have a pre-POSIX /bin/sh.
-
-me=`echo "$0" | sed -e 's,.*/,,'`
-
-usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
-
-Canonicalize a configuration name.
-
-Options:
-  -h, --help         print this help, then exit
-  -t, --time-stamp   print date of last modification, then exit
-  -v, --version      print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.sub ($timestamp)
-
-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."
-
-help="
-Try '$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
-  case $1 in
-    --time-stamp | --time* | -t )
-       echo "$timestamp" ; exit ;;
-    --version | -v )
-       echo "$version" ; exit ;;
-    --help | --h* | -h )
-       echo "$usage"; exit ;;
-    -- )     # Stop option processing
-       shift; break ;;
-    - )        # Use stdin as input.
-       break ;;
-    -* )
-       echo "$me: invalid option $1$help" >&2
-       exit 1 ;;
-
-    *local*)
-       # First pass through any local machine types.
-       echo "$1"
-       exit ;;
-
-    * )
-       break ;;
-  esac
-done
-
-case $# in
- 0) echo "$me: missing argument$help" >&2
-    exit 1;;
- 1) ;;
- *) echo "$me: too many arguments$help" >&2
-    exit 1;;
-esac
-
-# Split fields of configuration type
-# shellcheck disable=SC2162
-saved_IFS=$IFS
-IFS="-" read field1 field2 field3 field4 <<EOF
-$1
-EOF
-IFS=$saved_IFS
-
-# Separate into logical components for further validation
-case $1 in
-       *-*-*-*-*)
-               echo "Invalid configuration '$1': more than four components" >&2
-               exit 1
-               ;;
-       *-*-*-*)
-               basic_machine=$field1-$field2
-               basic_os=$field3-$field4
-               ;;
-       *-*-*)
-               # Ambiguous whether COMPANY is present, or skipped and 
KERNEL-OS is two
-               # parts
-               maybe_os=$field2-$field3
-               case $maybe_os in
-                       nto-qnx* | linux-* | uclinux-uclibc* \
-                       | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | 
netbsd*-gnu* \
-                       | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
-                       | storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \
-                       | windows-* )
-                               basic_machine=$field1
-                               basic_os=$maybe_os
-                               ;;
-                       android-linux)
-                               basic_machine=$field1-unknown
-                               basic_os=linux-android
-                               ;;
-                       *)
-                               basic_machine=$field1-$field2
-                               basic_os=$field3
-                               ;;
-               esac
-               ;;
-       *-*)
-               # A lone config we happen to match not fitting any pattern
-               case $field1-$field2 in
-                       decstation-3100)
-                               basic_machine=mips-dec
-                               basic_os=
-                               ;;
-                       *-*)
-                               # Second component is usually, but not always 
the OS
-                               case $field2 in
-                                       # Prevent following clause from 
handling this valid os
-                                       sun*os*)
-                                               basic_machine=$field1
-                                               basic_os=$field2
-                                               ;;
-                                       zephyr*)
-                                               basic_machine=$field1-unknown
-                                               basic_os=$field2
-                                               ;;
-                                       # Manufacturers
-                                       dec* | mips* | sequent* | encore* | 
pc533* | sgi* | sony* \
-                                       | att* | 7300* | 3300* | delta* | 
motorola* | sun[234]* \
-                                       | unicom* | ibm* | next | hp | isi* | 
apollo | altos* \
-                                       | convergent* | ncr* | news | 32* | 
3600* | 3100* \
-                                       | hitachi* | c[123]* | convex* | sun | 
crds | omron* | dg \
-                                       | ultra | tti* | harris | dolphin | 
highlevel | gould \
-                                       | cbm | ns | masscomp | apple | axis | 
knuth | cray \
-                                       | microblaze* | sim | cisco \
-                                       | oki | wec | wrs | winbond)
-                                               basic_machine=$field1-$field2
-                                               basic_os=
-                                               ;;
-                                       *)
-                                               basic_machine=$field1
-                                               basic_os=$field2
-                                               ;;
-                               esac
-                       ;;
-               esac
-               ;;
-       *)
-               # Convert single-component short-hands not valid as part of
-               # multi-component configurations.
-               case $field1 in
-                       386bsd)
-                               basic_machine=i386-pc
-                               basic_os=bsd
-                               ;;
-                       a29khif)
-                               basic_machine=a29k-amd
-                               basic_os=udi
-                               ;;
-                       adobe68k)
-                               basic_machine=m68010-adobe
-                               basic_os=scout
-                               ;;
-                       alliant)
-                               basic_machine=fx80-alliant
-                               basic_os=
-                               ;;
-                       altos | altos3068)
-                               basic_machine=m68k-altos
-                               basic_os=
-                               ;;
-                       am29k)
-                               basic_machine=a29k-none
-                               basic_os=bsd
-                               ;;
-                       amdahl)
-                               basic_machine=580-amdahl
-                               basic_os=sysv
-                               ;;
-                       amiga)
-                               basic_machine=m68k-unknown
-                               basic_os=
-                               ;;
-                       amigaos | amigados)
-                               basic_machine=m68k-unknown
-                               basic_os=amigaos
-                               ;;
-                       amigaunix | amix)
-                               basic_machine=m68k-unknown
-                               basic_os=sysv4
-                               ;;
-                       apollo68)
-                               basic_machine=m68k-apollo
-                               basic_os=sysv
-                               ;;
-                       apollo68bsd)
-                               basic_machine=m68k-apollo
-                               basic_os=bsd
-                               ;;
-                       aros)
-                               basic_machine=i386-pc
-                               basic_os=aros
-                               ;;
-                       aux)
-                               basic_machine=m68k-apple
-                               basic_os=aux
-                               ;;
-                       balance)
-                               basic_machine=ns32k-sequent
-                               basic_os=dynix
-                               ;;
-                       blackfin)
-                               basic_machine=bfin-unknown
-                               basic_os=linux
-                               ;;
-                       cegcc)
-                               basic_machine=arm-unknown
-                               basic_os=cegcc
-                               ;;
-                       convex-c1)
-                               basic_machine=c1-convex
-                               basic_os=bsd
-                               ;;
-                       convex-c2)
-                               basic_machine=c2-convex
-                               basic_os=bsd
-                               ;;
-                       convex-c32)
-                               basic_machine=c32-convex
-                               basic_os=bsd
-                               ;;
-                       convex-c34)
-                               basic_machine=c34-convex
-                               basic_os=bsd
-                               ;;
-                       convex-c38)
-                               basic_machine=c38-convex
-                               basic_os=bsd
-                               ;;
-                       cray)
-                               basic_machine=j90-cray
-                               basic_os=unicos
-                               ;;
-                       crds | unos)
-                               basic_machine=m68k-crds
-                               basic_os=
-                               ;;
-                       da30)
-                               basic_machine=m68k-da30
-                               basic_os=
-                               ;;
-                       decstation | pmax | pmin | dec3100 | decstatn)
-                               basic_machine=mips-dec
-                               basic_os=
-                               ;;
-                       delta88)
-                               basic_machine=m88k-motorola
-                               basic_os=sysv3
-                               ;;
-                       dicos)
-                               basic_machine=i686-pc
-                               basic_os=dicos
-                               ;;
-                       djgpp)
-                               basic_machine=i586-pc
-                               basic_os=msdosdjgpp
-                               ;;
-                       ebmon29k)
-                               basic_machine=a29k-amd
-                               basic_os=ebmon
-                               ;;
-                       es1800 | OSE68k | ose68k | ose | OSE)
-                               basic_machine=m68k-ericsson
-                               basic_os=ose
-                               ;;
-                       gmicro)
-                               basic_machine=tron-gmicro
-                               basic_os=sysv
-                               ;;
-                       go32)
-                               basic_machine=i386-pc
-                               basic_os=go32
-                               ;;
-                       h8300hms)
-                               basic_machine=h8300-hitachi
-                               basic_os=hms
-                               ;;
-                       h8300xray)
-                               basic_machine=h8300-hitachi
-                               basic_os=xray
-                               ;;
-                       h8500hms)
-                               basic_machine=h8500-hitachi
-                               basic_os=hms
-                               ;;
-                       harris)
-                               basic_machine=m88k-harris
-                               basic_os=sysv3
-                               ;;
-                       hp300 | hp300hpux)
-                               basic_machine=m68k-hp
-                               basic_os=hpux
-                               ;;
-                       hp300bsd)
-                               basic_machine=m68k-hp
-                               basic_os=bsd
-                               ;;
-                       hppaosf)
-                               basic_machine=hppa1.1-hp
-                               basic_os=osf
-                               ;;
-                       hppro)
-                               basic_machine=hppa1.1-hp
-                               basic_os=proelf
-                               ;;
-                       i386mach)
-                               basic_machine=i386-mach
-                               basic_os=mach
-                               ;;
-                       isi68 | isi)
-                               basic_machine=m68k-isi
-                               basic_os=sysv
-                               ;;
-                       m68knommu)
-                               basic_machine=m68k-unknown
-                               basic_os=linux
-                               ;;
-                       magnum | m3230)
-                               basic_machine=mips-mips
-                               basic_os=sysv
-                               ;;
-                       merlin)
-                               basic_machine=ns32k-utek
-                               basic_os=sysv
-                               ;;
-                       mingw64)
-                               basic_machine=x86_64-pc
-                               basic_os=mingw64
-                               ;;
-                       mingw32)
-                               basic_machine=i686-pc
-                               basic_os=mingw32
-                               ;;
-                       mingw32ce)
-                               basic_machine=arm-unknown
-                               basic_os=mingw32ce
-                               ;;
-                       monitor)
-                               basic_machine=m68k-rom68k
-                               basic_os=coff
-                               ;;
-                       morphos)
-                               basic_machine=powerpc-unknown
-                               basic_os=morphos
-                               ;;
-                       moxiebox)
-                               basic_machine=moxie-unknown
-                               basic_os=moxiebox
-                               ;;
-                       msdos)
-                               basic_machine=i386-pc
-                               basic_os=msdos
-                               ;;
-                       msys)
-                               basic_machine=i686-pc
-                               basic_os=msys
-                               ;;
-                       mvs)
-                               basic_machine=i370-ibm
-                               basic_os=mvs
-                               ;;
-                       nacl)
-                               basic_machine=le32-unknown
-                               basic_os=nacl
-                               ;;
-                       ncr3000)
-                               basic_machine=i486-ncr
-                               basic_os=sysv4
-                               ;;
-                       netbsd386)
-                               basic_machine=i386-pc
-                               basic_os=netbsd
-                               ;;
-                       netwinder)
-                               basic_machine=armv4l-rebel
-                               basic_os=linux
-                               ;;
-                       news | news700 | news800 | news900)
-                               basic_machine=m68k-sony
-                               basic_os=newsos
-                               ;;
-                       news1000)
-                               basic_machine=m68030-sony
-                               basic_os=newsos
-                               ;;
-                       necv70)
-                               basic_machine=v70-nec
-                               basic_os=sysv
-                               ;;
-                       nh3000)
-                               basic_machine=m68k-harris
-                               basic_os=cxux
-                               ;;
-                       nh[45]000)
-                               basic_machine=m88k-harris
-                               basic_os=cxux
-                               ;;
-                       nindy960)
-                               basic_machine=i960-intel
-                               basic_os=nindy
-                               ;;
-                       mon960)
-                               basic_machine=i960-intel
-                               basic_os=mon960
-                               ;;
-                       nonstopux)
-                               basic_machine=mips-compaq
-                               basic_os=nonstopux
-                               ;;
-                       os400)
-                               basic_machine=powerpc-ibm
-                               basic_os=os400
-                               ;;
-                       OSE68000 | ose68000)
-                               basic_machine=m68000-ericsson
-                               basic_os=ose
-                               ;;
-                       os68k)
-                               basic_machine=m68k-none
-                               basic_os=os68k
-                               ;;
-                       paragon)
-                               basic_machine=i860-intel
-                               basic_os=osf
-                               ;;
-                       parisc)
-                               basic_machine=hppa-unknown
-                               basic_os=linux
-                               ;;
-                       psp)
-                               basic_machine=mipsallegrexel-sony
-                               basic_os=psp
-                               ;;
-                       pw32)
-                               basic_machine=i586-unknown
-                               basic_os=pw32
-                               ;;
-                       rdos | rdos64)
-                               basic_machine=x86_64-pc
-                               basic_os=rdos
-                               ;;
-                       rdos32)
-                               basic_machine=i386-pc
-                               basic_os=rdos
-                               ;;
-                       rom68k)
-                               basic_machine=m68k-rom68k
-                               basic_os=coff
-                               ;;
-                       sa29200)
-                               basic_machine=a29k-amd
-                               basic_os=udi
-                               ;;
-                       sei)
-                               basic_machine=mips-sei
-                               basic_os=seiux
-                               ;;
-                       sequent)
-                               basic_machine=i386-sequent
-                               basic_os=
-                               ;;
-                       sps7)
-                               basic_machine=m68k-bull
-                               basic_os=sysv2
-                               ;;
-                       st2000)
-                               basic_machine=m68k-tandem
-                               basic_os=
-                               ;;
-                       stratus)
-                               basic_machine=i860-stratus
-                               basic_os=sysv4
-                               ;;
-                       sun2)
-                               basic_machine=m68000-sun
-                               basic_os=
-                               ;;
-                       sun2os3)
-                               basic_machine=m68000-sun
-                               basic_os=sunos3
-                               ;;
-                       sun2os4)
-                               basic_machine=m68000-sun
-                               basic_os=sunos4
-                               ;;
-                       sun3)
-                               basic_machine=m68k-sun
-                               basic_os=
-                               ;;
-                       sun3os3)
-                               basic_machine=m68k-sun
-                               basic_os=sunos3
-                               ;;
-                       sun3os4)
-                               basic_machine=m68k-sun
-                               basic_os=sunos4
-                               ;;
-                       sun4)
-                               basic_machine=sparc-sun
-                               basic_os=
-                               ;;
-                       sun4os3)
-                               basic_machine=sparc-sun
-                               basic_os=sunos3
-                               ;;
-                       sun4os4)
-                               basic_machine=sparc-sun
-                               basic_os=sunos4
-                               ;;
-                       sun4sol2)
-                               basic_machine=sparc-sun
-                               basic_os=solaris2
-                               ;;
-                       sun386 | sun386i | roadrunner)
-                               basic_machine=i386-sun
-                               basic_os=
-                               ;;
-                       sv1)
-                               basic_machine=sv1-cray
-                               basic_os=unicos
-                               ;;
-                       symmetry)
-                               basic_machine=i386-sequent
-                               basic_os=dynix
-                               ;;
-                       t3e)
-                               basic_machine=alphaev5-cray
-                               basic_os=unicos
-                               ;;
-                       t90)
-                               basic_machine=t90-cray
-                               basic_os=unicos
-                               ;;
-                       toad1)
-                               basic_machine=pdp10-xkl
-                               basic_os=tops20
-                               ;;
-                       tpf)
-                               basic_machine=s390x-ibm
-                               basic_os=tpf
-                               ;;
-                       udi29k)
-                               basic_machine=a29k-amd
-                               basic_os=udi
-                               ;;
-                       ultra3)
-                               basic_machine=a29k-nyu
-                               basic_os=sym1
-                               ;;
-                       v810 | necv810)
-                               basic_machine=v810-nec
-                               basic_os=none
-                               ;;
-                       vaxv)
-                               basic_machine=vax-dec
-                               basic_os=sysv
-                               ;;
-                       vms)
-                               basic_machine=vax-dec
-                               basic_os=vms
-                               ;;
-                       vsta)
-                               basic_machine=i386-pc
-                               basic_os=vsta
-                               ;;
-                       vxworks960)
-                               basic_machine=i960-wrs
-                               basic_os=vxworks
-                               ;;
-                       vxworks68)
-                               basic_machine=m68k-wrs
-                               basic_os=vxworks
-                               ;;
-                       vxworks29k)
-                               basic_machine=a29k-wrs
-                               basic_os=vxworks
-                               ;;
-                       xbox)
-                               basic_machine=i686-pc
-                               basic_os=mingw32
-                               ;;
-                       ymp)
-                               basic_machine=ymp-cray
-                               basic_os=unicos
-                               ;;
-                       *)
-                               basic_machine=$1
-                               basic_os=
-                               ;;
-               esac
-               ;;
-esac
-
-# Decode 1-component or ad-hoc basic machines
-case $basic_machine in
-       # Here we handle the default manufacturer of certain CPU types.  It is 
in
-       # some cases the only manufacturer, in others, it is the most popular.
-       w89k)
-               cpu=hppa1.1
-               vendor=winbond
-               ;;
-       op50n)
-               cpu=hppa1.1
-               vendor=oki
-               ;;
-       op60c)
-               cpu=hppa1.1
-               vendor=oki
-               ;;
-       ibm*)
-               cpu=i370
-               vendor=ibm
-               ;;
-       orion105)
-               cpu=clipper
-               vendor=highlevel
-               ;;
-       mac | mpw | mac-mpw)
-               cpu=m68k
-               vendor=apple
-               ;;
-       pmac | pmac-mpw)
-               cpu=powerpc
-               vendor=apple
-               ;;
-
-       # Recognize the various machine names and aliases which stand
-       # for a CPU type and a company and sometimes even an OS.
-       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
-               cpu=m68000
-               vendor=att
-               ;;
-       3b*)
-               cpu=we32k
-               vendor=att
-               ;;
-       bluegene*)
-               cpu=powerpc
-               vendor=ibm
-               basic_os=cnk
-               ;;
-       decsystem10* | dec10*)
-               cpu=pdp10
-               vendor=dec
-               basic_os=tops10
-               ;;
-       decsystem20* | dec20*)
-               cpu=pdp10
-               vendor=dec
-               basic_os=tops20
-               ;;
-       delta | 3300 | motorola-3300 | motorola-delta \
-             | 3300-motorola | delta-motorola)
-               cpu=m68k
-               vendor=motorola
-               ;;
-       dpx2*)
-               cpu=m68k
-               vendor=bull
-               basic_os=sysv3
-               ;;
-       encore | umax | mmax)
-               cpu=ns32k
-               vendor=encore
-               ;;
-       elxsi)
-               cpu=elxsi
-               vendor=elxsi
-               basic_os=${basic_os:-bsd}
-               ;;
-       fx2800)
-               cpu=i860
-               vendor=alliant
-               ;;
-       genix)
-               cpu=ns32k
-               vendor=ns
-               ;;
-       h3050r* | hiux*)
-               cpu=hppa1.1
-               vendor=hitachi
-               basic_os=hiuxwe2
-               ;;
-       hp3k9[0-9][0-9] | hp9[0-9][0-9])
-               cpu=hppa1.0
-               vendor=hp
-               ;;
-       hp9k2[0-9][0-9] | hp9k31[0-9])
-               cpu=m68000
-               vendor=hp
-               ;;
-       hp9k3[2-9][0-9])
-               cpu=m68k
-               vendor=hp
-               ;;
-       hp9k6[0-9][0-9] | hp6[0-9][0-9])
-               cpu=hppa1.0
-               vendor=hp
-               ;;
-       hp9k7[0-79][0-9] | hp7[0-79][0-9])
-               cpu=hppa1.1
-               vendor=hp
-               ;;
-       hp9k78[0-9] | hp78[0-9])
-               # FIXME: really hppa2.0-hp
-               cpu=hppa1.1
-               vendor=hp
-               ;;
-       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | 
hp9k893 | hp893)
-               # FIXME: really hppa2.0-hp
-               cpu=hppa1.1
-               vendor=hp
-               ;;
-       hp9k8[0-9][13679] | hp8[0-9][13679])
-               cpu=hppa1.1
-               vendor=hp
-               ;;
-       hp9k8[0-9][0-9] | hp8[0-9][0-9])
-               cpu=hppa1.0
-               vendor=hp
-               ;;
-       i*86v32)
-               cpu=`echo "$1" | sed -e 's/86.*/86/'`
-               vendor=pc
-               basic_os=sysv32
-               ;;
-       i*86v4*)
-               cpu=`echo "$1" | sed -e 's/86.*/86/'`
-               vendor=pc
-               basic_os=sysv4
-               ;;
-       i*86v)
-               cpu=`echo "$1" | sed -e 's/86.*/86/'`
-               vendor=pc
-               basic_os=sysv
-               ;;
-       i*86sol2)
-               cpu=`echo "$1" | sed -e 's/86.*/86/'`
-               vendor=pc
-               basic_os=solaris2
-               ;;
-       j90 | j90-cray)
-               cpu=j90
-               vendor=cray
-               basic_os=${basic_os:-unicos}
-               ;;
-       iris | iris4d)
-               cpu=mips
-               vendor=sgi
-               case $basic_os in
-                   irix*)
-                       ;;
-                   *)
-                       basic_os=irix4
-                       ;;
-               esac
-               ;;
-       miniframe)
-               cpu=m68000
-               vendor=convergent
-               ;;
-       *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
-               cpu=m68k
-               vendor=atari
-               basic_os=mint
-               ;;
-       news-3600 | risc-news)
-               cpu=mips
-               vendor=sony
-               basic_os=newsos
-               ;;
-       next | m*-next)
-               cpu=m68k
-               vendor=next
-               case $basic_os in
-                   openstep*)
-                       ;;
-                   nextstep*)
-                       ;;
-                   ns2*)
-                     basic_os=nextstep2
-                       ;;
-                   *)
-                     basic_os=nextstep3
-                       ;;
-               esac
-               ;;
-       np1)
-               cpu=np1
-               vendor=gould
-               ;;
-       op50n-* | op60c-*)
-               cpu=hppa1.1
-               vendor=oki
-               basic_os=proelf
-               ;;
-       pa-hitachi)
-               cpu=hppa1.1
-               vendor=hitachi
-               basic_os=hiuxwe2
-               ;;
-       pbd)
-               cpu=sparc
-               vendor=tti
-               ;;
-       pbb)
-               cpu=m68k
-               vendor=tti
-               ;;
-       pc532)
-               cpu=ns32k
-               vendor=pc532
-               ;;
-       pn)
-               cpu=pn
-               vendor=gould
-               ;;
-       power)
-               cpu=power
-               vendor=ibm
-               ;;
-       ps2)
-               cpu=i386
-               vendor=ibm
-               ;;
-       rm[46]00)
-               cpu=mips
-               vendor=siemens
-               ;;
-       rtpc | rtpc-*)
-               cpu=romp
-               vendor=ibm
-               ;;
-       sde)
-               cpu=mipsisa32
-               vendor=sde
-               basic_os=${basic_os:-elf}
-               ;;
-       simso-wrs)
-               cpu=sparclite
-               vendor=wrs
-               basic_os=vxworks
-               ;;
-       tower | tower-32)
-               cpu=m68k
-               vendor=ncr
-               ;;
-       vpp*|vx|vx-*)
-               cpu=f301
-               vendor=fujitsu
-               ;;
-       w65)
-               cpu=w65
-               vendor=wdc
-               ;;
-       w89k-*)
-               cpu=hppa1.1
-               vendor=winbond
-               basic_os=proelf
-               ;;
-       none)
-               cpu=none
-               vendor=none
-               ;;
-       leon|leon[3-9])
-               cpu=sparc
-               vendor=$basic_machine
-               ;;
-       leon-*|leon[3-9]-*)
-               cpu=sparc
-               vendor=`echo "$basic_machine" | sed 's/-.*//'`
-               ;;
-
-       *-*)
-               # shellcheck disable=SC2162
-               saved_IFS=$IFS
-               IFS="-" read cpu vendor <<EOF
-$basic_machine
-EOF
-               IFS=$saved_IFS
-               ;;
-       # We use 'pc' rather than 'unknown'
-       # because (1) that's what they normally are, and
-       # (2) the word "unknown" tends to confuse beginning users.
-       i*86 | x86_64)
-               cpu=$basic_machine
-               vendor=pc
-               ;;
-       # These rules are duplicated from below for sake of the special case 
above;
-       # i.e. things that normalized to x86 arches should also default to "pc"
-       pc98)
-               cpu=i386
-               vendor=pc
-               ;;
-       x64 | amd64)
-               cpu=x86_64
-               vendor=pc
-               ;;
-       # Recognize the basic CPU types without company name.
-       *)
-               cpu=$basic_machine
-               vendor=unknown
-               ;;
-esac
-
-unset -v basic_machine
-
-# Decode basic machines in the full and proper CPU-Company form.
-case $cpu-$vendor in
-       # Here we handle the default manufacturer of certain CPU types in 
canonical form. It is in
-       # some cases the only manufacturer, in others, it is the most popular.
-       craynv-unknown)
-               vendor=cray
-               basic_os=${basic_os:-unicosmp}
-               ;;
-       c90-unknown | c90-cray)
-               vendor=cray
-               basic_os=${Basic_os:-unicos}
-               ;;
-       fx80-unknown)
-               vendor=alliant
-               ;;
-       romp-unknown)
-               vendor=ibm
-               ;;
-       mmix-unknown)
-               vendor=knuth
-               ;;
-       microblaze-unknown | microblazeel-unknown)
-               vendor=xilinx
-               ;;
-       rs6000-unknown)
-               vendor=ibm
-               ;;
-       vax-unknown)
-               vendor=dec
-               ;;
-       pdp11-unknown)
-               vendor=dec
-               ;;
-       we32k-unknown)
-               vendor=att
-               ;;
-       cydra-unknown)
-               vendor=cydrome
-               ;;
-       i370-ibm*)
-               vendor=ibm
-               ;;
-       orion-unknown)
-               vendor=highlevel
-               ;;
-       xps-unknown | xps100-unknown)
-               cpu=xps100
-               vendor=honeywell
-               ;;
-
-       # Here we normalize CPU types with a missing or matching vendor
-       armh-unknown | armh-alt)
-               cpu=armv7l
-               vendor=alt
-               basic_os=${basic_os:-linux-gnueabihf}
-               ;;
-       dpx20-unknown | dpx20-bull)
-               cpu=rs6000
-               vendor=bull
-               basic_os=${basic_os:-bosx}
-               ;;
-
-       # Here we normalize CPU types irrespective of the vendor
-       amd64-*)
-               cpu=x86_64
-               ;;
-       blackfin-*)
-               cpu=bfin
-               basic_os=linux
-               ;;
-       c54x-*)
-               cpu=tic54x
-               ;;
-       c55x-*)
-               cpu=tic55x
-               ;;
-       c6x-*)
-               cpu=tic6x
-               ;;
-       e500v[12]-*)
-               cpu=powerpc
-               basic_os=${basic_os}"spe"
-               ;;
-       mips3*-*)
-               cpu=mips64
-               ;;
-       ms1-*)
-               cpu=mt
-               ;;
-       m68knommu-*)
-               cpu=m68k
-               basic_os=linux
-               ;;
-       m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
-               cpu=s12z
-               ;;
-       openrisc-*)
-               cpu=or32
-               ;;
-       parisc-*)
-               cpu=hppa
-               basic_os=linux
-               ;;
-       pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
-               cpu=i586
-               ;;
-       pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*)
-               cpu=i686
-               ;;
-       pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
-               cpu=i686
-               ;;
-       pentium4-*)
-               cpu=i786
-               ;;
-       pc98-*)
-               cpu=i386
-               ;;
-       ppc-* | ppcbe-*)
-               cpu=powerpc
-               ;;
-       ppcle-* | powerpclittle-*)
-               cpu=powerpcle
-               ;;
-       ppc64-*)
-               cpu=powerpc64
-               ;;
-       ppc64le-* | powerpc64little-*)
-               cpu=powerpc64le
-               ;;
-       sb1-*)
-               cpu=mipsisa64sb1
-               ;;
-       sb1el-*)
-               cpu=mipsisa64sb1el
-               ;;
-       sh5e[lb]-*)
-               cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
-               ;;
-       spur-*)
-               cpu=spur
-               ;;
-       strongarm-* | thumb-*)
-               cpu=arm
-               ;;
-       tx39-*)
-               cpu=mipstx39
-               ;;
-       tx39el-*)
-               cpu=mipstx39el
-               ;;
-       x64-*)
-               cpu=x86_64
-               ;;
-       xscale-* | xscalee[bl]-*)
-               cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
-               ;;
-       arm64-* | aarch64le-*)
-               cpu=aarch64
-               ;;
-
-       # Recognize the canonical CPU Types that limit and/or modify the
-       # company names they are paired with.
-       cr16-*)
-               basic_os=${basic_os:-elf}
-               ;;
-       crisv32-* | etraxfs*-*)
-               cpu=crisv32
-               vendor=axis
-               ;;
-       cris-* | etrax*-*)
-               cpu=cris
-               vendor=axis
-               ;;
-       crx-*)
-               basic_os=${basic_os:-elf}
-               ;;
-       neo-tandem)
-               cpu=neo
-               vendor=tandem
-               ;;
-       nse-tandem)
-               cpu=nse
-               vendor=tandem
-               ;;
-       nsr-tandem)
-               cpu=nsr
-               vendor=tandem
-               ;;
-       nsv-tandem)
-               cpu=nsv
-               vendor=tandem
-               ;;
-       nsx-tandem)
-               cpu=nsx
-               vendor=tandem
-               ;;
-       mipsallegrexel-sony)
-               cpu=mipsallegrexel
-               vendor=sony
-               ;;
-       tile*-*)
-               basic_os=${basic_os:-linux-gnu}
-               ;;
-
-       *)
-               # Recognize the canonical CPU types that are allowed with any
-               # company name.
-               case $cpu in
-                       1750a | 580 \
-                       | a29k \
-                       | aarch64 | aarch64_be \
-                       | abacus \
-                       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
-                       | alpha64 | alpha64ev[4-8] | alpha64ev56 | 
alpha64ev6[78] \
-                       | alphapca5[67] | alpha64pca5[67] \
-                       | am33_2.0 \
-                       | amdgcn \
-                       | arc | arceb | arc32 | arc64 \
-                       | arm | arm[lb]e | arme[lb] | armv* \
-                       | avr | avr32 \
-                       | asmjs \
-                       | ba \
-                       | be32 | be64 \
-                       | bfin | bpf | bs2000 \
-                       | c[123]* | c30 | [cjt]90 | c4x \
-                       | c8051 | clipper | craynv | csky | cydra \
-                       | d10v | d30v | dlx | dsp16xx \
-                       | e2k | elxsi | epiphany \
-                       | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
-                       | h8300 | h8500 \
-                       | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
-                       | hexagon \
-                       | i370 | i*86 | i860 | i960 | ia16 | ia64 \
-                       | ip2k | iq2000 \
-                       | k1om \
-                       | kvx \
-                       | le32 | le64 \
-                       | lm32 \
-                       | loongarch32 | loongarch64 \
-                       | m32c | m32r | m32rle \
-                       | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | 
m68k \
-                       | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
-                       | m88110 | m88k | maxq | mb | mcore | mep | metag \
-                       | microblaze | microblazeel \
-                       | mips* \
-                       | mmix \
-                       | mn10200 | mn10300 \
-                       | moxie \
-                       | mt \
-                       | msp430 \
-                       | nds32 | nds32le | nds32be \
-                       | nfp \
-                       | nios | nios2 | nios2eb | nios2el \
-                       | none | np1 | ns16k | ns32k | nvptx \
-                       | open8 \
-                       | or1k* \
-                       | or32 \
-                       | orion \
-                       | picochip \
-                       | pdp10 | pdp11 | pj | pjl | pn | power \
-                       | powerpc | powerpc64 | powerpc64le | powerpcle | 
powerpcspe \
-                       | pru \
-                       | pyramid \
-                       | riscv | riscv32 | riscv32be | riscv64 | riscv64be \
-                       | rl78 | romp | rs6000 | rx \
-                       | s390 | s390x \
-                       | score \
-                       | sh | shl \
-                       | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] 
| sh[lb]e \
-                       | sh[1234]e[lb] |  sh[12345][lb]e | sh[23]ele | sh64 | 
sh64le \
-                       | sparc | sparc64 | sparc64b | sparc64v | sparc86x | 
sparclet \
-                       | sparclite \
-                       | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
-                       | spu \
-                       | tahoe \
-                       | thumbv7* \
-                       | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
-                       | tron \
-                       | ubicom32 \
-                       | v70 | v850 | v850e | v850e1 | v850es | v850e2 | 
v850e2v3 \
-                       | vax \
-                       | visium \
-                       | w65 \
-                       | wasm32 | wasm64 \
-                       | we32k \
-                       | x86 | x86_64 | xc16x | xgate | xps100 \
-                       | xstormy16 | xtensa* \
-                       | ymp \
-                       | z8k | z80)
-                               ;;
-
-                       *)
-                               echo "Invalid configuration '$1': machine 
'$cpu-$vendor' not recognized" 1>&2
-                               exit 1
-                               ;;
-               esac
-               ;;
-esac
-
-# Here we canonicalize certain aliases for manufacturers.
-case $vendor in
-       digital*)
-               vendor=dec
-               ;;
-       commodore*)
-               vendor=cbm
-               ;;
-       *)
-               ;;
-esac
-
-# Decode manufacturer-specific aliases for certain operating systems.
-
-if test x$basic_os != x
-then
-
-# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
-# set os.
-case $basic_os in
-       gnu/linux*)
-               kernel=linux
-               os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
-               ;;
-       os2-emx)
-               kernel=os2
-               os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
-               ;;
-       nto-qnx*)
-               kernel=nto
-               os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
-               ;;
-       *-*)
-               # shellcheck disable=SC2162
-               saved_IFS=$IFS
-               IFS="-" read kernel os <<EOF
-$basic_os
-EOF
-               IFS=$saved_IFS
-               ;;
-       # Default OS when just kernel was specified
-       nto*)
-               kernel=nto
-               os=`echo "$basic_os" | sed -e 's|nto|qnx|'`
-               ;;
-       linux*)
-               kernel=linux
-               os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
-               ;;
-       managarm*)
-               kernel=managarm
-               os=`echo "$basic_os" | sed -e 's|managarm|mlibc|'`
-               ;;
-       *)
-               kernel=
-               os=$basic_os
-               ;;
-esac
-
-# Now, normalize the OS (knowing we just have one component, it's not a kernel,
-# etc.)
-case $os in
-       # First match some system type aliases that might get confused
-       # with valid system types.
-       # solaris* is a basic system type, with this one exception.
-       auroraux)
-               os=auroraux
-               ;;
-       bluegene*)
-               os=cnk
-               ;;
-       solaris1 | solaris1.*)
-               os=`echo "$os" | sed -e 's|solaris1|sunos4|'`
-               ;;
-       solaris)
-               os=solaris2
-               ;;
-       unixware*)
-               os=sysv4.2uw
-               ;;
-       # es1800 is here to avoid being matched by es* (a different OS)
-       es1800*)
-               os=ose
-               ;;
-       # Some version numbers need modification
-       chorusos*)
-               os=chorusos
-               ;;
-       isc)
-               os=isc2.2
-               ;;
-       sco6)
-               os=sco5v6
-               ;;
-       sco5)
-               os=sco3.2v5
-               ;;
-       sco4)
-               os=sco3.2v4
-               ;;
-       sco3.2.[4-9]*)
-               os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'`
-               ;;
-       sco*v* | scout)
-               # Don't match below
-               ;;
-       sco*)
-               os=sco3.2v2
-               ;;
-       psos*)
-               os=psos
-               ;;
-       qnx*)
-               os=qnx
-               ;;
-       hiux*)
-               os=hiuxwe2
-               ;;
-       lynx*178)
-               os=lynxos178
-               ;;
-       lynx*5)
-               os=lynxos5
-               ;;
-       lynxos*)
-               # don't get caught up in next wildcard
-               ;;
-       lynx*)
-               os=lynxos
-               ;;
-       mac[0-9]*)
-               os=`echo "$os" | sed -e 's|mac|macos|'`
-               ;;
-       opened*)
-               os=openedition
-               ;;
-       os400*)
-               os=os400
-               ;;
-       sunos5*)
-               os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
-               ;;
-       sunos6*)
-               os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
-               ;;
-       wince*)
-               os=wince
-               ;;
-       utek*)
-               os=bsd
-               ;;
-       dynix*)
-               os=bsd
-               ;;
-       acis*)
-               os=aos
-               ;;
-       atheos*)
-               os=atheos
-               ;;
-       syllable*)
-               os=syllable
-               ;;
-       386bsd)
-               os=bsd
-               ;;
-       ctix* | uts*)
-               os=sysv
-               ;;
-       nova*)
-               os=rtmk-nova
-               ;;
-       ns2)
-               os=nextstep2
-               ;;
-       # Preserve the version number of sinix5.
-       sinix5.*)
-               os=`echo "$os" | sed -e 's|sinix|sysv|'`
-               ;;
-       sinix*)
-               os=sysv4
-               ;;
-       tpf*)
-               os=tpf
-               ;;
-       triton*)
-               os=sysv3
-               ;;
-       oss*)
-               os=sysv3
-               ;;
-       svr4*)
-               os=sysv4
-               ;;
-       svr3)
-               os=sysv3
-               ;;
-       sysvr4)
-               os=sysv4
-               ;;
-       ose*)
-               os=ose
-               ;;
-       *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
-               os=mint
-               ;;
-       dicos*)
-               os=dicos
-               ;;
-       pikeos*)
-               # Until real need of OS specific support for
-               # particular features comes up, bare metal
-               # configurations are quite functional.
-               case $cpu in
-                   arm*)
-                       os=eabi
-                       ;;
-                   *)
-                       os=elf
-                       ;;
-               esac
-               ;;
-       *)
-               # No normalization, but not necessarily accepted, that comes 
below.
-               ;;
-esac
-
-else
-
-# Here we handle the default operating systems that come with various machines.
-# The value should be what the vendor currently ships out the door with their
-# machine or put another way, the most popular os provided with the machine.
-
-# Note that if you're going to try to match "-MANUFACTURER" here (say,
-# "-sun"), then you have to tell the case statement up towards the top
-# that MANUFACTURER isn't an operating system.  Otherwise, code above
-# will signal an error saying that MANUFACTURER isn't an operating
-# system, and we'll never get to this point.
-
-kernel=
-case $cpu-$vendor in
-       score-*)
-               os=elf
-               ;;
-       spu-*)
-               os=elf
-               ;;
-       *-acorn)
-               os=riscix1.2
-               ;;
-       arm*-rebel)
-               kernel=linux
-               os=gnu
-               ;;
-       arm*-semi)
-               os=aout
-               ;;
-       c4x-* | tic4x-*)
-               os=coff
-               ;;
-       c8051-*)
-               os=elf
-               ;;
-       clipper-intergraph)
-               os=clix
-               ;;
-       hexagon-*)
-               os=elf
-               ;;
-       tic54x-*)
-               os=coff
-               ;;
-       tic55x-*)
-               os=coff
-               ;;
-       tic6x-*)
-               os=coff
-               ;;
-       # This must come before the *-dec entry.
-       pdp10-*)
-               os=tops20
-               ;;
-       pdp11-*)
-               os=none
-               ;;
-       *-dec | vax-*)
-               os=ultrix4.2
-               ;;
-       m68*-apollo)
-               os=domain
-               ;;
-       i386-sun)
-               os=sunos4.0.2
-               ;;
-       m68000-sun)
-               os=sunos3
-               ;;
-       m68*-cisco)
-               os=aout
-               ;;
-       mep-*)
-               os=elf
-               ;;
-       mips*-cisco)
-               os=elf
-               ;;
-       mips*-*)
-               os=elf
-               ;;
-       or32-*)
-               os=coff
-               ;;
-       *-tti)  # must be before sparc entry or we get the wrong os.
-               os=sysv3
-               ;;
-       sparc-* | *-sun)
-               os=sunos4.1.1
-               ;;
-       pru-*)
-               os=elf
-               ;;
-       *-be)
-               os=beos
-               ;;
-       *-ibm)
-               os=aix
-               ;;
-       *-knuth)
-               os=mmixware
-               ;;
-       *-wec)
-               os=proelf
-               ;;
-       *-winbond)
-               os=proelf
-               ;;
-       *-oki)
-               os=proelf
-               ;;
-       *-hp)
-               os=hpux
-               ;;
-       *-hitachi)
-               os=hiux
-               ;;
-       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
-               os=sysv
-               ;;
-       *-cbm)
-               os=amigaos
-               ;;
-       *-dg)
-               os=dgux
-               ;;
-       *-dolphin)
-               os=sysv3
-               ;;
-       m68k-ccur)
-               os=rtu
-               ;;
-       m88k-omron*)
-               os=luna
-               ;;
-       *-next)
-               os=nextstep
-               ;;
-       *-sequent)
-               os=ptx
-               ;;
-       *-crds)
-               os=unos
-               ;;
-       *-ns)
-               os=genix
-               ;;
-       i370-*)
-               os=mvs
-               ;;
-       *-gould)
-               os=sysv
-               ;;
-       *-highlevel)
-               os=bsd
-               ;;
-       *-encore)
-               os=bsd
-               ;;
-       *-sgi)
-               os=irix
-               ;;
-       *-siemens)
-               os=sysv4
-               ;;
-       *-masscomp)
-               os=rtu
-               ;;
-       f30[01]-fujitsu | f700-fujitsu)
-               os=uxpv
-               ;;
-       *-rom68k)
-               os=coff
-               ;;
-       *-*bug)
-               os=coff
-               ;;
-       *-apple)
-               os=macos
-               ;;
-       *-atari*)
-               os=mint
-               ;;
-       *-wrs)
-               os=vxworks
-               ;;
-       *)
-               os=none
-               ;;
-esac
-
-fi
-
-# Now, validate our (potentially fixed-up) OS.
-case $os in
-       # Sometimes we do "kernel-libc", so those need to count as OSes.
-       musl* | newlib* | relibc* | uclibc*)
-               ;;
-       # Likewise for "kernel-abi"
-       eabi* | gnueabi*)
-               ;;
-       # VxWorks passes extra cpu info in the 4th filed.
-       simlinux | simwindows | spe)
-               ;;
-       # Now accept the basic system types.
-       # The portable systems comes first.
-       # Each alternative MUST end in a * to match a version number.
-       gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
-            | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
-            | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
-            | sym* |  plan9* | psp* | sim* | xray* | os68k* | v88r* \
-            | hiux* | abug | nacl* | netware* | windows* \
-            | os9* | macos* | osx* | ios* | tvos* | watchos* \
-            | mpw* | magic* | mmixware* | mon960* | lnews* \
-            | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
-            | aos* | aros* | cloudabi* | sortix* | twizzler* \
-            | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
-            | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
-            | mirbsd* | netbsd* | dicos* | openedition* | ose* \
-            | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
-            | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
-            | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
-            | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
-            | udi* | lites* | ieee* | go32* | aux* | hcos* \
-            | chorusrdb* | cegcc* | glidix* | serenity* \
-            | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
-            | midipix* | mingw32* | mingw64* | mint* \
-            | uxpv* | beos* | mpeix* | udk* | moxiebox* \
-            | interix* | uwin* | mks* | rhapsody* | darwin* \
-            | openstep* | oskit* | conix* | pw32* | nonstopux* \
-            | storm-chaos* | tops10* | tenex* | tops20* | its* \
-            | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
-            | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
-            | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
-            | skyos* | haiku* | rdos* | toppers* | drops* | es* \
-            | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
-            | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
-            | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
-            | fiwix* | mlibc* | cos* | mbr* )
-               ;;
-       # This one is extra strict with allowed versions
-       sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
-               # Don't forget version if it is 3.2v4 or newer.
-               ;;
-       none)
-               ;;
-       kernel* | msvc* )
-               # Restricted further below
-               ;;
-       *)
-               echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2
-               exit 1
-               ;;
-esac
-
-# As a final step for OS-related things, validate the OS-kernel combination
-# (given a valid OS), if there is a kernel.
-case $kernel-$os in
-       linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
-                  | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* 
)
-               ;;
-       uclinux-uclibc* )
-               ;;
-       managarm-mlibc* | managarm-kernel* )
-               ;;
-       windows*-gnu* | windows*-msvc*)
-               ;;
-       -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* )
-               # These are just libc implementations, not actual OSes, and thus
-               # require a kernel.
-               echo "Invalid configuration '$1': libc '$os' needs explicit 
kernel." 1>&2
-               exit 1
-               ;;
-       -kernel* )
-               echo "Invalid configuration '$1': '$os' needs explicit kernel." 
1>&2
-               exit 1
-               ;;
-       *-kernel* )
-               echo "Invalid configuration '$1': '$kernel' does not support 
'$os'." 1>&2
-               exit 1
-               ;;
-       *-msvc* )
-               echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2
-               exit 1
-               ;;
-       kfreebsd*-gnu* | kopensolaris*-gnu*)
-               ;;
-       vxworks-simlinux | vxworks-simwindows | vxworks-spe)
-               ;;
-       nto-qnx*)
-               ;;
-       os2-emx)
-               ;;
-       *-eabi* | *-gnueabi*)
-               ;;
-       none-coff* | none-elf*)
-               # None (no kernel, i.e. freestanding / bare metal),
-               # can be paired with an output format "OS"
-               ;;
-       -*)
-               # Blank kernel with real OS is always fine.
-               ;;
-       *-*)
-               echo "Invalid configuration '$1': Kernel '$kernel' not known to 
work with OS '$os'." 1>&2
-               exit 1
-               ;;
-esac
-
-# Here we handle the case where we know the os, and the CPU type, but not the
-# manufacturer.  We pick the logical manufacturer.
-case $vendor in
-       unknown)
-               case $cpu-$os in
-                       *-riscix*)
-                               vendor=acorn
-                               ;;
-                       *-sunos*)
-                               vendor=sun
-                               ;;
-                       *-cnk* | *-aix*)
-                               vendor=ibm
-                               ;;
-                       *-beos*)
-                               vendor=be
-                               ;;
-                       *-hpux*)
-                               vendor=hp
-                               ;;
-                       *-mpeix*)
-                               vendor=hp
-                               ;;
-                       *-hiux*)
-                               vendor=hitachi
-                               ;;
-                       *-unos*)
-                               vendor=crds
-                               ;;
-                       *-dgux*)
-                               vendor=dg
-                               ;;
-                       *-luna*)
-                               vendor=omron
-                               ;;
-                       *-genix*)
-                               vendor=ns
-                               ;;
-                       *-clix*)
-                               vendor=intergraph
-                               ;;
-                       *-mvs* | *-opened*)
-                               vendor=ibm
-                               ;;
-                       *-os400*)
-                               vendor=ibm
-                               ;;
-                       s390-* | s390x-*)
-                               vendor=ibm
-                               ;;
-                       *-ptx*)
-                               vendor=sequent
-                               ;;
-                       *-tpf*)
-                               vendor=ibm
-                               ;;
-                       *-vxsim* | *-vxworks* | *-windiss*)
-                               vendor=wrs
-                               ;;
-                       *-aux*)
-                               vendor=apple
-                               ;;
-                       *-hms*)
-                               vendor=hitachi
-                               ;;
-                       *-mpw* | *-macos*)
-                               vendor=apple
-                               ;;
-                       *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
-                               vendor=atari
-                               ;;
-                       *-vos*)
-                               vendor=stratus
-                               ;;
-               esac
-               ;;
-esac
-
-echo "$cpu-$vendor-${kernel:+$kernel-}$os"
-exit
-
-# Local variables:
-# eval: (add-hook 'before-save-hook 'time-stamp)
-# time-stamp-start: "timestamp='"
-# time-stamp-format: "%:y-%02m-%02d"
-# time-stamp-end: "'"
-# End:
diff --git a/exec/configure.ac b/exec/configure.ac
index 180c200d13d..317250332cb 100644
--- a/exec/configure.ac
+++ b/exec/configure.ac
@@ -4,7 +4,7 @@ dnl     autoconf
 dnl in the directory containing this script.
 dnl If you changed any AC_DEFINES, also run autoheader.
 dnl
-dnl Copyright (C) 2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2023-2024 Free Software Foundation, Inc.
 dnl
 dnl  This file is part of GNU Emacs.
 dnl
@@ -25,7 +25,7 @@ AC_PREREQ([2.65])
 AC_INIT([libexec], [30.0.50], [bug-gnu-emacs@gnu.org], [],
   [https://www.gnu.org/software/emacs/])
 
-AH_TOP([/* Copyright (C) 2023 Free Software Foundation, Inc.
+AH_TOP([/* Copyright (C) 2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -131,6 +131,8 @@ AH_TEMPLATE([CLONE_SYSCALL], [Define to number of the 
`clone' system call.])
 AH_TEMPLATE([CLONE3_SYSCALL], [Define to number of the `clone3' system call.])
 AH_TEMPLATE([READLINK_SYSCALL], [Define to number of the `readlink' system 
call.])
 AH_TEMPLATE([READLINKAT_SYSCALL], [Define to number of the `readlinkat' system 
call.])
+AH_TEMPLATE([OPEN_SYSCALL], [Define to number of the `open' system call.])
+AH_TEMPLATE([OPENAT_SYSCALL], [Define to number of the `openat' system call.])
 AH_TEMPLATE([REENTRANT], [Define to 1 if the library is used within a signal 
handler.])
 
 AC_CANONICAL_HOST
@@ -257,6 +259,8 @@ AS_CASE([$host], [x86_64-*linux*],
      AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
      AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
      AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
+     AC_DEFINE([OPEN_SYSCALL], [__NR_open])
+     AC_DEFINE([OPENAT_SYSCALL], [__NR_openat])
      exec_CHECK_LINUX_CLONE3
      # Make sure the loader doesn't conflict with other position
      # dependent code.
@@ -285,6 +289,8 @@ AS_CASE([$host], [x86_64-*linux*],
      AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
      AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
      AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
+     AC_DEFINE([OPEN_SYSCALL], [__NR_open])
+     AC_DEFINE([OPENAT_SYSCALL], [__NR_openat])
      exec_CHECK_LINUX_CLONE3
      # Make sure the loader doesn't conflict with other position
      # dependent code.
@@ -312,8 +318,9 @@ AS_CASE([$host], [x86_64-*linux*],
      AC_DEFINE([INTERPRETER_BASE], [0x3f00000000])
      AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
      AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
-     # Note that aarch64 has no `readlink'.
+     # Note that aarch64 has neither `readlink' nor `open'.
      AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
+     AC_DEFINE([OPENAT_SYSCALL], [__NR_openat])
      exec_CHECK_LINUX_CLONE3
      # Make sure the loader doesn't conflict with other position
      # dependent code.  ARM places rather significant restrictions on
@@ -343,6 +350,8 @@ AS_CASE([$host], [x86_64-*linux*],
      AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
      AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
      AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
+     AC_DEFINE([OPEN_SYSCALL], [__NR_open])
+     AC_DEFINE([OPENAT_SYSCALL], [__NR_openat])
      exec_CHECK_LINUX_CLONE3
      LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
      exec_loader=loader-armeabi.s],
@@ -365,6 +374,8 @@ AS_CASE([$host], [x86_64-*linux*],
        AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
        AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
        AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
+       AC_DEFINE([OPEN_SYSCALL], [__NR_open])
+       AC_DEFINE([OPENAT_SYSCALL], [__NR_openat])
        exec_CHECK_LINUX_CLONE3
        LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
        exec_loader=loader-armeabi.s],
@@ -393,6 +404,8 @@ AS_CASE([$host], [x86_64-*linux*],
    AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
    AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
    AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
+   AC_DEFINE([OPEN_SYSCALL], [__NR_open])
+   AC_DEFINE([OPENAT_SYSCALL], [__NR_openat])
    AC_CHECK_DECL([_MIPS_SIM], [exec_CHECK_MIPS_NABI],
      [AC_MSG_ERROR([_MIPS_SIM could not be determined]),
      [[
@@ -421,6 +434,8 @@ AS_CASE([$host], [x86_64-*linux*],
    AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
    AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
    AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
+   AC_DEFINE([OPEN_SYSCALL], [__NR_open])
+   AC_DEFINE([OPENAT_SYSCALL], [__NR_openat])
    AC_CACHE_CHECK([whether as understands `daddi'],
      [exec_cv_as_daddi],
      [exec_cv_as_daddi=no
diff --git a/exec/deps.mk b/exec/deps.mk
index 20fcd2dbc5a..2425503ab44 100644
--- a/exec/deps.mk
+++ b/exec/deps.mk
@@ -1,6 +1,6 @@
 ### deps.mk
 
-## Copyright (C) 2023 Free Software Foundation, Inc.
+## Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ## This file is part of GNU Emacs.
 
diff --git a/exec/exec.c b/exec/exec.c
index 231b5b1c46a..254a983f25f 100644
--- a/exec/exec.c
+++ b/exec/exec.c
@@ -1,6 +1,6 @@
 /* Program execution for Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/exec/exec.h b/exec/exec.h
index 8ee74d7ca8b..ad1b50276c8 100644
--- a/exec/exec.h
+++ b/exec/exec.h
@@ -1,6 +1,6 @@
 /* Program execution for Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -148,6 +148,10 @@ struct exec_tracee
   /* The next process being traced.  */
   struct exec_tracee *next;
 
+  /* Address of any stack pointer to restore after system call
+     completion.  */
+  USER_WORD sp;
+
   /* The thread ID of this process.  */
   pid_t pid;
 
diff --git a/exec/exec1.c b/exec/exec1.c
index d77ca8adf54..aaff9a94c62 100644
--- a/exec/exec1.c
+++ b/exec/exec1.c
@@ -1,6 +1,6 @@
 /* Program execution for Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -53,7 +53,7 @@ main (int argc, char **argv)
 
       tracing_execve (argv[2], argv + 2, environ);
 
-      /* An error occured.  Exit with failure.  */
+      /* An error occurred.  Exit with failure.  */
       exit (127);
     }
   else
diff --git a/exec/install-sh b/exec/install-sh
deleted file mode 100755
index e046efdf0a3..00000000000
--- a/exec/install-sh
+++ /dev/null
@@ -1,541 +0,0 @@
-#!/usr/bin/sh
-# install - install a program, script, or datafile
-
-scriptversion=2020-11-14.01; # UTC
-
-# This originates from X11R5 (mit/util/scripts/install.sh), which was
-# later released in X11R6 (xc/config/util/install.sh) with the
-# following copyright and license.
-#
-# Copyright (C) 1994 X Consortium
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
-# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Except as contained in this notice, the name of the X Consortium shall not
-# be used in advertising or otherwise to promote the sale, use or other deal-
-# ings in this Software without prior written authorization from the X Consor-
-# tium.
-#
-#
-# FSF changes to this file are in the public domain.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# 'make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch.
-
-tab='  '
-nl='
-'
-IFS=" $tab$nl"
-
-# Set DOITPROG to "echo" to test this script.
-
-doit=${DOITPROG-}
-doit_exec=${doit:-exec}
-
-# Put in absolute file names if you don't have them in your path;
-# or use environment vars.
-
-chgrpprog=${CHGRPPROG-chgrp}
-chmodprog=${CHMODPROG-chmod}
-chownprog=${CHOWNPROG-chown}
-cmpprog=${CMPPROG-cmp}
-cpprog=${CPPROG-cp}
-mkdirprog=${MKDIRPROG-mkdir}
-mvprog=${MVPROG-mv}
-rmprog=${RMPROG-rm}
-stripprog=${STRIPPROG-strip}
-
-posix_mkdir=
-
-# Desired mode of installed file.
-mode=0755
-
-# Create dirs (including intermediate dirs) using mode 755.
-# This is like GNU 'install' as of coreutils 8.32 (2020).
-mkdir_umask=22
-
-backupsuffix=
-chgrpcmd=
-chmodcmd=$chmodprog
-chowncmd=
-mvcmd=$mvprog
-rmcmd="$rmprog -f"
-stripcmd=
-
-src=
-dst=
-dir_arg=
-dst_arg=
-
-copy_on_change=false
-is_target_a_directory=possibly
-
-usage="\
-Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
-   or: $0 [OPTION]... SRCFILES... DIRECTORY
-   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
-   or: $0 [OPTION]... -d DIRECTORIES...
-
-In the 1st form, copy SRCFILE to DSTFILE.
-In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
-In the 4th, create DIRECTORIES.
-
-Options:
-     --help     display this help and exit.
-     --version  display version info and exit.
-
-  -c            (ignored)
-  -C            install only if different (preserve data modification time)
-  -d            create directories instead of installing files.
-  -g GROUP      $chgrpprog installed files to GROUP.
-  -m MODE       $chmodprog installed files to MODE.
-  -o USER       $chownprog installed files to USER.
-  -p            pass -p to $cpprog.
-  -s            $stripprog installed files.
-  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
-  -t DIRECTORY  install into DIRECTORY.
-  -T            report an error if DSTFILE is a directory.
-
-Environment variables override the default commands:
-  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
-  RMPROG STRIPPROG
-
-By default, rm is invoked with -f; when overridden with RMPROG,
-it's up to you to specify -f if you want it.
-
-If -S is not specified, no backups are attempted.
-
-Email bug reports to bug-automake@gnu.org.
-Automake home page: https://www.gnu.org/software/automake/
-"
-
-while test $# -ne 0; do
-  case $1 in
-    -c) ;;
-
-    -C) copy_on_change=true;;
-
-    -d) dir_arg=true;;
-
-    -g) chgrpcmd="$chgrpprog $2"
-        shift;;
-
-    --help) echo "$usage"; exit $?;;
-
-    -m) mode=$2
-        case $mode in
-          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
-            echo "$0: invalid mode: $mode" >&2
-            exit 1;;
-        esac
-        shift;;
-
-    -o) chowncmd="$chownprog $2"
-        shift;;
-
-    -p) cpprog="$cpprog -p";;
-
-    -s) stripcmd=$stripprog;;
-
-    -S) backupsuffix="$2"
-        shift;;
-
-    -t)
-        is_target_a_directory=always
-        dst_arg=$2
-        # Protect names problematic for 'test' and other utilities.
-        case $dst_arg in
-          -* | [=\(\)!]) dst_arg=./$dst_arg;;
-        esac
-        shift;;
-
-    -T) is_target_a_directory=never;;
-
-    --version) echo "$0 $scriptversion"; exit $?;;
-
-    --) shift
-        break;;
-
-    -*) echo "$0: invalid option: $1" >&2
-        exit 1;;
-
-    *)  break;;
-  esac
-  shift
-done
-
-# We allow the use of options -d and -T together, by making -d
-# take the precedence; this is for compatibility with GNU install.
-
-if test -n "$dir_arg"; then
-  if test -n "$dst_arg"; then
-    echo "$0: target directory not allowed when installing a directory." >&2
-    exit 1
-  fi
-fi
-
-if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
-  # When -d is used, all remaining arguments are directories to create.
-  # When -t is used, the destination is already specified.
-  # Otherwise, the last argument is the destination.  Remove it from $@.
-  for arg
-  do
-    if test -n "$dst_arg"; then
-      # $@ is not empty: it contains at least $arg.
-      set fnord "$@" "$dst_arg"
-      shift # fnord
-    fi
-    shift # arg
-    dst_arg=$arg
-    # Protect names problematic for 'test' and other utilities.
-    case $dst_arg in
-      -* | [=\(\)!]) dst_arg=./$dst_arg;;
-    esac
-  done
-fi
-
-if test $# -eq 0; then
-  if test -z "$dir_arg"; then
-    echo "$0: no input file specified." >&2
-    exit 1
-  fi
-  # It's OK to call 'install-sh -d' without argument.
-  # This can happen when creating conditional directories.
-  exit 0
-fi
-
-if test -z "$dir_arg"; then
-  if test $# -gt 1 || test "$is_target_a_directory" = always; then
-    if test ! -d "$dst_arg"; then
-      echo "$0: $dst_arg: Is not a directory." >&2
-      exit 1
-    fi
-  fi
-fi
-
-if test -z "$dir_arg"; then
-  do_exit='(exit $ret); exit $ret'
-  trap "ret=129; $do_exit" 1
-  trap "ret=130; $do_exit" 2
-  trap "ret=141; $do_exit" 13
-  trap "ret=143; $do_exit" 15
-
-  # Set umask so as not to create temps with too-generous modes.
-  # However, 'strip' requires both read and write access to temps.
-  case $mode in
-    # Optimize common cases.
-    *644) cp_umask=133;;
-    *755) cp_umask=22;;
-
-    *[0-7])
-      if test -z "$stripcmd"; then
-        u_plus_rw=
-      else
-        u_plus_rw='% 200'
-      fi
-      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
-    *)
-      if test -z "$stripcmd"; then
-        u_plus_rw=
-      else
-        u_plus_rw=,u+rw
-      fi
-      cp_umask=$mode$u_plus_rw;;
-  esac
-fi
-
-for src
-do
-  # Protect names problematic for 'test' and other utilities.
-  case $src in
-    -* | [=\(\)!]) src=./$src;;
-  esac
-
-  if test -n "$dir_arg"; then
-    dst=$src
-    dstdir=$dst
-    test -d "$dstdir"
-    dstdir_status=$?
-    # Don't chown directories that already exist.
-    if test $dstdir_status = 0; then
-      chowncmd=""
-    fi
-  else
-
-    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
-    # might cause directories to be created, which would be especially bad
-    # if $src (and thus $dsttmp) contains '*'.
-    if test ! -f "$src" && test ! -d "$src"; then
-      echo "$0: $src does not exist." >&2
-      exit 1
-    fi
-
-    if test -z "$dst_arg"; then
-      echo "$0: no destination specified." >&2
-      exit 1
-    fi
-    dst=$dst_arg
-
-    # If destination is a directory, append the input filename.
-    if test -d "$dst"; then
-      if test "$is_target_a_directory" = never; then
-        echo "$0: $dst_arg: Is a directory" >&2
-        exit 1
-      fi
-      dstdir=$dst
-      dstbase=`basename "$src"`
-      case $dst in
-       */) dst=$dst$dstbase;;
-       *)  dst=$dst/$dstbase;;
-      esac
-      dstdir_status=0
-    else
-      dstdir=`dirname "$dst"`
-      test -d "$dstdir"
-      dstdir_status=$?
-    fi
-  fi
-
-  case $dstdir in
-    */) dstdirslash=$dstdir;;
-    *)  dstdirslash=$dstdir/;;
-  esac
-
-  obsolete_mkdir_used=false
-
-  if test $dstdir_status != 0; then
-    case $posix_mkdir in
-      '')
-        # With -d, create the new directory with the user-specified mode.
-        # Otherwise, rely on $mkdir_umask.
-        if test -n "$dir_arg"; then
-          mkdir_mode=-m$mode
-        else
-          mkdir_mode=
-        fi
-
-        posix_mkdir=false
-       # The $RANDOM variable is not portable (e.g., dash).  Use it
-       # here however when possible just to lower collision chance.
-       tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
-
-       trap '
-         ret=$?
-         rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
-         exit $ret
-       ' 0
-
-       # Because "mkdir -p" follows existing symlinks and we likely work
-       # directly in world-writeable /tmp, make sure that the '$tmpdir'
-       # directory is successfully created first before we actually test
-       # 'mkdir -p'.
-       if (umask $mkdir_umask &&
-           $mkdirprog $mkdir_mode "$tmpdir" &&
-           exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
-       then
-         if test -z "$dir_arg" || {
-              # Check for POSIX incompatibilities with -m.
-              # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
-              # other-writable bit of parent directory when it shouldn't.
-              # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
-              test_tmpdir="$tmpdir/a"
-              ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
-              case $ls_ld_tmpdir in
-                d????-?r-*) different_mode=700;;
-                d????-?--*) different_mode=755;;
-                *) false;;
-              esac &&
-              $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
-                ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
-                test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
-              }
-            }
-         then posix_mkdir=:
-         fi
-         rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
-       else
-         # Remove any dirs left behind by ancient mkdir implementations.
-         rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
-       fi
-       trap '' 0;;
-    esac
-
-    if
-      $posix_mkdir && (
-        umask $mkdir_umask &&
-        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
-      )
-    then :
-    else
-
-      # mkdir does not conform to POSIX,
-      # or it failed possibly due to a race condition.  Create the
-      # directory the slow way, step by step, checking for races as we go.
-
-      case $dstdir in
-        /*) prefix='/';;
-        [-=\(\)!]*) prefix='./';;
-        *)  prefix='';;
-      esac
-
-      oIFS=$IFS
-      IFS=/
-      set -f
-      set fnord $dstdir
-      shift
-      set +f
-      IFS=$oIFS
-
-      prefixes=
-
-      for d
-      do
-        test X"$d" = X && continue
-
-        prefix=$prefix$d
-        if test -d "$prefix"; then
-          prefixes=
-        else
-          if $posix_mkdir; then
-            (umask $mkdir_umask &&
-             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
-            # Don't fail if two instances are running concurrently.
-            test -d "$prefix" || exit 1
-          else
-            case $prefix in
-              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
-              *) qprefix=$prefix;;
-            esac
-            prefixes="$prefixes '$qprefix'"
-          fi
-        fi
-        prefix=$prefix/
-      done
-
-      if test -n "$prefixes"; then
-        # Don't fail if two instances are running concurrently.
-        (umask $mkdir_umask &&
-         eval "\$doit_exec \$mkdirprog $prefixes") ||
-          test -d "$dstdir" || exit 1
-        obsolete_mkdir_used=true
-      fi
-    fi
-  fi
-
-  if test -n "$dir_arg"; then
-    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
-    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
-    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
-      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
-  else
-
-    # Make a couple of temp file names in the proper directory.
-    dsttmp=${dstdirslash}_inst.$$_
-    rmtmp=${dstdirslash}_rm.$$_
-
-    # Trap to clean up those temp files at exit.
-    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
-
-    # Copy the file name to the temp name.
-    (umask $cp_umask &&
-     { test -z "$stripcmd" || {
-        # Create $dsttmp read-write so that cp doesn't create it read-only,
-        # which would cause strip to fail.
-        if test -z "$doit"; then
-          : >"$dsttmp" # No need to fork-exec 'touch'.
-        else
-          $doit touch "$dsttmp"
-        fi
-       }
-     } &&
-     $doit_exec $cpprog "$src" "$dsttmp") &&
-
-    # and set any options; do chmod last to preserve setuid bits.
-    #
-    # If any of these fail, we abort the whole thing.  If we want to
-    # ignore errors from any of these, just make sure not to ignore
-    # errors from the above "$doit $cpprog $src $dsttmp" command.
-    #
-    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
-    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
-    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
-    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
-
-    # If -C, don't bother to copy if it wouldn't change the file.
-    if $copy_on_change &&
-       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
-       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
-       set -f &&
-       set X $old && old=:$2:$4:$5:$6 &&
-       set X $new && new=:$2:$4:$5:$6 &&
-       set +f &&
-       test "$old" = "$new" &&
-       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
-    then
-      rm -f "$dsttmp"
-    else
-      # If $backupsuffix is set, and the file being installed
-      # already exists, attempt a backup.  Don't worry if it fails,
-      # e.g., if mv doesn't support -f.
-      if test -n "$backupsuffix" && test -f "$dst"; then
-        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
-      fi
-
-      # Rename the file to the real destination.
-      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
-
-      # The rename failed, perhaps because mv can't rename something else
-      # to itself, or perhaps because mv is so ancient that it does not
-      # support -f.
-      {
-        # Now remove or move aside any old file at destination location.
-        # We try this two ways since rm can't unlink itself on some
-        # systems and the destination file might be busy for other
-        # reasons.  In this case, the final cleanup might fail but the new
-        # file should still install successfully.
-        {
-          test ! -f "$dst" ||
-          $doit $rmcmd "$dst" 2>/dev/null ||
-          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
-            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
-          } ||
-          { echo "$0: cannot unlink or rename $dst" >&2
-            (exit 1); exit 1
-          }
-        } &&
-
-        # Now rename the file to the real destination.
-        $doit $mvcmd "$dsttmp" "$dst"
-      }
-    fi || exit 1
-
-    trap '' 0
-  fi
-done
-
-# Local variables:
-# eval: (add-hook 'before-save-hook 'time-stamp)
-# time-stamp-start: "scriptversion="
-# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-time-zone: "UTC0"
-# time-stamp-end: "; # UTC"
-# End:
diff --git a/exec/loader-aarch64.s b/exec/loader-aarch64.s
index da8ec1f4977..0fc9606c62a 100644
--- a/exec/loader-aarch64.s
+++ b/exec/loader-aarch64.s
@@ -1,4 +1,4 @@
-// Copyright (C) 2023 Free Software Foundation, Inc.
+// Copyright (C) 2023-2024 Free Software Foundation, Inc.
 //
 // This file is part of GNU Emacs.
 //
diff --git a/exec/loader-armeabi.s b/exec/loader-armeabi.s
index 32b2a5268d6..5601088262c 100644
--- a/exec/loader-armeabi.s
+++ b/exec/loader-armeabi.s
@@ -1,4 +1,4 @@
-@ Copyright (C) 2023 Free Software Foundation, Inc.
+@ Copyright (C) 2023-2024 Free Software Foundation, Inc.
 @
 @ This file is part of GNU Emacs.
 @
@@ -200,5 +200,5 @@ timespec:
        .long 10
 
 @ Local Variables:
-@ asm-comment-char: 64
+@ asm-comment-char: ?@
 @ End:
diff --git a/exec/loader-mips64el.s b/exec/loader-mips64el.s
index f4a6f918497..0ff140f9f31 100644
--- a/exec/loader-mips64el.s
+++ b/exec/loader-mips64el.s
@@ -1,4 +1,4 @@
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
@@ -230,5 +230,5 @@ dnl syscall                         # syscall
        .quad   10
 
 # Local Variables:
-# asm-comment-char: 35
+# asm-comment-char: ?#
 # End:
diff --git a/exec/loader-mipsel.s b/exec/loader-mipsel.s
index baba3f05a94..f1cdcfcf149 100644
--- a/exec/loader-mipsel.s
+++ b/exec/loader-mipsel.s
@@ -1,4 +1,4 @@
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
@@ -232,5 +232,5 @@ RESTORE()                           # restore sp
        .long   10
 
 # Local Variables:
-# asm-comment-char: 35
+# asm-comment-char: ?#
 # End:
diff --git a/exec/loader-x86.s b/exec/loader-x86.s
index 6329e7f33b1..216bc88f976 100644
--- a/exec/loader-x86.s
+++ b/exec/loader-x86.s
@@ -1,7 +1,7 @@
 define(`CC', `
 dnl')
 
-CC Copyright (C) 2023 Free Software Foundation, Inc.
+CC Copyright (C) 2023-2024 Free Software Foundation, Inc.
 CC
 CC This file is part of GNU Emacs.
 CC
diff --git a/exec/loader-x86_64.s b/exec/loader-x86_64.s
index acba609b202..2ef779e4504 100644
--- a/exec/loader-x86_64.s
+++ b/exec/loader-x86_64.s
@@ -1,7 +1,7 @@
 define(`CC', `
 dnl')
 
-CC Copyright (C) 2023 Free Software Foundation, Inc.
+CC Copyright (C) 2023-2024 Free Software Foundation, Inc.
 CC
 CC This file is part of GNU Emacs.
 CC
diff --git a/exec/mipsel-user.h b/exec/mipsel-user.h
index 9c5a445c9aa..04f4a2a5089 100644
--- a/exec/mipsel-user.h
+++ b/exec/mipsel-user.h
@@ -1,6 +1,6 @@
 /* Program execution for Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/exec/mipsfpu.c b/exec/mipsfpu.c
index f5fa5720804..5fd81fb9237 100644
--- a/exec/mipsfpu.c
+++ b/exec/mipsfpu.c
@@ -1,6 +1,6 @@
 /* Program execution for Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/exec/mipsfpu.h b/exec/mipsfpu.h
index 2315db59e93..1669102942b 100644
--- a/exec/mipsfpu.h
+++ b/exec/mipsfpu.h
@@ -1,6 +1,6 @@
 /* Program execution for Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/exec/test.c b/exec/test.c
index fa2a848837c..7185c958b87 100644
--- a/exec/test.c
+++ b/exec/test.c
@@ -1,6 +1,6 @@
 /* Program execution for Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/exec/trace.c b/exec/trace.c
index f9deef8eb2d..a7cbda54d68 100644
--- a/exec/trace.c
+++ b/exec/trace.c
@@ -1,6 +1,6 @@
 /* Program execution for Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -961,7 +961,7 @@ handle_readlinkat (USER_WORD callno, USER_REGS_STRUCT *regs,
     return 0;
 
   /* Copy over tracee->exec_file.  Truncate it to PATH_MAX, length, or
-     size, whichever is less.  */
+     size, whichever is smaller.  */
 
   length = strlen (tracee->exec_file);
   length = MIN (size, MIN (PATH_MAX, length));
@@ -979,6 +979,98 @@ handle_readlinkat (USER_WORD callno, USER_REGS_STRUCT 
*regs,
 #endif /* REENTRANT */
 }
 
+/* Handle an `open' or `openat' system call.
+
+   CALLNO is the system call number, and REGS are the current user
+   registers of the TRACEE.
+
+   If the file name specified in such system call is `/proc/self/exe',
+   replace the file name with the executable loaded into the process
+   issuing this system call.
+
+   Value is 0 upon success and 1 upon failure.  */
+
+static int
+handle_openat (USER_WORD callno, USER_REGS_STRUCT *regs,
+              struct exec_tracee *tracee, USER_WORD *result)
+{
+#ifdef REENTRANT
+  /* readlinkat cannot be handled specially when the library is built
+     to be reentrant, as the file name information cannot be
+     recorded.  */
+  return 0;
+#else /* !REENTRANT */
+  char buffer[PATH_MAX + 1];
+  USER_WORD address;
+  size_t length;
+  USER_REGS_STRUCT original;
+
+  /* Read the file name.  */
+
+#ifdef OPEN_SYSCALL
+  if (callno == OPEN_SYSCALL)
+    address = regs->SYSCALL_ARG_REG;
+  else
+#endif /* OPEN_SYSCALL */
+    address = regs->SYSCALL_ARG1_REG;
+
+  /* Read the file name into the buffer and verify that it is NULL
+     terminated.  */
+  read_memory (tracee, buffer, PATH_MAX, address);
+
+  if (!memchr (buffer, '\0', PATH_MAX))
+    {
+      errno = ENAMETOOLONG;
+      return 1;
+    }
+
+  /* Now check if the caller is looking for /proc/self/exe.
+
+     dirfd can be ignored, as for now only absolute file names are
+     handled.  FIXME.  */
+
+  if (strcmp (buffer, "/proc/self/exe") || !tracee->exec_file)
+    return 0;
+
+  /* Copy over tracee->exec_file.  This doesn't correctly handle the
+     scenario where tracee->exec_file is longer than PATH_MAX, but
+     that has yet to be encountered in practice.  */
+
+  original = *regs;
+  length   = strlen (tracee->exec_file);
+  address  = user_alloca (tracee, &original, regs, length + 1);
+
+  if (!address
+      || user_copy (tracee, (unsigned char *) tracee->exec_file,
+                   address, length))
+    goto fail;
+
+  /* Replace the file name buffer with ADDRESS.  */
+
+#ifdef OPEN_SYSCALL
+  if (callno == OPEN_SYSCALL)
+    regs->SYSCALL_ARG_REG = address;
+  else
+#endif /* OPEN_SYSCALL */
+    regs->SYSCALL_ARG1_REG = address;
+
+#ifdef __aarch64__
+  if (aarch64_set_regs (tracee->pid, regs, false))
+    goto fail;
+#else /* !__aarch64__ */
+  if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, regs))
+    goto fail;
+#endif /* __aarch64__ */
+
+  /* Resume the system call.  */
+  return 0;
+
+ fail:
+  errno = EIO;
+  return 1;
+#endif /* REENTRANT */
+}
+
 /* Process the system call at which TRACEE is stopped.  If the system
    call is not known or not exec, send TRACEE on its way.  Otherwise,
    rewrite it to load the loader and perform an appropriate action.  */
@@ -1028,7 +1120,7 @@ process_system_call (struct exec_tracee *tracee)
          break;
 
        case 1:
-         /* An error has occured; errno is set to the error.  */
+         /* An error has occurred; errno is set to the error.  */
          goto report_syscall_error;
        }
 
@@ -1056,9 +1148,50 @@ process_system_call (struct exec_tracee *tracee)
            goto emulate_syscall;
        }
 
+      goto continue_syscall;
+
+#ifdef OPEN_SYSCALL
+    case OPEN_SYSCALL:
+#endif /* OPEN_SYSCALL */
+    case OPENAT_SYSCALL:
+
+      /* This system call is already in progress if
+        TRACEE->waiting_for_syscall is true.  */
+
+      if (!tracee->waiting_for_syscall)
+       {
+         /* Handle this open system call.  */
+         rc = handle_openat (callno, &regs, tracee, &result);
+
+         /* rc means the same as in `handle_exec', except that `open'
+            is never emulated.  */
+
+         if (rc == 1)
+           goto report_syscall_error;
+
+         /* The stack pointer must be restored after it was modified
+            by `user_alloca'; record sp in TRACEE, which will be
+            restored after this system call completes.  */
+         tracee->sp = sp;
+       }
+      else
+       {
+         /* Restore that stack pointer.  */
+         regs.STACK_POINTER = tracee->sp;
+
+#ifdef __aarch64__
+         if (aarch64_set_regs (tracee->pid, &regs, true))
+           return;
+#else /* !__aarch64__ */
+         if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, &regs))
+           return;
+#endif /* __aarch64__ */
+       }
+
       /* Fallthrough.  */
 
     default:
+    continue_syscall:
       /* Don't wait for the system call to finish; instead, the system
         will DTRT upon the next call to PTRACE_SYSCALL after the
         syscall-trap signal is delivered.  */
diff --git a/java/AndroidManifest.xml.in b/java/AndroidManifest.xml.in
index 2749f43c245..b18446bece0 100644
--- a/java/AndroidManifest.xml.in
+++ b/java/AndroidManifest.xml.in
@@ -1,6 +1,6 @@
 <!-- @configure_input@
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -94,7 +94,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>. -->
              android:launchMode="singleInstance"
              android:windowSoftInputMode="adjustResize"
              android:exported="true"
-             
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
+             
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|locale|fontScale">
       <intent-filter>
         <action android:name="android.intent.action.MAIN" />
         <category android:name="android.intent.category.DEFAULT" />
@@ -149,7 +149,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>. -->
     <activity android:name="org.gnu.emacs.EmacsMultitaskActivity"
              android:windowSoftInputMode="adjustResize"
              android:exported="true"
-             
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"/>
+             
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|locale|fontScale"/>
 
     <activity android:autoRemoveFromRecents="true"
               android:label="Emacs options"
diff --git a/java/INSTALL b/java/INSTALL
index fb221c5e2b4..175ff2826b2 100644
--- a/java/INSTALL
+++ b/java/INSTALL
@@ -1,5 +1,5 @@
 Installation instructions for Android
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 Please read the entirety of this file before attempting to build Emacs
@@ -167,7 +167,7 @@ than a compressed package for a newer version of Android.
 BUILDING C++ DEPENDENCIES
 
 With a new version of the NDK, dependencies containing C++ code should
-build without any futher configuration.  However, older versions
+build without any further configuration.  However, older versions
 require that you use the ``make_standalone_toolchain.py'' script in
 the NDK distribution to create a ``standalone toolchain'', and use
 that instead, in order for C++ headers to be found.
@@ -309,7 +309,7 @@ work, along with what has to be patched to make them work:
 Many of these dependencies have been migrated over to the
 ``Android.bp'' build system now used to build Android itself.
 However, the old ``Android.mk'' Makefiles are still present in older
-branches, and can be easily adapte to newer versions.
+branches, and can be easily adapted to newer versions.
 
 In addition, some Emacs dependencies provide `ndk-build' support
 themselves:
diff --git a/java/Makefile.in b/java/Makefile.in
index 87683f12544..60bd2ea086b 100644
--- a/java/Makefile.in
+++ b/java/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/java/debug.sh b/java/debug.sh
index d6e439bec90..8fc03d014cf 100755
--- a/java/debug.sh
+++ b/java/debug.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 ### Run Emacs under GDB or JDB on Android.
 
-## Copyright (C) 2023 Free Software Foundation, Inc.
+## Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ## This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsActivity.java 
b/java/org/gnu/emacs/EmacsActivity.java
index f9aa261e355..3237f650240 100644
--- a/java/org/gnu/emacs/EmacsActivity.java
+++ b/java/org/gnu/emacs/EmacsActivity.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsApplication.java 
b/java/org/gnu/emacs/EmacsApplication.java
index d70f16346e5..b5f8e688b65 100644
--- a/java/org/gnu/emacs/EmacsApplication.java
+++ b/java/org/gnu/emacs/EmacsApplication.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsClipboard.java 
b/java/org/gnu/emacs/EmacsClipboard.java
index 5cd48af6e3a..9db436ca1e2 100644
--- a/java/org/gnu/emacs/EmacsClipboard.java
+++ b/java/org/gnu/emacs/EmacsClipboard.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsContextMenu.java 
b/java/org/gnu/emacs/EmacsContextMenu.java
index c415ba59c79..17e6033377d 100644
--- a/java/org/gnu/emacs/EmacsContextMenu.java
+++ b/java/org/gnu/emacs/EmacsContextMenu.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -22,6 +22,9 @@ package org.gnu.emacs;
 import java.util.List;
 import java.util.ArrayList;
 
+import java.util.concurrent.Callable;
+import java.util.concurrent.FutureTask;
+
 import android.content.Context;
 import android.content.Intent;
 
@@ -36,7 +39,7 @@ import android.view.SubMenu;
 import android.util.Log;
 
 /* Context menu implementation.  This object is built from JNI and
-   describes a menu hiearchy.  Then, `inflate' can turn it into an
+   describes a menu hierarchy.  Then, `inflate' can turn it into an
    Android menu, which can be turned into a popup (or other kind of)
    menu.  */
 
@@ -344,8 +347,7 @@ public final class EmacsContextMenu
   display (final EmacsWindow window, final int xPosition,
           final int yPosition, final int serial)
   {
-    Runnable runnable;
-    final EmacsHolder<Boolean> rc;
+    FutureTask<Boolean> task;
 
     /* Android will permanently cease to display any popup menus at
        all if the list of menu items is empty.  Prevent this by
@@ -354,25 +356,17 @@ public final class EmacsContextMenu
     if (menuItems.isEmpty ())
       return false;
 
-    rc = new EmacsHolder<Boolean> ();
-    rc.thing = false;
-
-    runnable = new Runnable () {
+    task = new FutureTask<Boolean> (new Callable<Boolean> () {
        @Override
-       public void
-       run ()
+       public Boolean
+       call ()
        {
-         synchronized (this)
-           {
-             lastMenuEventSerial = serial;
-             rc.thing = display1 (window, xPosition, yPosition);
-             notify ();
-           }
+         lastMenuEventSerial = serial;
+         return display1 (window, xPosition, yPosition);
        }
-      };
+      });
 
-    EmacsService.syncRunnable (runnable);
-    return rc.thing;
+    return EmacsService.<Boolean>syncRunnable (task);
   }
 
   /* Dismiss this context menu.  WINDOW is the window where the
diff --git a/java/org/gnu/emacs/EmacsCursor.java 
b/java/org/gnu/emacs/EmacsCursor.java
index c14c6f2a11b..1049c03d7da 100644
--- a/java/org/gnu/emacs/EmacsCursor.java
+++ b/java/org/gnu/emacs/EmacsCursor.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsDesktopNotification.java 
b/java/org/gnu/emacs/EmacsDesktopNotification.java
index 4a6bbf7a606..fb35e3fea1f 100644
--- a/java/org/gnu/emacs/EmacsDesktopNotification.java
+++ b/java/org/gnu/emacs/EmacsDesktopNotification.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsDialog.java 
b/java/org/gnu/emacs/EmacsDialog.java
index bad1ddde227..0d5b650f7d0 100644
--- a/java/org/gnu/emacs/EmacsDialog.java
+++ b/java/org/gnu/emacs/EmacsDialog.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -22,6 +22,9 @@ package org.gnu.emacs;
 import java.util.List;
 import java.util.ArrayList;
 
+import java.util.concurrent.Callable;
+import java.util.concurrent.FutureTask;
+
 import android.app.AlertDialog;
 
 import android.content.Context;
@@ -388,26 +391,18 @@ public final class EmacsDialog implements 
DialogInterface.OnDismissListener
   public boolean
   display ()
   {
-    Runnable runnable;
-    final EmacsHolder<Boolean> rc;
+    FutureTask<Boolean> task;
 
-    rc = new EmacsHolder<Boolean> ();
-    rc.thing = false;
-    runnable = new Runnable () {
+    task = new FutureTask<Boolean> (new Callable<Boolean> () {
        @Override
-       public void
-       run ()
+       public Boolean
+       call ()
        {
-         synchronized (this)
-           {
-             rc.thing = display1 ();
-             notify ();
-           }
+         return display1 ();
        }
-      };
+      });
 
-    EmacsService.syncRunnable (runnable);
-    return rc.thing;
+    return EmacsService.<Boolean>syncRunnable (task);
   }
 
 
diff --git a/java/org/gnu/emacs/EmacsDialogButtonLayout.java 
b/java/org/gnu/emacs/EmacsDialogButtonLayout.java
index fd8d63d81d3..da57d1c4404 100644
--- a/java/org/gnu/emacs/EmacsDialogButtonLayout.java
+++ b/java/org/gnu/emacs/EmacsDialogButtonLayout.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsDirectoryEntry.java 
b/java/org/gnu/emacs/EmacsDirectoryEntry.java
index 75c52e48002..4a7526dddc6 100644
--- a/java/org/gnu/emacs/EmacsDirectoryEntry.java
+++ b/java/org/gnu/emacs/EmacsDirectoryEntry.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsDocumentsProvider.java 
b/java/org/gnu/emacs/EmacsDocumentsProvider.java
index 96dc2bc6e14..7c5de9e0e14 100644
--- a/java/org/gnu/emacs/EmacsDocumentsProvider.java
+++ b/java/org/gnu/emacs/EmacsDocumentsProvider.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsDrawLine.java 
b/java/org/gnu/emacs/EmacsDrawLine.java
index be4da54c075..61b7d54d63c 100644
--- a/java/org/gnu/emacs/EmacsDrawLine.java
+++ b/java/org/gnu/emacs/EmacsDrawLine.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsDrawPoint.java 
b/java/org/gnu/emacs/EmacsDrawPoint.java
index 6a1cb744d60..859c590b1d0 100644
--- a/java/org/gnu/emacs/EmacsDrawPoint.java
+++ b/java/org/gnu/emacs/EmacsDrawPoint.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsDrawRectangle.java 
b/java/org/gnu/emacs/EmacsDrawRectangle.java
index ee9110daaaf..a8f68c6530a 100644
--- a/java/org/gnu/emacs/EmacsDrawRectangle.java
+++ b/java/org/gnu/emacs/EmacsDrawRectangle.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsDrawable.java 
b/java/org/gnu/emacs/EmacsDrawable.java
index 3ed72a836e5..a75a8f7017d 100644
--- a/java/org/gnu/emacs/EmacsDrawable.java
+++ b/java/org/gnu/emacs/EmacsDrawable.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsFillPolygon.java 
b/java/org/gnu/emacs/EmacsFillPolygon.java
index 4ae3882cab4..6bc8333984a 100644
--- a/java/org/gnu/emacs/EmacsFillPolygon.java
+++ b/java/org/gnu/emacs/EmacsFillPolygon.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsFillRectangle.java 
b/java/org/gnu/emacs/EmacsFillRectangle.java
index 461fd3c639c..ca87c06c014 100644
--- a/java/org/gnu/emacs/EmacsFillRectangle.java
+++ b/java/org/gnu/emacs/EmacsFillRectangle.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsFontDriver.java 
b/java/org/gnu/emacs/EmacsFontDriver.java
index 798c3cfb032..09d0377bd5e 100644
--- a/java/org/gnu/emacs/EmacsFontDriver.java
+++ b/java/org/gnu/emacs/EmacsFontDriver.java
@@ -1,6 +1,6 @@
 /* Font backend for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsGC.java b/java/org/gnu/emacs/EmacsGC.java
index a7467cb9bd0..e45f0666fe2 100644
--- a/java/org/gnu/emacs/EmacsGC.java
+++ b/java/org/gnu/emacs/EmacsGC.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsHandleObject.java 
b/java/org/gnu/emacs/EmacsHandleObject.java
index 5b889895337..8534f08519c 100644
--- a/java/org/gnu/emacs/EmacsHandleObject.java
+++ b/java/org/gnu/emacs/EmacsHandleObject.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsHolder.java 
b/java/org/gnu/emacs/EmacsHolder.java
index 6cd48ba57ce..6d093d27e06 100644
--- a/java/org/gnu/emacs/EmacsHolder.java
+++ b/java/org/gnu/emacs/EmacsHolder.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsInputConnection.java 
b/java/org/gnu/emacs/EmacsInputConnection.java
index 7f6331205cb..054eca66cf3 100644
--- a/java/org/gnu/emacs/EmacsInputConnection.java
+++ b/java/org/gnu/emacs/EmacsInputConnection.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -60,7 +60,7 @@ public final class EmacsInputConnection implements 
InputConnection
 
      This helps with on screen keyboard programs found in some vendor
      versions of Android, which rely on immediate updates to the point
-     position after text is commited in order to place the cursor
+     position after text is committed in order to place the cursor
      within that text.  */
 
   private static boolean syncAfterCommit;
diff --git a/java/org/gnu/emacs/EmacsLauncherPreferencesActivity.java 
b/java/org/gnu/emacs/EmacsLauncherPreferencesActivity.java
index 1e1e5d97631..21a43b261a0 100644
--- a/java/org/gnu/emacs/EmacsLauncherPreferencesActivity.java
+++ b/java/org/gnu/emacs/EmacsLauncherPreferencesActivity.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsMultitaskActivity.java 
b/java/org/gnu/emacs/EmacsMultitaskActivity.java
index b1c48f03fba..7229e34496e 100644
--- a/java/org/gnu/emacs/EmacsMultitaskActivity.java
+++ b/java/org/gnu/emacs/EmacsMultitaskActivity.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsNative.java 
b/java/org/gnu/emacs/EmacsNative.java
index 78176dd0e47..cd0e70923d1 100644
--- a/java/org/gnu/emacs/EmacsNative.java
+++ b/java/org/gnu/emacs/EmacsNative.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsNoninteractive.java 
b/java/org/gnu/emacs/EmacsNoninteractive.java
index 1c7513e1cc9..ba23399cb3e 100644
--- a/java/org/gnu/emacs/EmacsNoninteractive.java
+++ b/java/org/gnu/emacs/EmacsNoninteractive.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsOpenActivity.java 
b/java/org/gnu/emacs/EmacsOpenActivity.java
index 32a79d1a797..9ae1bf353dd 100644
--- a/java/org/gnu/emacs/EmacsOpenActivity.java
+++ b/java/org/gnu/emacs/EmacsOpenActivity.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -636,7 +636,7 @@ public final class EmacsOpenActivity extends Activity
                  {
                    /* This means Emacs lacks the rights to open this
                       file.  Display the error message and exit.  */
-                   displayFailureDialog ("Error openining file",
+                   displayFailureDialog ("Error opening file",
                                          exception.toString ());
                    return;
                  }
diff --git a/java/org/gnu/emacs/EmacsPixmap.java 
b/java/org/gnu/emacs/EmacsPixmap.java
index fa6e61c15a5..c621e2de3c5 100644
--- a/java/org/gnu/emacs/EmacsPixmap.java
+++ b/java/org/gnu/emacs/EmacsPixmap.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsPreferencesActivity.java 
b/java/org/gnu/emacs/EmacsPreferencesActivity.java
index 7e67cc3679b..330adbea223 100644
--- a/java/org/gnu/emacs/EmacsPreferencesActivity.java
+++ b/java/org/gnu/emacs/EmacsPreferencesActivity.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsSafThread.java 
b/java/org/gnu/emacs/EmacsSafThread.java
index 7917e2d4880..14c3f222833 100644
--- a/java/org/gnu/emacs/EmacsSafThread.java
+++ b/java/org/gnu/emacs/EmacsSafThread.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -504,7 +504,7 @@ public final class EmacsSafThread extends HandlerThread
   cacheDirectoryFromCursor (CacheToplevel toplevel, String documentId,
                            Cursor cursor)
   {
-    CacheEntry entry, constitutent;
+    CacheEntry entry, constituent;
     int nameColumn, idColumn, typeColumn;
     String id, name, type;
     DocIdEntry idEntry;
@@ -561,8 +561,8 @@ public final class EmacsSafThread extends HandlerThread
 
            /* Otherwise, create a new cache entry comprised of its
               type.  */
-           constitutent = new CacheEntry ();
-           constitutent.type = type;
+           constituent = new CacheEntry ();
+           constituent.type = type;
            toplevel.idCache.put (documentId, entry);
          }
        catch (Exception e)
@@ -767,7 +767,7 @@ public final class EmacsSafThread extends HandlerThread
 
   private abstract class SafIntFunction
   {
-    /* The ``throws Throwable'' here is a Java idiosyncracy that tells
+    /* The ``throws Throwable'' here is a Java idiosyncrasy that tells
        the compiler to allow arbitrary error objects to be signaled
        from within this function.
 
@@ -782,7 +782,7 @@ public final class EmacsSafThread extends HandlerThread
 
   private abstract class SafObjectFunction
   {
-    /* The ``throws Throwable'' here is a Java idiosyncracy that tells
+    /* The ``throws Throwable'' here is a Java idiosyncrasy that tells
        the compiler to allow arbitrary error objects to be signaled
        from within this function.
 
@@ -1216,7 +1216,7 @@ public final class EmacsSafThread extends HandlerThread
       });
   }
 
-  /* The bulk of `statDocument'.  SIGNAL should be a cancelation
+  /* The bulk of `statDocument'.  SIGNAL should be a cancellation
      signal.  */
 
   private long[]
diff --git a/java/org/gnu/emacs/EmacsSdk11Clipboard.java 
b/java/org/gnu/emacs/EmacsSdk11Clipboard.java
index b068a89831e..850bb6c8deb 100644
--- a/java/org/gnu/emacs/EmacsSdk11Clipboard.java
+++ b/java/org/gnu/emacs/EmacsSdk11Clipboard.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsSdk23FontDriver.java 
b/java/org/gnu/emacs/EmacsSdk23FontDriver.java
index 0752d8064ac..91153feaa11 100644
--- a/java/org/gnu/emacs/EmacsSdk23FontDriver.java
+++ b/java/org/gnu/emacs/EmacsSdk23FontDriver.java
@@ -1,6 +1,6 @@
 /* Font backend for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsSdk7FontDriver.java 
b/java/org/gnu/emacs/EmacsSdk7FontDriver.java
index 33d6ee34fa4..49d9514c104 100644
--- a/java/org/gnu/emacs/EmacsSdk7FontDriver.java
+++ b/java/org/gnu/emacs/EmacsSdk7FontDriver.java
@@ -1,6 +1,6 @@
 /* Font backend for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsSdk8Clipboard.java 
b/java/org/gnu/emacs/EmacsSdk8Clipboard.java
index 9622641810f..418f55c12c1 100644
--- a/java/org/gnu/emacs/EmacsSdk8Clipboard.java
+++ b/java/org/gnu/emacs/EmacsSdk8Clipboard.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsService.java 
b/java/org/gnu/emacs/EmacsService.java
index 33832505333..5cb1ceca0aa 100644
--- a/java/org/gnu/emacs/EmacsService.java
+++ b/java/org/gnu/emacs/EmacsService.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -27,6 +27,10 @@ import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+
 import java.util.concurrent.atomic.AtomicInteger;
 
 import android.database.Cursor;
@@ -331,52 +335,45 @@ public final class EmacsService extends Service
                final boolean isFocusedByDefault)
   {
     Runnable runnable;
-    final EmacsHolder<EmacsView> view;
-
-    view = new EmacsHolder<EmacsView> ();
+    FutureTask<EmacsView> task;
 
-    runnable = new Runnable () {
+    task = new FutureTask<EmacsView> (new Callable<EmacsView> () {
        @Override
-       public void
-       run ()
+       public EmacsView
+       call ()
        {
-         synchronized (this)
-           {
-             view.thing = new EmacsView (window);
-             view.thing.setVisibility (visibility);
+         EmacsView view;
 
-             /* The following function is only present on Android 26
-                or later.  */
-             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
-               view.thing.setFocusedByDefault (isFocusedByDefault);
+         view = new EmacsView (window);
+         view.setVisibility (visibility);
 
-             notify ();
-           }
+         /* The following function is only present on Android 26
+            or later.  */
+         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+           view.setFocusedByDefault (isFocusedByDefault);
+
+         return view;
        }
-      };
+      });
 
-    syncRunnable (runnable);
-    return view.thing;
+    return EmacsService.<EmacsView>syncRunnable (task);
   }
 
   public void
   getLocationOnScreen (final EmacsView view, final int[] coordinates)
   {
-    Runnable runnable;
+    FutureTask<Void> task;
 
-    runnable = new Runnable () {
-       public void
-       run ()
+    task = new FutureTask<Void> (new Callable<Void> () {
+       public Void
+       call ()
        {
-         synchronized (this)
-           {
-             view.getLocationOnScreen (coordinates);
-             notify ();
-           }
+         view.getLocationOnScreen (coordinates);
+         return null;
        }
-      };
+      });
 
-    syncRunnable (runnable);
+    EmacsService.<Void>syncRunnable (task);
   }
 
 
@@ -612,7 +609,7 @@ public final class EmacsService extends Service
          context.startService (new Intent (context,
                                            EmacsService.class));
        else
-         /* Display the permanant notification and start Emacs as a
+         /* Display the permanent notification and start Emacs as a
             foreground service.  */
          context.startForegroundService (new Intent (context,
                                                      EmacsService.class));
@@ -679,7 +676,7 @@ public final class EmacsService extends Service
            /* Display a list of programs able to send this URL.  */
            intent = Intent.createChooser (intent, "Send");
 
-           /* Apparently flags need to be set after a choser is
+           /* Apparently flags need to be set after a chooser is
               created.  */
            intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
          }
@@ -702,28 +699,17 @@ public final class EmacsService extends Service
   public ClipboardManager
   getClipboardManager ()
   {
-    final EmacsHolder<ClipboardManager> manager;
-    Runnable runnable;
+    FutureTask<Object> task;
 
-    manager = new EmacsHolder<ClipboardManager> ();
-
-    runnable = new Runnable () {
-       public void
-       run ()
+    task = new FutureTask<Object> (new Callable<Object> () {
+       public Object
+       call ()
        {
-         Object tem;
-
-         synchronized (this)
-           {
-             tem = getSystemService (Context.CLIPBOARD_SERVICE);
-             manager.thing = (ClipboardManager) tem;
-             notify ();
-           }
+         return getSystemService (Context.CLIPBOARD_SERVICE);
        }
-      };
+      });
 
-    syncRunnable (runnable);
-    return manager.thing;
+    return (ClipboardManager) EmacsService.<Object>syncRunnable (task);
   }
 
   public void
@@ -738,33 +724,37 @@ public final class EmacsService extends Service
     System.exit (0);
   }
 
-  /* Wait synchronously for the specified RUNNABLE to complete in the
-     UI thread.  Must be called from the Emacs thread.  */
+  /* Wait synchronously for the specified TASK to complete in the UI
+     thread, then return its result.  Must be called from the Emacs
+     thread.  */
 
-  public static void
-  syncRunnable (Runnable runnable)
+  public static <V> V
+  syncRunnable (FutureTask<V> task)
   {
+    V object;
+
     EmacsNative.beginSynchronous ();
+    SERVICE.runOnUiThread (task);
 
-    synchronized (runnable)
+    try
       {
-       SERVICE.runOnUiThread (runnable);
-
-       while (true)
-         {
-           try
-             {
-               runnable.wait ();
-               break;
-             }
-           catch (InterruptedException e)
-             {
-               continue;
-             }
-         }
+       object = task.get ();
+      }
+    catch (ExecutionException exception)
+      {
+       /* Wrap this exception in a RuntimeException and signal it to
+          the caller.  */
+       throw new RuntimeException (exception.getCause ());
+      }
+    catch (InterruptedException exception)
+      {
+       EmacsNative.emacsAbort ();
+       object = null;
       }
 
     EmacsNative.endSynchronous ();
+
+    return object;
   }
 
 
@@ -927,7 +917,7 @@ public final class EmacsService extends Service
 
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
       /* Since the system predates drag and drop, return this resolver
-        to avoid any unforseen difficulties.  */
+        to avoid any unforeseen difficulties.  */
       return resolver;
 
     activity = EmacsActivity.lastFocusedActivity;
@@ -947,7 +937,7 @@ public final class EmacsService extends Service
 
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
       /* Since the system predates drag and drop, return this resolver
-        to avoid any unforseen difficulties.  */
+        to avoid any unforeseen difficulties.  */
       return this;
 
     activity = EmacsActivity.lastFocusedActivity;
@@ -1283,71 +1273,61 @@ public final class EmacsService extends Service
   public int
   requestDirectoryAccess ()
   {
-    Runnable runnable;
-    final EmacsHolder<Integer> rc;
+    FutureTask<Integer> task;
 
     /* Return 1 if Android is too old to support this feature.  */
 
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
       return 1;
 
-    rc = new EmacsHolder<Integer> ();
-    rc.thing = Integer.valueOf (1);
-
-    runnable = new Runnable () {
+    task = new FutureTask<Integer> (new Callable<Integer> () {
        @Override
-       public void
-       run ()
+       public Integer
+        call ()
        {
          EmacsActivity activity;
          Intent intent;
-         int id;
+         int id, rc;
+
+         /* Try to obtain an activity that will receive the response
+            from the file chooser dialog.  */
 
-         synchronized (this)
+         if (EmacsActivity.focusedActivities.isEmpty ())
            {
-             /* Try to obtain an activity that will receive the
-                response from the file chooser dialog.  */
+             /* If focusedActivities is empty then this dialog may
+                have been displayed immediately after another popup
+                dialog was dismissed.  Try the EmacsActivity to be
+                focused.  */
 
-             if (EmacsActivity.focusedActivities.isEmpty ())
-               {
-                 /* If focusedActivities is empty then this dialog
-                    may have been displayed immediately after another
-                    popup dialog was dismissed.  Try the
-                    EmacsActivity to be focused.  */
-
-                 activity = EmacsActivity.lastFocusedActivity;
-
-                 if (activity == null)
-                   {
-                     /* Still no luck.  Return failure.  */
-                     notify ();
-                     return;
-                   }
-               }
-             else
-               activity = EmacsActivity.focusedActivities.get (0);
+             activity = EmacsActivity.lastFocusedActivity;
 
-             /* Now create the intent.  */
-             intent = new Intent (Intent.ACTION_OPEN_DOCUMENT_TREE);
+             if (activity == null)
+               /* Still no luck.  Return failure.  */
+               return 1;
+           }
+         else
+           activity = EmacsActivity.focusedActivities.get (0);
 
-             try
-               {
-                 id = EmacsActivity.ACCEPT_DOCUMENT_TREE;
-                 activity.startActivityForResult (intent, id, null);
-                 rc.thing = Integer.valueOf (0);
-               }
-             catch (Exception e)
-               {
-                 e.printStackTrace ();
-               }
+         /* Now create the intent.  */
+         intent = new Intent (Intent.ACTION_OPEN_DOCUMENT_TREE);
+         rc = 1;
 
-             notify ();
+         try
+           {
+             id = EmacsActivity.ACCEPT_DOCUMENT_TREE;
+             activity.startActivityForResult (intent, id, null);
+             rc = 0;
            }
+         catch (Exception e)
+           {
+             e.printStackTrace ();
+           }
+
+         return rc;
        }
-      };
+      });
 
-    syncRunnable (runnable);
-    return rc.thing;
+    return EmacsService.<Integer>syncRunnable (task);
   }
 
   /* Return an array of each tree provided by the document PROVIDER
@@ -1969,7 +1949,7 @@ public final class EmacsService extends Service
          /* Now request these permissions.  */
          activity.requestPermissions (new String[] { permission,
                                                      permission1, },
-           0);
+                                      0);
        }
       };
 
diff --git a/java/org/gnu/emacs/EmacsSurfaceView.java 
b/java/org/gnu/emacs/EmacsSurfaceView.java
index c47696b35c0..e5601041538 100644
--- a/java/org/gnu/emacs/EmacsSurfaceView.java
+++ b/java/org/gnu/emacs/EmacsSurfaceView.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsThread.java 
b/java/org/gnu/emacs/EmacsThread.java
index 5307015b46f..4adcb98b2f7 100644
--- a/java/org/gnu/emacs/EmacsThread.java
+++ b/java/org/gnu/emacs/EmacsThread.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/org/gnu/emacs/EmacsView.java 
b/java/org/gnu/emacs/EmacsView.java
index 2d53231fbf9..8398e4b784c 100644
--- a/java/org/gnu/emacs/EmacsView.java
+++ b/java/org/gnu/emacs/EmacsView.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -388,7 +388,7 @@ public final class EmacsView extends ViewGroup
                && !rootWindowInsets.isVisible (WindowInsets.Type.ime ())
                /* N.B. that the keyboard is dismissed during gesture
                   navigation under Android 30, but the system is
-                  quite tempermental regarding whether the window is
+                  quite temperamental regarding whether the window is
                   focused at that point.  Ideally
                   isCurrentlyTextEditor shouldn't be reset in that
                   case, but detecting that situation appears to be
@@ -456,7 +456,6 @@ public final class EmacsView extends ViewGroup
   {
     Canvas canvas;
     Rect damageRect;
-    Bitmap bitmap;
 
     /* Make sure this function is called only from the Emacs
        thread.  */
@@ -474,11 +473,12 @@ public final class EmacsView extends ViewGroup
     damageRect = damageRegion.getBounds ();
     damageRegion.setEmpty ();
 
-    bitmap = getBitmap ();
-
-    /* Transfer the bitmap to the surface view, then invalidate
-       it.  */
-    surfaceView.setBitmap (bitmap, damageRect);
+    synchronized (this)
+      {
+       /* Transfer the bitmap to the surface view, then invalidate
+          it.  */
+       surfaceView.setBitmap (bitmap, damageRect);
+      }
   }
 
   @Override
@@ -724,17 +724,20 @@ public final class EmacsView extends ViewGroup
   public synchronized void
   onDetachedFromWindow ()
   {
-    isAttachedToWindow = false;
-
-    /* Recycle the bitmap and call GC.  */
-
-    if (bitmap != null)
-      bitmap.recycle ();
+    Bitmap savedBitmap;
 
+    savedBitmap = bitmap;
+    isAttachedToWindow = false;
     bitmap = null;
     canvas = null;
+
     surfaceView.setBitmap (null, null);
 
+    /* Recycle the bitmap and call GC.  */
+
+    if (savedBitmap != null)
+      savedBitmap.recycle ();
+
     /* Collect the bitmap storage; it could be large.  */
     Runtime.getRuntime ().gc ();
 
diff --git a/java/org/gnu/emacs/EmacsWindow.java 
b/java/org/gnu/emacs/EmacsWindow.java
index 7d161fdcf88..304304a328b 100644
--- a/java/org/gnu/emacs/EmacsWindow.java
+++ b/java/org/gnu/emacs/EmacsWindow.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -428,7 +428,7 @@ public final class EmacsWindow extends EmacsHandleObject
                  manager = EmacsWindowAttachmentManager.MANAGER;
 
                  /* If parent is the root window, notice that there are new
-                    children available for interested activites to pick
+                    children available for interested activities to pick
                     up.  */
                  manager.registerWindow (EmacsWindow.this);
 
@@ -644,7 +644,7 @@ public final class EmacsWindow extends EmacsHandleObject
   public void
   onKeyDown (int keyCode, KeyEvent event)
   {
-    int state, state_1;
+    int state, state_1, num_lock_flag;
     long serial;
     String characters;
 
@@ -665,13 +665,23 @@ public final class EmacsWindow extends EmacsHandleObject
 
     state = eventModifiers (event);
 
+    /* Num Lock and Scroll Lock aren't supported by systems older than
+       Android 3.0. */
+
+    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+      num_lock_flag = (KeyEvent.META_NUM_LOCK_ON
+                      | KeyEvent.META_SCROLL_LOCK_ON);
+    else
+      num_lock_flag = 0;
+
     /* Ignore meta-state understood by Emacs for now, or key presses
        such as Ctrl+C and Meta+C will not be recognized as an ASCII
        key press event.  */
 
     state_1
       = state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK
-                 | KeyEvent.META_SYM_ON | KeyEvent.META_META_MASK);
+                 | KeyEvent.META_SYM_ON | KeyEvent.META_META_MASK
+                 | num_lock_flag);
 
     synchronized (eventStrings)
       {
@@ -692,19 +702,29 @@ public final class EmacsWindow extends EmacsHandleObject
   public void
   onKeyUp (int keyCode, KeyEvent event)
   {
-    int state, state_1, unicode_char;
+    int state, state_1, unicode_char, num_lock_flag;
     long time;
 
     /* Compute the event's modifier mask.  */
     state = eventModifiers (event);
 
+    /* Num Lock and Scroll Lock aren't supported by systems older than
+       Android 3.0. */
+
+    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+      num_lock_flag = (KeyEvent.META_NUM_LOCK_ON
+                      | KeyEvent.META_SCROLL_LOCK_ON);
+    else
+      num_lock_flag = 0;
+
     /* Ignore meta-state understood by Emacs for now, or key presses
        such as Ctrl+C and Meta+C will not be recognized as an ASCII
        key press event.  */
 
     state_1
       = state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK
-                 | KeyEvent.META_SYM_ON | KeyEvent.META_META_MASK);
+                 | KeyEvent.META_SYM_ON | KeyEvent.META_META_MASK
+                 | num_lock_flag);
 
     unicode_char = getEventUnicodeChar (event, state_1);
 
@@ -1399,7 +1419,7 @@ public final class EmacsWindow extends EmacsHandleObject
                  }
 
                /* Effect the same adjustment upon the view
-                  hiearchy.  */
+                  hierarchy.  */
 
                EmacsService.SERVICE.runOnUiThread (new Runnable () {
                    @Override
@@ -1764,4 +1784,32 @@ public final class EmacsWindow extends EmacsHandleObject
 
     return true;
   }
+
+
+
+  /* Miscellaneous functions for debugging graphics code.  */
+
+  /* Recreate the activity to which this window is attached, if any.
+     This is nonfunctional on Android 2.3.7 and earlier.  */
+
+  public void
+  recreateActivity ()
+  {
+    final EmacsWindowAttachmentManager.WindowConsumer attached;
+
+    attached = this.attached;
+
+    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
+      return;
+
+    view.post (new Runnable () {
+       @Override
+       public void
+       run ()
+       {
+         if (attached instanceof EmacsActivity)
+           ((EmacsActivity) attached).recreate ();
+       }
+      });
+  }
 };
diff --git a/java/org/gnu/emacs/EmacsWindowAttachmentManager.java 
b/java/org/gnu/emacs/EmacsWindowAttachmentManager.java
index 4ba5b35aacf..18bdb6dbf60 100644
--- a/java/org/gnu/emacs/EmacsWindowAttachmentManager.java
+++ b/java/org/gnu/emacs/EmacsWindowAttachmentManager.java
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.  -*- c-file-style: "GNU" -*-
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/drawable/emacs_background.xml 
b/java/res/drawable/emacs_background.xml
index c29e0635f7d..448ca48d1cb 100644
--- a/java/res/drawable/emacs_background.xml
+++ b/java/res/drawable/emacs_background.xml
@@ -1,6 +1,6 @@
 <!-- Adaptive icon for Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/drawable/emacs_foreground.xml 
b/java/res/drawable/emacs_foreground.xml
index 68a4631f17b..d4d71f8e29a 100644
--- a/java/res/drawable/emacs_foreground.xml
+++ b/java/res/drawable/emacs_foreground.xml
@@ -1,6 +1,6 @@
 <!-- Adaptive icon for Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/layout/sdk8_notifications_view.xml 
b/java/res/layout/sdk8_notifications_view.xml
index 0572f350cff..a6a441b098f 100644
--- a/java/res/layout/sdk8_notifications_view.xml
+++ b/java/res/layout/sdk8_notifications_view.xml
@@ -1,6 +1,6 @@
 <!-- Notification content widget tree for GNU Emacs on Android 2.3.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/mipmap-v26/emacs_icon.xml 
b/java/res/mipmap-v26/emacs_icon.xml
index 9f070e3f3d2..f0a8df92846 100644
--- a/java/res/mipmap-v26/emacs_icon.xml
+++ b/java/res/mipmap-v26/emacs_icon.xml
@@ -1,6 +1,6 @@
 <!-- Adaptive icon for Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/values-v11/style.xml b/java/res/values-v11/style.xml
index b114758bf0d..f55dd378e39 100644
--- a/java/res/values-v11/style.xml
+++ b/java/res/values-v11/style.xml
@@ -1,6 +1,6 @@
 <!-- Style resources for GNU Emacs on Android.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/values-v14/style.xml b/java/res/values-v14/style.xml
index 2cb54dc301b..aa19067d4ec 100644
--- a/java/res/values-v14/style.xml
+++ b/java/res/values-v14/style.xml
@@ -1,6 +1,6 @@
 <!-- Style resources for GNU Emacs on Android.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/values-v19/bool.xml b/java/res/values-v19/bool.xml
index a4e3a87ae71..fa0f8b5c486 100644
--- a/java/res/values-v19/bool.xml
+++ b/java/res/values-v19/bool.xml
@@ -1,6 +1,6 @@
 <!-- Boolean resources for GNU Emacs on Android 4.4 or later.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/values-v24/bool.xml b/java/res/values-v24/bool.xml
index 37f07992995..aeab90a0da0 100644
--- a/java/res/values-v24/bool.xml
+++ b/java/res/values-v24/bool.xml
@@ -1,6 +1,6 @@
 <!-- Boolean resources for GNU Emacs on Android.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/values-v29/style.xml b/java/res/values-v29/style.xml
index ec7b8d14554..4de416c645e 100644
--- a/java/res/values-v29/style.xml
+++ b/java/res/values-v29/style.xml
@@ -1,6 +1,6 @@
 <!-- Style resources for GNU Emacs on Android.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/values/bool.xml b/java/res/values/bool.xml
index 2b253824e29..f7a7528bead 100644
--- a/java/res/values/bool.xml
+++ b/java/res/values/bool.xml
@@ -1,6 +1,6 @@
 <!-- Boolean resources for GNU Emacs on Android.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 0bf1ef0ac9b..f858b44fe4b 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -1,6 +1,6 @@
 <!-- String resources used by GNU Emacs on Android.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/values/style.xml b/java/res/values/style.xml
index 498e844fda0..64f2f68aea9 100644
--- a/java/res/values/style.xml
+++ b/java/res/values/style.xml
@@ -1,6 +1,6 @@
 <!-- Style resources for GNU Emacs on Android.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/java/res/xml/preferences.xml b/java/res/xml/preferences.xml
index d52d28816e5..8ff93910446 100644
--- a/java/res/xml/preferences.xml
+++ b/java/res/xml/preferences.xml
@@ -1,6 +1,6 @@
 <!-- Descriptions for the preferences screen for GNU Emacs on Android.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/leim/ChangeLog.1 b/leim/ChangeLog.1
index ac17527d66f..23c7a9ce7ce 100644
--- a/leim/ChangeLog.1
+++ b/leim/ChangeLog.1
@@ -2578,7 +2578,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1997-1999, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1997-1999, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/leim/Makefile.in b/leim/Makefile.in
index f7dfdf66f30..f7a23178919 100644
--- a/leim/Makefile.in
+++ b/leim/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 1997-2023 Free Software Foundation, Inc.
+# Copyright (C) 1997-2024 Free Software Foundation, Inc.
 # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 #   2006, 2007, 2008, 2009, 2010, 2011
 #   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/leim/README b/leim/README
index 89219f27db2..054b1710dbd 100644
--- a/leim/README
+++ b/leim/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/leim/leim-ext.el b/leim/leim-ext.el
index d145296e3c8..e710da1004a 100644
--- a/leim/leim-ext.el
+++ b/leim/leim-ext.el
@@ -1,6 +1,6 @@
 ;;; leim-ext.el --- extra leim configuration   -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
 ;;   Registration Number H13PRO009
diff --git a/lib-src/ChangeLog.1 b/lib-src/ChangeLog.1
index 7a540979613..5acb93fb76f 100644
--- a/lib-src/ChangeLog.1
+++ b/lib-src/ChangeLog.1
@@ -8609,7 +8609,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1988-1999, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1988-1999, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in
index 8a5ce019ca2..7c059640862 100644
--- a/lib-src/Makefile.in
+++ b/lib-src/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 1985, 1987-1988, 1993-1994, 2001-2023 Free Software
+# Copyright (C) 1985, 1987-1988, 1993-1994, 2001-2024 Free Software
 # Foundation, Inc.
 
 # This file is part of GNU Emacs.
diff --git a/lib-src/asset-directory-tool.c b/lib-src/asset-directory-tool.c
index 99c954a3922..31735586193 100644
--- a/lib-src/asset-directory-tool.c
+++ b/lib-src/asset-directory-tool.c
@@ -1,6 +1,6 @@
 /* Android asset directory tool.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/lib-src/be_resources.cc b/lib-src/be_resources.cc
index f77601d3414..e91ee315803 100644
--- a/lib-src/be_resources.cc
+++ b/lib-src/be_resources.cc
@@ -1,5 +1,5 @@
 /* Haiku window system support
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/lib-src/ebrowse.c b/lib-src/ebrowse.c
index 4b71f7447e0..821c29272a4 100644
--- a/lib-src/ebrowse.c
+++ b/lib-src/ebrowse.c
@@ -1,6 +1,6 @@
 /* ebrowse.c --- parsing files for the ebrowse C++ browser
 
-Copyright (C) 1992-2023 Free Software Foundation, Inc.
+Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index d15f9846163..ea34d5f7b93 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -1,6 +1,6 @@
 /* Client process that communicates with GNU Emacs acting as server.
 
-Copyright (C) 1986-2023 Free Software Foundation, Inc.
+Copyright (C) 1986-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 147ecbd7c1b..032cfa8010b 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -28,7 +28,7 @@ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
SOFTWARE, EVEN
 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2023 Free Software
+Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2024 Free Software
 Foundation, Inc.
 
 This file is not considered part of GNU Emacs.
@@ -3825,7 +3825,7 @@ C_entries (int c_ext,             /* extension of C */
                    {
                    case fstartlist:
                      /* This prevents tagging fb in
-                        void (__attribute__((noreturn)) *fb) (void);
+                        void (__attribute__ ((noreturn)) *fb) (void);
                         Fixing this is not easy and not very important. */
                      fvdef = finlist;
                      continue;
@@ -4380,14 +4380,14 @@ Yacc_entries (FILE *inf)
 
 #define LOOKING_AT(cp, kw)  /* kw is the keyword, a literal string */  \
   ((assert ("" kw), true)   /* syntax error if not a literal string */ \
-   && strneq ((cp), kw, sizeof (kw)-1)         /* cp points at kw */   \
+   && strneq (cp, kw, sizeof (kw) - 1)         /* cp points at kw */   \
    && notinname ((cp)[sizeof (kw)-1])          /* end of kw */         \
    && ((cp) = skip_spaces ((cp) + sizeof (kw) - 1), true)) /* skip spaces */
 
 /* Similar to LOOKING_AT but does not use notinname, does not skip */
 #define LOOKING_AT_NOCASE(cp, kw) /* the keyword is a literal string */        
\
   ((assert ("" kw), true) /* syntax error if not a literal string */   \
-   && strncaseeq ((cp), kw, sizeof (kw)-1)     /* cp points at kw */   \
+   && strncaseeq (cp, kw, sizeof (kw) - 1)     /* cp points at kw */   \
    && ((cp) += sizeof (kw) - 1, true))         /* skip spaces */
 
 /*
diff --git a/lib-src/hexl.c b/lib-src/hexl.c
index ff2466a0a57..4b67633e743 100644
--- a/lib-src/hexl.c
+++ b/lib-src/hexl.c
@@ -1,5 +1,5 @@
 /* Convert files for Emacs Hexl mode.
-   Copyright (C) 1989, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1989, 2001-2024 Free Software Foundation, Inc.
 
 Author: Keith Gabryelski (according to authors.el)
 
diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c
index 1087562dc0b..ac4f320f9a5 100644
--- a/lib-src/make-docfile.c
+++ b/lib-src/make-docfile.c
@@ -1,6 +1,6 @@
 /* Generate doc-string file for GNU Emacs from source files.
 
-Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2023 Free Software
+Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/lib-src/make-fingerprint.c b/lib-src/make-fingerprint.c
index 7931616096b..dcd2ccc6f54 100644
--- a/lib-src/make-fingerprint.c
+++ b/lib-src/make-fingerprint.c
@@ -1,6 +1,6 @@
 /* Hash inputs and generate C file with the digest.
 
-Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2016, 2018-2023 Free
+Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2016, 2018-2024 Free
 Software Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/lib-src/movemail.c b/lib-src/movemail.c
index 6a772e9043e..407f95e4541 100644
--- a/lib-src/movemail.c
+++ b/lib-src/movemail.c
@@ -1,7 +1,7 @@
 /* movemail foo bar -- move file foo to file bar,
    locking file foo the way /bin/mail respects.
 
-Copyright (C) 1986, 1992-1994, 1996, 1999, 2001-2023 Free Software
+Copyright (C) 1986, 1992-1994, 1996, 1999, 2001-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/lib-src/ntlib.c b/lib-src/ntlib.c
index 252bc576c94..55f247f8b5d 100644
--- a/lib-src/ntlib.c
+++ b/lib-src/ntlib.c
@@ -1,6 +1,6 @@
 /* Utility and Unix shadow routines for GNU Emacs support programs on NT.
 
-Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 
 Author: Geoff Voelker (voelker@cs.washington.edu)
 Created: 10-8-94
diff --git a/lib-src/ntlib.h b/lib-src/ntlib.h
index f47fb5745de..c0756fde571 100644
--- a/lib-src/ntlib.h
+++ b/lib-src/ntlib.h
@@ -1,5 +1,5 @@
 /* Utility and Unix shadow routines for GNU Emacs support programs on NT.
-   Copyright (C) 1994, 2002-2023 Free Software Foundation, Inc.
+   Copyright (C) 1994, 2002-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/lib-src/pop.c b/lib-src/pop.c
index c58103a7e65..e2a4f1d8d3b 100644
--- a/lib-src/pop.c
+++ b/lib-src/pop.c
@@ -1,6 +1,6 @@
 /* pop.c: client routines for talking to a POP3-protocol post-office server
 
-Copyright (C) 1991, 1993, 1996-1997, 1999, 2001-2023 Free Software
+Copyright (C) 1991, 1993, 1996-1997, 1999, 2001-2024 Free Software
 Foundation, Inc.
 
 Author: Jonathan Kamens <jik@security.ov.com>
diff --git a/lib-src/pop.h b/lib-src/pop.h
index 2f48272edb2..3e7d8c47ee1 100644
--- a/lib-src/pop.h
+++ b/lib-src/pop.h
@@ -1,5 +1,5 @@
 /* pop.h: Header file for the "pop.c" client POP3 protocol.
-   Copyright (C) 1991, 1993, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1991, 1993, 2001-2024 Free Software Foundation, Inc.
 
 Author: Jonathan Kamens <jik@security.ov.com>
 
diff --git a/lib-src/rcs2log b/lib-src/rcs2log
index 65fb1c9598f..61301e7246d 100755
--- a/lib-src/rcs2log
+++ b/lib-src/rcs2log
@@ -2,7 +2,7 @@
 
 # RCS to ChangeLog generator
 
-# Copyright (C) 1992-1998, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1992-1998, 2001-2024 Free Software Foundation, Inc.
 
 # Author: Paul Eggert <eggert@cs.ucla.edu>
 
@@ -20,7 +20,7 @@
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 
-Copyright='Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright='Copyright (C) 2024 Free Software Foundation, Inc.
 This program comes with NO WARRANTY, to the extent permitted by law.
 You may redistribute copies of this program
 under the terms of the GNU General Public License.
diff --git a/lib-src/seccomp-filter.c b/lib-src/seccomp-filter.c
index e83c2142e51..0aeb6e8d88a 100644
--- a/lib-src/seccomp-filter.c
+++ b/lib-src/seccomp-filter.c
@@ -1,6 +1,6 @@
 /* Generate a Secure Computing filter definition file.
 
-Copyright (C) 2020-2023 Free Software Foundation, Inc.
+Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -114,7 +114,7 @@ set_attribute (enum scmp_filter_attr attr, uint32_t value)
     {                                                                \
       const struct scmp_arg_cmp arg_array[] = {__VA_ARGS__};         \
       enum { arg_cnt = sizeof arg_array / sizeof *arg_array };       \
-      int status = seccomp_rule_add_array (ctx, (action), (syscall), \
+      int status = seccomp_rule_add_array (ctx, action, syscall,     \
                                            arg_cnt, arg_array);      \
       if (status < 0)                                                \
         fail (-status, "seccomp_rule_add_array (%s, %s, %d, {%s})",  \
@@ -143,7 +143,7 @@ export_filter (const char *file,
 }
 
 #define EXPORT_FILTER(file, function) \
-  export_filter ((file), (function), #function)
+  export_filter (file, function, #function)
 
 int
 main (int argc, char **argv)
diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c
index 4592e14d1d6..4139073bcd7 100644
--- a/lib-src/update-game-score.c
+++ b/lib-src/update-game-score.c
@@ -1,6 +1,6 @@
 /* update-game-score.c --- Update a score file
 
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 Author: Colin Walters <walters@debian.org>
 
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 6752f68c50e..6706d73ace0 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright 2017-2023 Free Software Foundation, Inc.
+# Copyright 2017-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h
index 6ecea98b54a..7326bd47733 100644
--- a/lib/_Noreturn.h
+++ b/lib/_Noreturn.h
@@ -1,5 +1,5 @@
 /* A C macro for declaring that a function does not return.
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published
diff --git a/lib/acl-errno-valid.c b/lib/acl-errno-valid.c
index a4fd575e3f3..ee9407232db 100644
--- a/lib/acl-errno-valid.c
+++ b/lib/acl-errno-valid.c
@@ -1,6 +1,6 @@
 /* Test whether ACLs are well supported on this system.
 
-   Copyright 2013-2023 Free Software Foundation, Inc.
+   Copyright 2013-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/acl-internal.c b/lib/acl-internal.c
index fbe9b2c9a06..68aead8de65 100644
--- a/lib/acl-internal.c
+++ b/lib/acl-internal.c
@@ -1,6 +1,6 @@
 /* Test whether a file has a nontrivial ACL.  -*- coding: utf-8 -*-
 
-   Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/acl-internal.h b/lib/acl-internal.h
index 496e41d7b21..ef1f84dc243 100644
--- a/lib/acl-internal.h
+++ b/lib/acl-internal.h
@@ -1,6 +1,6 @@
 /* Internal implementation of access control lists.  -*- coding: utf-8 -*-
 
-   Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -52,9 +52,6 @@ extern int aclsort (int, int, struct acl *);
 #include <errno.h>
 
 #include <limits.h>
-#ifndef MIN
-# define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
 
 #ifndef SIZE_MAX
 # define SIZE_MAX ((size_t) -1)
diff --git a/lib/acl.h b/lib/acl.h
index 0d021200556..a3aeb8fc86a 100644
--- a/lib/acl.h
+++ b/lib/acl.h
@@ -1,6 +1,6 @@
 /* acl.c - access control lists
 
-   Copyright (C) 2002, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2008-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/acl_entries.c b/lib/acl_entries.c
index a59ace3f404..81338323f5c 100644
--- a/lib/acl_entries.c
+++ b/lib/acl_entries.c
@@ -1,6 +1,6 @@
 /* Return the number of entries in an ACL.
 
-   Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/af_alg.h b/lib/af_alg.h
index e8ffb3f7a09..ed933e1208d 100644
--- a/lib/af_alg.h
+++ b/lib/af_alg.h
@@ -1,5 +1,5 @@
 /* af_alg.h - Compute message digests from file streams and buffers.
-   Copyright (C) 2018-2023 Free Software Foundation, Inc.
+   Copyright (C) 2018-2024 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
diff --git a/lib/alloca.in.h b/lib/alloca.in.h
index a1bb3d758dc..6aa47df8ec3 100644
--- a/lib/alloca.in.h
+++ b/lib/alloca.in.h
@@ -1,6 +1,6 @@
 /* Memory allocation on the stack.
 
-   Copyright (C) 1995, 1999, 2001-2004, 2006-2023 Free Software Foundation,
+   Copyright (C) 1995, 1999, 2001-2004, 2006-2024 Free Software Foundation,
    Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/allocator.c b/lib/allocator.c
index 922be1fce8d..79fffbed14b 100644
--- a/lib/allocator.c
+++ b/lib/allocator.c
@@ -1,6 +1,6 @@
 /* Memory allocators such as malloc+free.
 
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 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
diff --git a/lib/allocator.h b/lib/allocator.h
index 0c830d01cda..bb30a3440c2 100644
--- a/lib/allocator.h
+++ b/lib/allocator.h
@@ -1,6 +1,6 @@
 /* Memory allocators such as malloc+free.
 
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 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
diff --git a/lib/arg-nonnull.h b/lib/arg-nonnull.h
index 9498ae1f7da..46c711ca1a1 100644
--- a/lib/arg-nonnull.h
+++ b/lib/arg-nonnull.h
@@ -1,5 +1,5 @@
 /* A C macro for declaring that specific arguments must not be NULL.
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published
diff --git a/lib/assert.in.h b/lib/assert.in.h
index b0ab99c776e..6e4995e1455 100644
--- a/lib/assert.in.h
+++ b/lib/assert.in.h
@@ -1,5 +1,5 @@
 /* Substitute for and wrapper around <assert.h>
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 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
diff --git a/lib/at-func.c b/lib/at-func.c
index 13e3fb32056..56b313f4749 100644
--- a/lib/at-func.c
+++ b/lib/at-func.c
@@ -1,5 +1,5 @@
 /* Define at-style functions like fstatat, unlinkat, fchownat, etc.
-   Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/attribute.h b/lib/attribute.h
index 9464fde0f30..710341ba417 100644
--- a/lib/attribute.h
+++ b/lib/attribute.h
@@ -1,6 +1,6 @@
 /* ATTRIBUTE_* macros for using attributes in GCC and similar compilers
 
-   Copyright 2020-2023 Free Software Foundation, Inc.
+   Copyright 2020-2024 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
@@ -182,6 +182,8 @@
 
 /* The function does not throw exceptions.  */
 /* Applies to: functions.  */
+/* After a function's parameter list, this attribute must come first, before
+   other attributes.  */
 #define ATTRIBUTE_NOTHROW _GL_ATTRIBUTE_NOTHROW
 
 /* Do not inline the function.  */
diff --git a/lib/binary-io.c b/lib/binary-io.c
index 28a9e6ed69c..40f01d67ee1 100644
--- a/lib/binary-io.c
+++ b/lib/binary-io.c
@@ -1,5 +1,5 @@
 /* Binary mode I/O.
-   Copyright 2017-2023 Free Software Foundation, Inc.
+   Copyright 2017-2024 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
diff --git a/lib/binary-io.h b/lib/binary-io.h
index 855d6f819f0..0cc5c11748c 100644
--- a/lib/binary-io.h
+++ b/lib/binary-io.h
@@ -1,5 +1,5 @@
 /* Binary mode I/O.
-   Copyright (C) 2001, 2003, 2005, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2003, 2005, 2008-2024 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
diff --git a/lib/boot-time-aux.h b/lib/boot-time-aux.h
index e59a0fd03c7..8b966fe691f 100644
--- a/lib/boot-time-aux.h
+++ b/lib/boot-time-aux.h
@@ -1,5 +1,5 @@
 /* Auxiliary functions for determining the time when the machine last booted.
-   Copyright (C) 2023 Free Software Foundation, Inc.
+   Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published
@@ -86,15 +86,21 @@ get_linux_uptime (struct timespec *p_uptime)
 static int
 get_linux_boot_time_fallback (struct timespec *p_boot_time)
 {
-  /* On Alpine Linux, UTMP_FILE is not filled.  It is always empty.
-     So, get the time stamp of a file that gets touched only during the
-     boot process.  */
+  /* On Devuan with the 'runit' init system and on Artix with the 's6' init
+     system, UTMP_FILE contains USER_PROCESS and other entries, but no
+     BOOT_TIME entry.
+     On Alpine Linux, UTMP_FILE is not filled.  It is always empty.
+     So, in both cases, get the time stamp of a file that gets touched only
+     during the boot process.  */
 
   const char * const boot_touched_files[] =
     {
       "/var/lib/systemd/random-seed", /* seen on distros with systemd */
-      "/var/run/utmp",                /* seen on distros with OpenRC */
-      "/var/lib/random-seed"          /* seen on older distros */
+      "/var/lib/urandom/random-seed", /* seen on Devuan with runit */
+      "/var/lib/random-seed",         /* seen on Artix with s6 */
+      /* This must come last, since on several distros /var/run/utmp is
+         modified when a user logs in, i.e. long after boot.  */
+      "/var/run/utmp"                 /* seen on Alpine Linux with OpenRC */
     };
   for (idx_t i = 0; i < SIZEOF (boot_touched_files); i++)
     {
diff --git a/lib/boot-time.c b/lib/boot-time.c
index fe5b5b88c8e..c1171e8024d 100644
--- a/lib/boot-time.c
+++ b/lib/boot-time.c
@@ -1,5 +1,5 @@
 /* Determine the time when the machine last booted.
-   Copyright (C) 2023 Free Software Foundation, Inc.
+   Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published
@@ -203,7 +203,14 @@ get_boot_time_uncached (struct timespec *p_boot_time)
     }
 #  endif
 
-# else /* old FreeBSD, OpenBSD, native Windows */
+# else /* Adélie Linux, old FreeBSD, OpenBSD, native Windows */
+
+#  if defined __linux__ && !defined __ANDROID__
+  /* Workaround for Adélie Linux:  */
+  get_linux_boot_time_fallback (&found_boot_time);
+  if (found_boot_time.tv_sec == 0)
+    get_linux_boot_time_final_fallback (&found_boot_time);
+#  endif
 
 #  if defined __OpenBSD__
   /* Workaround for OpenBSD:  */
diff --git a/lib/boot-time.h b/lib/boot-time.h
index 401e854adbb..99684323ec6 100644
--- a/lib/boot-time.h
+++ b/lib/boot-time.h
@@ -1,5 +1,5 @@
 /* Determine the time when the machine last booted.
-   Copyright (C) 2023 Free Software Foundation, Inc.
+   Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published
diff --git a/lib/byteswap.in.h b/lib/byteswap.in.h
index e61be27e917..8e49efad05a 100644
--- a/lib/byteswap.in.h
+++ b/lib/byteswap.in.h
@@ -1,5 +1,5 @@
 /* byteswap.h - Byte swapping
-   Copyright (C) 2005, 2007, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2007, 2009-2024 Free Software Foundation, Inc.
    Written by Oskar Liljeblad <oskar@osk.mine.nu>, 2005.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/c++defs.h b/lib/c++defs.h
index 458c014de5c..eb66967b09b 100644
--- a/lib/c++defs.h
+++ b/lib/c++defs.h
@@ -1,5 +1,5 @@
 /* C++ compatible function declaration macros.
-   Copyright (C) 2010-2023 Free Software Foundation, Inc.
+   Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published
diff --git a/lib/c-ctype.c b/lib/c-ctype.c
index a4343f445f0..d3f1b12d5a9 100644
--- a/lib/c-ctype.c
+++ b/lib/c-ctype.c
@@ -1,6 +1,6 @@
 /* Character handling in C locale.
 
-   Copyright (C) 2003-2023 Free Software Foundation, Inc.
+   Copyright (C) 2003-2024 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
diff --git a/lib/c-ctype.h b/lib/c-ctype.h
index cb0f4f3ba1f..b582de4a7fd 100644
--- a/lib/c-ctype.h
+++ b/lib/c-ctype.h
@@ -5,7 +5,7 @@
    <ctype.h> functions' behaviour depends on the current locale set via
    setlocale.
 
-   Copyright (C) 2000-2003, 2006, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2000-2003, 2006, 2008-2024 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
diff --git a/lib/c-strcase.h b/lib/c-strcase.h
index 5dfa96c41f4..b75e8dd1cb3 100644
--- a/lib/c-strcase.h
+++ b/lib/c-strcase.h
@@ -1,5 +1,5 @@
 /* Case-insensitive string comparison functions in C locale.
-   Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2023 Free Software
+   Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2024 Free Software
    Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/c-strcasecmp.c b/lib/c-strcasecmp.c
index 8a958dc4fd9..1fa575a8562 100644
--- a/lib/c-strcasecmp.c
+++ b/lib/c-strcasecmp.c
@@ -1,5 +1,5 @@
 /* c-strcasecmp.c -- case insensitive string comparator in C locale
-   Copyright (C) 1998-1999, 2005-2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 1998-1999, 2005-2006, 2009-2024 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
diff --git a/lib/c-strncasecmp.c b/lib/c-strncasecmp.c
index 4ca8c5f4001..4c8b0b6b841 100644
--- a/lib/c-strncasecmp.c
+++ b/lib/c-strncasecmp.c
@@ -1,5 +1,5 @@
 /* c-strncasecmp.c -- case insensitive string comparator in C locale
-   Copyright (C) 1998-1999, 2005-2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 1998-1999, 2005-2006, 2009-2024 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
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c
index e701297d84b..efd79ceebb8 100644
--- a/lib/canonicalize-lgpl.c
+++ b/lib/canonicalize-lgpl.c
@@ -1,5 +1,5 @@
 /* Return the canonical absolute name of a given file.
-   Copyright (C) 1996-2023 Free Software Foundation, Inc.
+   Copyright (C) 1996-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c
index 49c92dcc196..f308b6963ae 100644
--- a/lib/careadlinkat.c
+++ b/lib/careadlinkat.c
@@ -1,6 +1,6 @@
 /* Read symbolic links into a buffer without size limitation, relative to fd.
 
-   Copyright (C) 2001, 2003-2004, 2007, 2009-2023 Free Software Foundation,
+   Copyright (C) 2001, 2003-2004, 2007, 2009-2024 Free Software Foundation,
    Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/careadlinkat.h b/lib/careadlinkat.h
index 562cf013b75..473e6531e67 100644
--- a/lib/careadlinkat.h
+++ b/lib/careadlinkat.h
@@ -1,6 +1,6 @@
 /* Read symbolic links into a buffer without size limitation, relative to fd.
 
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 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
diff --git a/lib/cdefs.h b/lib/cdefs.h
index 412f036ce35..d38382ad9d8 100644
--- a/lib/cdefs.h
+++ b/lib/cdefs.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2024 Free Software Foundation, Inc.
    Copyright The GNU Toolchain Authors.
    This file is part of the GNU C Library.
 
@@ -42,8 +42,8 @@
 #if (defined __has_attribute \
      && (!defined __clang_minor__ \
          || (defined __apple_build_version__ \
-             ? 6000000 <= __apple_build_version__ \
-             : 3 < __clang_major__ + (5 <= __clang_minor__))))
+             ? 7000000 <= __apple_build_version__ \
+             : 5 <= __clang_major__)))
 # define __glibc_has_attribute(attr) __has_attribute (attr)
 #else
 # define __glibc_has_attribute(attr) 0
diff --git a/lib/cloexec.c b/lib/cloexec.c
index e4cecbd2e8a..cdb0d740eb7 100644
--- a/lib/cloexec.c
+++ b/lib/cloexec.c
@@ -1,6 +1,6 @@
 /* cloexec.c - set or clear the close-on-exec descriptor flag
 
-   Copyright (C) 1991, 2004-2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 1991, 2004-2006, 2009-2024 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
diff --git a/lib/cloexec.h b/lib/cloexec.h
index 057fd668c9b..f52e5f2ec0f 100644
--- a/lib/cloexec.h
+++ b/lib/cloexec.h
@@ -1,6 +1,6 @@
 /* cloexec.c - set or clear the close-on-exec descriptor flag
 
-   Copyright (C) 2004, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2009-2024 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
diff --git a/lib/close-stream.c b/lib/close-stream.c
index ab686bac2ae..81094c6863c 100644
--- a/lib/close-stream.c
+++ b/lib/close-stream.c
@@ -1,6 +1,6 @@
 /* Close a stream, with nicer error checking than fclose's.
 
-   Copyright (C) 1998-2002, 2004, 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 1998-2002, 2004, 2006-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/close-stream.h b/lib/close-stream.h
index 3b52cc66c3d..8a1b3c7ac2c 100644
--- a/lib/close-stream.h
+++ b/lib/close-stream.h
@@ -1,6 +1,6 @@
 /* Close a stream, with nicer error checking than fclose's.
 
-   Copyright (C) 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published
diff --git a/lib/copy-file-range.c b/lib/copy-file-range.c
index 747a5a8ad1d..e7e3a441c6b 100644
--- a/lib/copy-file-range.c
+++ b/lib/copy-file-range.c
@@ -1,5 +1,5 @@
 /* Stub for copy_file_range
-   Copyright 2019-2023 Free Software Foundation, Inc.
+   Copyright 2019-2024 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
diff --git a/lib/count-leading-zeros.c b/lib/count-leading-zeros.c
index 949f156eab1..2bbfd674849 100644
--- a/lib/count-leading-zeros.c
+++ b/lib/count-leading-zeros.c
@@ -1,6 +1,6 @@
 /* Count the number of leading 0 bits in a word.
 
-   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Copyright (C) 2012-2024 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
diff --git a/lib/count-leading-zeros.h b/lib/count-leading-zeros.h
index 9fe2a03ee09..545749d6d27 100644
--- a/lib/count-leading-zeros.h
+++ b/lib/count-leading-zeros.h
@@ -1,5 +1,5 @@
 /* count-leading-zeros.h -- counts the number of leading 0 bits in a word.
-   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Copyright (C) 2012-2024 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
diff --git a/lib/count-one-bits.c b/lib/count-one-bits.c
index 8a348f2e5a0..54b87088028 100644
--- a/lib/count-one-bits.c
+++ b/lib/count-one-bits.c
@@ -1,6 +1,6 @@
 /* Count the number of 1-bits in a word.
 
-   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Copyright (C) 2012-2024 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
diff --git a/lib/count-one-bits.h b/lib/count-one-bits.h
index 2821a1fb75e..8d67f8718a4 100644
--- a/lib/count-one-bits.h
+++ b/lib/count-one-bits.h
@@ -1,5 +1,5 @@
 /* count-one-bits.h -- counts the number of 1-bits in a word.
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 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
diff --git a/lib/count-trailing-zeros.c b/lib/count-trailing-zeros.c
index f6fddab4232..e13f77788da 100644
--- a/lib/count-trailing-zeros.c
+++ b/lib/count-trailing-zeros.c
@@ -1,6 +1,6 @@
 /* Count the number of trailing 0 bits in a word.
 
-   Copyright 2013-2023 Free Software Foundation, Inc.
+   Copyright 2013-2024 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
diff --git a/lib/count-trailing-zeros.h b/lib/count-trailing-zeros.h
index 9b33df76f6d..ed1e0131147 100644
--- a/lib/count-trailing-zeros.h
+++ b/lib/count-trailing-zeros.h
@@ -1,5 +1,5 @@
 /* count-trailing-zeros.h -- counts the number of trailing 0 bits in a word.
-   Copyright 2013-2023 Free Software Foundation, Inc.
+   Copyright 2013-2024 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
diff --git a/lib/diffseq.h b/lib/diffseq.h
index 3f85ab2ec41..0c5bc9cbc6d 100644
--- a/lib/diffseq.h
+++ b/lib/diffseq.h
@@ -1,6 +1,6 @@
 /* Analyze differences between two vectors.
 
-   Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2023 Free Software
+   Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2024 Free Software
    Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
diff --git a/lib/dirent-private.h b/lib/dirent-private.h
index 012b6837198..335fbc351a5 100644
--- a/lib/dirent-private.h
+++ b/lib/dirent-private.h
@@ -1,5 +1,5 @@
 /* Private details of the DIR type.
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 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
diff --git a/lib/dirent.in.h b/lib/dirent.in.h
index d409a031ec8..f05b880077f 100644
--- a/lib/dirent.in.h
+++ b/lib/dirent.in.h
@@ -1,5 +1,5 @@
 /* A GNU-like <dirent.h>.
-   Copyright (C) 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006-2024 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
@@ -237,12 +237,6 @@ _GL_WARN_ON_USE (rewinddir, "rewinddir is not portable - "
 _GL_FUNCDECL_RPL (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1)));
 _GL_CXXALIAS_RPL (dirfd, int, (DIR *));
 
-#  ifdef __KLIBC__
-/* Gnulib internal hooks needed to maintain the dirfd metadata.  */
-_GL_EXTERN_C int _gl_register_dirp_fd (int fd, DIR *dirp)
-     _GL_ARG_NONNULL ((2));
-_GL_EXTERN_C void _gl_unregister_dirp_fd (int fd);
-#  endif
 # else
 #  if defined __cplusplus && defined GNULIB_NAMESPACE && defined dirfd
     /* dirfd is defined as a macro and not as a function.
diff --git a/lib/dirfd.c b/lib/dirfd.c
index 75b2163c353..afcf382e301 100644
--- a/lib/dirfd.c
+++ b/lib/dirfd.c
@@ -1,6 +1,6 @@
 /* dirfd.c -- return the file descriptor associated with an open DIR*
 
-   Copyright (C) 2001, 2006, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2006, 2008-2024 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
@@ -26,59 +26,6 @@
 # include "dirent-private.h"
 #endif
 
-#ifdef __KLIBC__
-# include <stdlib.h>
-# include <io.h>
-
-static struct dirp_fd_list
-{
-  DIR *dirp;
-  int fd;
-  struct dirp_fd_list *next;
-} *dirp_fd_start = NULL;
-
-/* Register fd associated with dirp to dirp_fd_list. */
-int
-_gl_register_dirp_fd (int fd, DIR *dirp)
-{
-  struct dirp_fd_list *new_dirp_fd = malloc (sizeof *new_dirp_fd);
-  if (!new_dirp_fd)
-    return -1;
-
-  new_dirp_fd->dirp = dirp;
-  new_dirp_fd->fd = fd;
-  new_dirp_fd->next = dirp_fd_start;
-
-  dirp_fd_start = new_dirp_fd;
-
-  return 0;
-}
-
-/* Unregister fd from dirp_fd_list with closing it */
-void
-_gl_unregister_dirp_fd (int fd)
-{
-  struct dirp_fd_list *dirp_fd;
-  struct dirp_fd_list *dirp_fd_prev;
-
-  for (dirp_fd_prev = NULL, dirp_fd = dirp_fd_start; dirp_fd;
-       dirp_fd_prev = dirp_fd, dirp_fd = dirp_fd->next)
-    {
-      if (dirp_fd->fd == fd)
-        {
-          if (dirp_fd_prev)
-            dirp_fd_prev->next = dirp_fd->next;
-          else  /* dirp_fd == dirp_fd_start */
-            dirp_fd_start = dirp_fd_start->next;
-
-          close (fd);
-          free (dirp_fd);
-          break;
-        }
-    }
-}
-#endif
-
 int
 dirfd (DIR *dir_p)
 {
@@ -90,19 +37,7 @@ dirfd (DIR *dir_p)
 #else
   int fd = DIR_TO_FD (dir_p);
   if (fd == -1)
-# ifndef __KLIBC__
     errno = ENOTSUP;
-# else
-    {
-      struct dirp_fd_list *dirp_fd;
-
-      for (dirp_fd = dirp_fd_start; dirp_fd; dirp_fd = dirp_fd->next)
-        if (dirp_fd->dirp == dir_p)
-          return dirp_fd->fd;
-
-      errno = EINVAL;
-    }
-# endif
 
   return fd;
 #endif
diff --git a/lib/dtoastr.c b/lib/dtoastr.c
index 66b50995c79..09ddc3c6688 100644
--- a/lib/dtoastr.c
+++ b/lib/dtoastr.c
@@ -1,6 +1,6 @@
 /* Convert 'double' to accurate string.
 
-   Copyright (C) 2010-2023 Free Software Foundation, Inc.
+   Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published
diff --git a/lib/dtotimespec.c b/lib/dtotimespec.c
index 28a44b69171..0557961cf97 100644
--- a/lib/dtotimespec.c
+++ b/lib/dtotimespec.c
@@ -1,6 +1,6 @@
 /* Convert double to timespec.
 
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/dup2.c b/lib/dup2.c
index 7d197ca3123..916e113dd89 100644
--- a/lib/dup2.c
+++ b/lib/dup2.c
@@ -1,6 +1,6 @@
 /* Duplicate an open file descriptor to a specified file descriptor.
 
-   Copyright (C) 1999, 2004-2007, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2004-2007, 2009-2024 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
diff --git a/lib/dynarray.h b/lib/dynarray.h
index 9155910934f..8940e81b25d 100644
--- a/lib/dynarray.h
+++ b/lib/dynarray.h
@@ -1,5 +1,5 @@
 /* Type-safe arrays which grow dynamically.
-   Copyright 2021-2023 Free Software Foundation, Inc.
+   Copyright 2021-2024 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
diff --git a/lib/eloop-threshold.h b/lib/eloop-threshold.h
index d9b154e4868..84d19b458b8 100644
--- a/lib/eloop-threshold.h
+++ b/lib/eloop-threshold.h
@@ -1,5 +1,5 @@
 /* Threshold at which to diagnose ELOOP.  Generic version.
-   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Copyright (C) 2012-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/errno.in.h b/lib/errno.in.h
index 3dda9c260e6..aa658e62708 100644
--- a/lib/errno.in.h
+++ b/lib/errno.in.h
@@ -1,6 +1,6 @@
 /* A POSIX-like <errno.h>.
 
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 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
diff --git a/lib/euidaccess.c b/lib/euidaccess.c
index c2ecbeff52a..ad392dba19c 100644
--- a/lib/euidaccess.c
+++ b/lib/euidaccess.c
@@ -1,6 +1,6 @@
 /* euidaccess -- check if effective user id can access file
 
-   Copyright (C) 1990-1991, 1995, 1998, 2000, 2003-2006, 2008-2023 Free
+   Copyright (C) 1990-1991, 1995, 1998, 2000, 2003-2006, 2008-2024 Free
    Software Foundation, Inc.
 
    This file is part of the GNU C Library.
diff --git a/lib/execinfo.c b/lib/execinfo.c
index 2048d00f5fb..ea30f4140b2 100644
--- a/lib/execinfo.c
+++ b/lib/execinfo.c
@@ -1,6 +1,6 @@
 /* Information about executables.
 
-   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Copyright (C) 2012-2024 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
diff --git a/lib/execinfo.in.h b/lib/execinfo.in.h
index 56b04d1d862..0ffb2c386e7 100644
--- a/lib/execinfo.in.h
+++ b/lib/execinfo.in.h
@@ -1,6 +1,6 @@
 /* Information about executables.
 
-   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
diff --git a/lib/explicit_bzero.c b/lib/explicit_bzero.c
index c33cab9e6d5..91c31c52dd3 100644
--- a/lib/explicit_bzero.c
+++ b/lib/explicit_bzero.c
@@ -1,5 +1,5 @@
 /* Erasure of sensitive data, generic implementation.
-   Copyright (C) 2016-2023 Free Software Foundation, Inc.
+   Copyright (C) 2016-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/faccessat.c b/lib/faccessat.c
index ac8977cfd65..8178ca8632e 100644
--- a/lib/faccessat.c
+++ b/lib/faccessat.c
@@ -1,5 +1,5 @@
 /* Check the access rights of a file relative to an open directory.
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -40,10 +40,14 @@ orig_faccessat (int fd, char const *name, int mode, int 
flag)
 }
 #endif
 
+#ifdef __osf__
 /* Write "unistd.h" here, not <unistd.h>, otherwise OSF/1 5.1 DTK cc
    eliminates this include because of the preliminary #include <unistd.h>
    above.  */
-#include "unistd.h"
+# include "unistd.h"
+#else
+# include <unistd.h>
+#endif
 
 #ifndef HAVE_ACCESS
 /* Mingw lacks access, but it also lacks real vs. effective ids, so
diff --git a/lib/fchmodat.c b/lib/fchmodat.c
index a7b70a2af2c..00f6cf62448 100644
--- a/lib/fchmodat.c
+++ b/lib/fchmodat.c
@@ -1,5 +1,5 @@
 /* Change the protections of file relative to an open directory.
-   Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/fcntl.c b/lib/fcntl.c
index e220800845b..7cd3a0f976d 100644
--- a/lib/fcntl.c
+++ b/lib/fcntl.c
@@ -1,6 +1,6 @@
 /* Provide file descriptor control.
 
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 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
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index d0bb85f30b5..eea3b9542a5 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -1,6 +1,6 @@
 /* Like <fcntl.h>, but with non-working flags defined to 0.
 
-   Copyright (C) 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006-2024 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
diff --git a/lib/fdopendir.c b/lib/fdopendir.c
index 0f43d6ff349..bdbb2ea912f 100644
--- a/lib/fdopendir.c
+++ b/lib/fdopendir.c
@@ -1,5 +1,5 @@
 /* provide a replacement fdopendir function
-   Copyright (C) 2004-2023 Free Software Foundation, Inc.
+   Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -44,42 +44,6 @@ fdopendir (int fd)
   return dirp;
 }
 
-# elif defined __KLIBC__
-
-#  include <InnoTekLIBC/backend.h>
-
-DIR *
-fdopendir (int fd)
-{
-  char path[_MAX_PATH];
-  DIR *dirp;
-
-  /* Get a path from fd */
-  if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
-    return NULL;
-
-  dirp = opendir (path);
-  if (!dirp)
-    return NULL;
-
-  /* Unregister fd registered by opendir() */
-  _gl_unregister_dirp_fd (dirfd (dirp));
-
-  /* Register our fd */
-  if (_gl_register_dirp_fd (fd, dirp))
-    {
-      int saved_errno = errno;
-
-      closedir (dirp);
-
-      errno = saved_errno;
-
-      dirp = NULL;
-    }
-
-  return dirp;
-}
-
 # else
 /* We are not in control of the file descriptor of a DIR, and therefore have to
    play tricks with file descriptors before and after a call to opendir().  */
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
index 3eeaf9c57d1..898fb030d1d 100644
--- a/lib/file-has-acl.c
+++ b/lib/file-has-acl.c
@@ -1,6 +1,6 @@
 /* Test whether a file has a nontrivial ACL.  -*- coding: utf-8 -*-
 
-   Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/filemode.c b/lib/filemode.c
index 318d287f27d..9be6aad1878 100644
--- a/lib/filemode.c
+++ b/lib/filemode.c
@@ -1,6 +1,6 @@
 /* filemode.c -- make a string describing file modes
 
-   Copyright (C) 1985, 1990, 1993, 1998-2000, 2004, 2006, 2009-2023 Free
+   Copyright (C) 1985, 1990, 1993, 1998-2000, 2004, 2006, 2009-2024 Free
    Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
diff --git a/lib/filemode.h b/lib/filemode.h
index 3e1d9903eac..2dee82f0be1 100644
--- a/lib/filemode.h
+++ b/lib/filemode.h
@@ -1,6 +1,6 @@
 /* Make a string describing file modes.
 
-   Copyright (C) 1998-1999, 2003, 2006, 2009-2023 Free Software Foundation,
+   Copyright (C) 1998-1999, 2003, 2006, 2009-2024 Free Software Foundation,
    Inc.
 
    This program is free software: you can redistribute it and/or modify
diff --git a/lib/filename.h b/lib/filename.h
index a2400a9dfe3..4f0f0fbc3c6 100644
--- a/lib/filename.h
+++ b/lib/filename.h
@@ -1,5 +1,5 @@
 /* Basic filename support macros.
-   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/filevercmp.c b/lib/filevercmp.c
index 78e1faff536..88745b5f1d4 100644
--- a/lib/filevercmp.c
+++ b/lib/filevercmp.c
@@ -2,7 +2,7 @@
 
    Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
    Copyright (C) 2001 Anthony Towns <aj@azure.humbug.org.au>
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 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
diff --git a/lib/filevercmp.h b/lib/filevercmp.h
index 9e052bdd08c..8c549fcda00 100644
--- a/lib/filevercmp.h
+++ b/lib/filevercmp.h
@@ -2,7 +2,7 @@
 
    Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
    Copyright (C) 2001 Anthony Towns <aj@azure.humbug.org.au>
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 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
diff --git a/lib/fingerprint.c b/lib/fingerprint.c
index d83de2245e8..52d4b25e599 100644
--- a/lib/fingerprint.c
+++ b/lib/fingerprint.c
@@ -1,6 +1,6 @@
 /* Placeholder fingerprint for Emacs
 
-Copyright 2019-2023 Free Software Foundation, Inc.
+Copyright 2019-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/lib/fingerprint.h b/lib/fingerprint.h
index 0bb099ceeee..74a6a4b281d 100644
--- a/lib/fingerprint.h
+++ b/lib/fingerprint.h
@@ -1,6 +1,6 @@
 /* Header file for the Emacs build fingerprint.
 
-Copyright (C) 2016, 2018-2023 Free Software Foundation, Inc.
+Copyright (C) 2016, 2018-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/lib/flexmember.h b/lib/flexmember.h
index 8df44195392..6ef66a32d32 100644
--- a/lib/flexmember.h
+++ b/lib/flexmember.h
@@ -1,6 +1,6 @@
 /* Sizes of structs with flexible array members.
 
-   Copyright 2016-2023 Free Software Foundation, Inc.
+   Copyright 2016-2024 Free Software Foundation, Inc.
 
    This file is part of the GNU C Library.
 
diff --git a/lib/fpending.c b/lib/fpending.c
index e57155e586e..51468955844 100644
--- a/lib/fpending.c
+++ b/lib/fpending.c
@@ -1,5 +1,5 @@
 /* fpending.c -- return the number of pending output bytes on a stream
-   Copyright (C) 2000, 2004, 2006-2007, 2009-2023 Free Software Foundation,
+   Copyright (C) 2000, 2004, 2006-2007, 2009-2024 Free Software Foundation,
    Inc.
 
    This program is free software: you can redistribute it and/or modify
diff --git a/lib/fpending.h b/lib/fpending.h
index 1604ca0b7af..28db3b403d9 100644
--- a/lib/fpending.h
+++ b/lib/fpending.h
@@ -1,6 +1,6 @@
 /* Declare __fpending.
 
-   Copyright (C) 2000, 2003, 2005-2006, 2009-2023 Free Software Foundation,
+   Copyright (C) 2000, 2003, 2005-2006, 2009-2024 Free Software Foundation,
    Inc.
 
    This program is free software: you can redistribute it and/or modify
diff --git a/lib/free.c b/lib/free.c
index 372a6b0fecf..2f0c40ba89d 100644
--- a/lib/free.c
+++ b/lib/free.c
@@ -1,6 +1,6 @@
 /* Make free() preserve errno.
 
-   Copyright (C) 2003, 2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2006, 2009-2024 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
diff --git a/lib/fstatat.c b/lib/fstatat.c
index 372965ef5f6..470ef336cff 100644
--- a/lib/fstatat.c
+++ b/lib/fstatat.c
@@ -1,6 +1,6 @@
 /* Work around an fstatat bug on Solaris 9.
 
-   Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/fsusage.c b/lib/fsusage.c
index f6f4b1c35fd..97d0eef7aa8 100644
--- a/lib/fsusage.c
+++ b/lib/fsusage.c
@@ -1,6 +1,6 @@
 /* fsusage.c -- return space usage of mounted file systems
 
-   Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2023 Free Software
+   Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2024 Free Software
    Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/fsusage.h b/lib/fsusage.h
index 9630b04e001..d7ae5f63a36 100644
--- a/lib/fsusage.h
+++ b/lib/fsusage.h
@@ -1,6 +1,6 @@
 /* fsusage.h -- declarations for file system space usage info
 
-   Copyright (C) 1991-1992, 1997, 2003-2006, 2009-2023 Free Software
+   Copyright (C) 1991-1992, 1997, 2003-2006, 2009-2024 Free Software
    Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/fsync.c b/lib/fsync.c
index 51314662872..10a70023a15 100644
--- a/lib/fsync.c
+++ b/lib/fsync.c
@@ -7,7 +7,7 @@
 
    Written by Richard W.M. Jones <rjones.at.redhat.com>
 
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 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
diff --git a/lib/ftoastr.c b/lib/ftoastr.c
index 8740a4d86c8..4ecde06cea9 100644
--- a/lib/ftoastr.c
+++ b/lib/ftoastr.c
@@ -1,6 +1,6 @@
 /* floating point to accurate string
 
-   Copyright (C) 2010-2023 Free Software Foundation, Inc.
+   Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/ftoastr.h b/lib/ftoastr.h
index 1ce1b7a4bc6..ed43c961a04 100644
--- a/lib/ftoastr.h
+++ b/lib/ftoastr.h
@@ -1,6 +1,6 @@
 /* floating point to accurate string
 
-   Copyright (C) 2010-2023 Free Software Foundation, Inc.
+   Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/futimens.c b/lib/futimens.c
index 5bb30493c7e..defae933ade 100644
--- a/lib/futimens.c
+++ b/lib/futimens.c
@@ -1,5 +1,5 @@
 /* Set the access and modification time of an open fd.
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 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
diff --git a/lib/get-permissions.c b/lib/get-permissions.c
index 545ad23195b..36848d3d080 100644
--- a/lib/get-permissions.c
+++ b/lib/get-permissions.c
@@ -1,6 +1,6 @@
 /* Get permissions of a file.  -*- coding: utf-8 -*-
 
-   Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/getdelim.c b/lib/getdelim.c
index e414df648f6..58063b156e7 100644
--- a/lib/getdelim.c
+++ b/lib/getdelim.c
@@ -1,5 +1,5 @@
 /* getdelim.c --- Implementation of replacement getdelim function.
-   Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2023 Free Software
+   Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2024 Free Software
    Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/getdtablesize.c b/lib/getdtablesize.c
index ac2d1753a6b..762c100b38a 100644
--- a/lib/getdtablesize.c
+++ b/lib/getdtablesize.c
@@ -1,5 +1,5 @@
 /* getdtablesize() function: Return maximum possible file descriptor value + 1.
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2008.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/getgroups.c b/lib/getgroups.c
index 93829d3b15e..9f4908e9977 100644
--- a/lib/getgroups.c
+++ b/lib/getgroups.c
@@ -1,6 +1,6 @@
 /* provide consistent interface to getgroups for systems that don't allow N==0
 
-   Copyright (C) 1996, 1999, 2003, 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1999, 2003, 2006-2024 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
diff --git a/lib/getline.c b/lib/getline.c
index 85f16ab8bac..2d03b64689e 100644
--- a/lib/getline.c
+++ b/lib/getline.c
@@ -1,5 +1,5 @@
 /* getline.c --- Implementation of replacement getline function.
-   Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2005-2007, 2009-2024 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
diff --git a/lib/getloadavg.c b/lib/getloadavg.c
index 59b53e79980..c940e4c7ee0 100644
--- a/lib/getloadavg.c
+++ b/lib/getloadavg.c
@@ -1,6 +1,6 @@
 /* Get the system load averages.
 
-   Copyright (C) 1985-1989, 1991-1995, 1997, 1999-2000, 2003-2023 Free Software
+   Copyright (C) 1985-1989, 1991-1995, 1997, 1999-2000, 2003-2024 Free Software
    Foundation, Inc.
 
    NOTE: The canonical source of this file is maintained with gnulib.
diff --git a/lib/getopt-cdefs.in.h b/lib/getopt-cdefs.in.h
index e76c78cb212..a1d304d49e8 100644
--- a/lib/getopt-cdefs.in.h
+++ b/lib/getopt-cdefs.in.h
@@ -1,5 +1,5 @@
 /* getopt-on-non-glibc compatibility macros.
-   Copyright (C) 1989-2023 Free Software Foundation, Inc.
+   Copyright (C) 1989-2024 Free Software Foundation, Inc.
    This file is part of gnulib.
    Unlike most of the getopt implementation, it is NOT shared
    with the GNU C Library.
@@ -57,7 +57,11 @@
 
 #ifndef __THROW
 # if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major__ >= 4)
-#  define __THROW       throw ()
+#  if __cplusplus >= 201103L
+#   define __THROW      noexcept (true)
+#  else
+#   define __THROW      throw ()
+#  endif
 # else
 #  define __THROW
 # endif
diff --git a/lib/getopt-core.h b/lib/getopt-core.h
index c5dd49363f0..12d09a25c0d 100644
--- a/lib/getopt-core.h
+++ b/lib/getopt-core.h
@@ -1,5 +1,5 @@
 /* Declarations for getopt (basic, portable features only).
-   Copyright (C) 1989-2023 Free Software Foundation, Inc.
+   Copyright (C) 1989-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library and is also part of gnulib.
    Patches to this file should be submitted to both projects.
 
diff --git a/lib/getopt-ext.h b/lib/getopt-ext.h
index d37c29328b2..e4b499d4e82 100644
--- a/lib/getopt-ext.h
+++ b/lib/getopt-ext.h
@@ -1,5 +1,5 @@
 /* Declarations for getopt (GNU extensions).
-   Copyright (C) 1989-2023 Free Software Foundation, Inc.
+   Copyright (C) 1989-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library and is also part of gnulib.
    Patches to this file should be submitted to both projects.
 
diff --git a/lib/getopt-pfx-core.h b/lib/getopt-pfx-core.h
index 095e3930feb..78b7816aa42 100644
--- a/lib/getopt-pfx-core.h
+++ b/lib/getopt-pfx-core.h
@@ -1,5 +1,5 @@
 /* getopt (basic, portable features) gnulib wrapper header.
-   Copyright (C) 1989-2023 Free Software Foundation, Inc.
+   Copyright (C) 1989-2024 Free Software Foundation, Inc.
    This file is part of gnulib.
    Unlike most of the getopt implementation, it is NOT shared
    with the GNU C Library.
diff --git a/lib/getopt-pfx-ext.h b/lib/getopt-pfx-ext.h
index 8578d72530a..f001c11e057 100644
--- a/lib/getopt-pfx-ext.h
+++ b/lib/getopt-pfx-ext.h
@@ -1,5 +1,5 @@
 /* getopt (GNU extensions) gnulib wrapper header.
-   Copyright (C) 1989-2023 Free Software Foundation, Inc.
+   Copyright (C) 1989-2024 Free Software Foundation, Inc.
    This file is part of gnulib.
    Unlike most of the getopt implementation, it is NOT shared
    with the GNU C Library.
diff --git a/lib/getopt.c b/lib/getopt.c
index 1e2441c4afe..f66f119ec50 100644
--- a/lib/getopt.c
+++ b/lib/getopt.c
@@ -1,5 +1,5 @@
 /* Getopt for GNU.
-   Copyright (C) 1987-2023 Free Software Foundation, Inc.
+   Copyright (C) 1987-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library and is also part of gnulib.
    Patches to this file should be submitted to both projects.
 
@@ -21,7 +21,7 @@
 # include <config.h>
 #endif
 
-#include "getopt.h"
+#include <getopt.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -223,8 +223,9 @@ process_long_option (int argc, char **argv, const char 
*optstring,
     {
       /* Didn't find an exact match, so look for abbreviations.  */
       unsigned char *ambig_set = NULL;
-      int ambig_malloced = 0;
-      int ambig_fallback = 0;
+      /* Use simpler fallback diagnostic if ambig_set == &ambig_fallback.  */
+      unsigned char ambig_fallback;
+      void *ambig_malloced = NULL;
       int indfound = -1;
 
       for (p = longopts, option_index = 0; p->name; p++, option_index++)
@@ -242,39 +243,42 @@ process_long_option (int argc, char **argv, const char 
*optstring,
                     || pfound->val != p->val)
              {
                /* Second or later nonexact match found.  */
-               if (!ambig_fallback)
+               if (ambig_set != &ambig_fallback)
                  {
                    if (!print_errors)
                      /* Don't waste effort tracking the ambig set if
                         we're not going to print it anyway.  */
-                     ambig_fallback = 1;
+                     ambig_set = &ambig_fallback;
                    else if (!ambig_set)
                      {
                        if (__libc_use_alloca (n_options))
                          ambig_set = alloca (n_options);
-                       else if ((ambig_set = malloc (n_options)) == NULL)
-                         /* Fall back to simpler error message.  */
-                         ambig_fallback = 1;
                        else
-                         ambig_malloced = 1;
+                         {
+                           ambig_malloced = malloc (n_options);
+                           /* Fall back to simpler diagnostic if
+                              memory allocation fails.  */
+                           ambig_set = (ambig_malloced ? ambig_malloced
+                                        : &ambig_fallback);
+                         }
 
-                       if (ambig_set)
+                       if (ambig_set != &ambig_fallback)
                          {
                            memset (ambig_set, 0, n_options);
                            ambig_set[indfound] = 1;
                          }
                      }
-                   if (ambig_set)
+                   if (ambig_set && ambig_set != &ambig_fallback)
                      ambig_set[option_index] = 1;
                  }
              }
          }
 
-      if (ambig_set || ambig_fallback)
+      if (ambig_set)
        {
          if (print_errors)
            {
-             if (ambig_fallback)
+             if (ambig_set == &ambig_fallback)
                fprintf (stderr, _("%s: option '%s%s' is ambiguous\n"),
                         argv[0], prefix, d->__nextchar);
              else
@@ -296,8 +300,7 @@ process_long_option (int argc, char **argv, const char 
*optstring,
                  funlockfile (stderr);
                }
            }
-         if (ambig_malloced)
-           free (ambig_set);
+         free (ambig_malloced);
          d->__nextchar += strlen (d->__nextchar);
          d->optind++;
          d->optopt = 0;
diff --git a/lib/getopt.in.h b/lib/getopt.in.h
index 0867d365f47..c2411a754fa 100644
--- a/lib/getopt.in.h
+++ b/lib/getopt.in.h
@@ -1,5 +1,5 @@
 /* Declarations for getopt.
-   Copyright (C) 1989-2023 Free Software Foundation, Inc.
+   Copyright (C) 1989-2024 Free Software Foundation, Inc.
    This file is part of gnulib.
    Unlike most of the getopt implementation, it is NOT shared
    with the GNU C Library, which supplies a different version of
diff --git a/lib/getopt1.c b/lib/getopt1.c
index 49323aa8ed1..c42d29f8b57 100644
--- a/lib/getopt1.c
+++ b/lib/getopt1.c
@@ -1,5 +1,5 @@
 /* getopt_long and getopt_long_only entry points for GNU getopt.
-   Copyright (C) 1987-2023 Free Software Foundation, Inc.
+   Copyright (C) 1987-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library and is also part of gnulib.
    Patches to this file should be submitted to both projects.
 
@@ -21,7 +21,7 @@
 # include <config.h>
 #endif
 
-#include "getopt.h"
+#include <getopt.h>
 #include "getopt_int.h"
 
 int
diff --git a/lib/getopt_int.h b/lib/getopt_int.h
index 4d9e24beebc..c00c0b69404 100644
--- a/lib/getopt_int.h
+++ b/lib/getopt_int.h
@@ -1,5 +1,5 @@
 /* Internal declarations for getopt.
-   Copyright (C) 1989-2023 Free Software Foundation, Inc.
+   Copyright (C) 1989-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library and is also part of gnulib.
    Patches to this file should be submitted to both projects.
 
diff --git a/lib/getrandom.c b/lib/getrandom.c
index 19bb3429baf..44283cf1816 100644
--- a/lib/getrandom.c
+++ b/lib/getrandom.c
@@ -1,6 +1,6 @@
 /* Obtain a series of random bytes.
 
-   Copyright 2020-2023 Free Software Foundation, Inc.
+   Copyright 2020-2024 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
diff --git a/lib/gettext.h b/lib/gettext.h
index d0462c47e17..39d5ae4daa5 100644
--- a/lib/gettext.h
+++ b/lib/gettext.h
@@ -1,5 +1,5 @@
 /* Convenience header for conditional use of GNU <libintl.h>.
-   Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2023 Free Software
+   Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2024 Free Software
    Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/gettime.c b/lib/gettime.c
index ec40ff903e1..38d36859415 100644
--- a/lib/gettime.c
+++ b/lib/gettime.c
@@ -1,6 +1,6 @@
 /* gettime -- get the system clock
 
-   Copyright (C) 2002, 2004-2007, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004-2007, 2009-2024 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
diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c
index c71629cbc57..8dd26f73c03 100644
--- a/lib/gettimeofday.c
+++ b/lib/gettimeofday.c
@@ -1,6 +1,6 @@
 /* Provide gettimeofday for systems that don't have it or for which it's 
broken.
 
-   Copyright (C) 2001-2003, 2005-2007, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2003, 2005-2007, 2009-2024 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
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 3b33f39f73b..e10aab5fc8d 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -1,5 +1,5 @@
 ## DO NOT EDIT! GENERATED AUTOMATICALLY!
-# Copyright (C) 2002-2023 Free Software Foundation, Inc.
+# Copyright (C) 2002-2024 Free Software Foundation, Inc.
 #
 # 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
@@ -34,6 +34,7 @@
 #  --no-libtool \
 #  --macro-prefix=gl \
 #  --no-vc-files \
+#  --avoid=access \
 #  --avoid=btowc \
 #  --avoid=chmod \
 #  --avoid=close \
@@ -563,6 +564,7 @@ GL_GNULIB_PUTS = @GL_GNULIB_PUTS@
 GL_GNULIB_PWRITE = @GL_GNULIB_PWRITE@
 GL_GNULIB_QSORT_R = @GL_GNULIB_QSORT_R@
 GL_GNULIB_RAISE = @GL_GNULIB_RAISE@
+GL_GNULIB_RAND = @GL_GNULIB_RAND@
 GL_GNULIB_RANDOM = @GL_GNULIB_RANDOM@
 GL_GNULIB_RANDOM_R = @GL_GNULIB_RANDOM_R@
 GL_GNULIB_RAWMEMCHR = @GL_GNULIB_RAWMEMCHR@
@@ -1123,6 +1125,7 @@ REPLACE_EXECVE = @REPLACE_EXECVE@
 REPLACE_EXECVP = @REPLACE_EXECVP@
 REPLACE_EXECVPE = @REPLACE_EXECVPE@
 REPLACE_FACCESSAT = @REPLACE_FACCESSAT@
+REPLACE_FCHDIR = @REPLACE_FCHDIR@
 REPLACE_FCHMODAT = @REPLACE_FCHMODAT@
 REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@
 REPLACE_FCLOSE = @REPLACE_FCLOSE@
@@ -1182,6 +1185,7 @@ REPLACE_MB_CUR_MAX = @REPLACE_MB_CUR_MAX@
 REPLACE_MEMCHR = @REPLACE_MEMCHR@
 REPLACE_MEMMEM = @REPLACE_MEMMEM@
 REPLACE_MEMPCPY = @REPLACE_MEMPCPY@
+REPLACE_MEMSET_EXPLICIT = @REPLACE_MEMSET_EXPLICIT@
 REPLACE_MKDIR = @REPLACE_MKDIR@
 REPLACE_MKFIFO = @REPLACE_MKFIFO@
 REPLACE_MKFIFOAT = @REPLACE_MKFIFOAT@
@@ -1212,6 +1216,7 @@ REPLACE_PUTENV = @REPLACE_PUTENV@
 REPLACE_PWRITE = @REPLACE_PWRITE@
 REPLACE_QSORT_R = @REPLACE_QSORT_R@
 REPLACE_RAISE = @REPLACE_RAISE@
+REPLACE_RAND = @REPLACE_RAND@
 REPLACE_RANDOM = @REPLACE_RANDOM@
 REPLACE_RANDOM_R = @REPLACE_RANDOM_R@
 REPLACE_READ = @REPLACE_READ@
@@ -1261,11 +1266,13 @@ REPLACE_STRTOUL = @REPLACE_STRTOUL@
 REPLACE_STRTOULL = @REPLACE_STRTOULL@
 REPLACE_STRTOUMAX = @REPLACE_STRTOUMAX@
 REPLACE_STRUCT_TIMEVAL = @REPLACE_STRUCT_TIMEVAL@
+REPLACE_STRVERSCMP = @REPLACE_STRVERSCMP@
 REPLACE_SYMLINK = @REPLACE_SYMLINK@
 REPLACE_SYMLINKAT = @REPLACE_SYMLINKAT@
 REPLACE_TIME = @REPLACE_TIME@
 REPLACE_TIMEGM = @REPLACE_TIMEGM@
 REPLACE_TIMESPEC_GET = @REPLACE_TIMESPEC_GET@
+REPLACE_TIMESPEC_GETRES = @REPLACE_TIMESPEC_GETRES@
 REPLACE_TMPFILE = @REPLACE_TMPFILE@
 REPLACE_TRUNCATE = @REPLACE_TRUNCATE@
 REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@
@@ -3326,6 +3333,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) \
              -e 's/@''GNULIB_PTSNAME_R''@/$(GL_GNULIB_PTSNAME_R)/g' \
              -e 's/@''GNULIB_PUTENV''@/$(GL_GNULIB_PUTENV)/g' \
              -e 's/@''GNULIB_QSORT_R''@/$(GL_GNULIB_QSORT_R)/g' \
+             -e 's/@''GNULIB_RAND''@/$(GL_GNULIB_RAND)/g' \
              -e 's/@''GNULIB_RANDOM''@/$(GL_GNULIB_RANDOM)/g' \
              -e 's/@''GNULIB_RANDOM_R''@/$(GL_GNULIB_RANDOM_R)/g' \
              -e 's/@''GNULIB_REALLOC_GNU''@/$(GL_GNULIB_REALLOC_GNU)/g' \
@@ -3423,6 +3431,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) \
              -e 's|@''REPLACE_PTSNAME_R''@|$(REPLACE_PTSNAME_R)|g' \
              -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \
              -e 's|@''REPLACE_QSORT_R''@|$(REPLACE_QSORT_R)|g' \
+             -e 's|@''REPLACE_RAND''@|$(REPLACE_RAND)|g' \
              -e 's|@''REPLACE_RANDOM''@|$(REPLACE_RANDOM)|g' \
              -e 's|@''REPLACE_RANDOM_R''@|$(REPLACE_RANDOM_R)|g' \
              -e 
's|@''REPLACE_REALLOC_FOR_REALLOC_GNU''@|$(REPLACE_REALLOC_FOR_REALLOC_GNU)|g' \
@@ -3553,6 +3562,7 @@ string.h: string.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's|@''REPLACE_MEMCHR''@|$(REPLACE_MEMCHR)|g' \
              -e 's|@''REPLACE_MEMMEM''@|$(REPLACE_MEMMEM)|g' \
              -e 's|@''REPLACE_MEMPCPY''@|$(REPLACE_MEMPCPY)|g' \
+             -e 's|@''REPLACE_MEMSET_EXPLICIT''@|$(REPLACE_MEMSET_EXPLICIT)|g' 
\
              -e 's|@''REPLACE_FREE''@|$(REPLACE_FREE)|g' \
              -e 's|@''REPLACE_STPCPY''@|$(REPLACE_STPCPY)|g' \
              -e 's|@''REPLACE_STPNCPY''@|$(REPLACE_STPNCPY)|g' \
@@ -3568,6 +3578,7 @@ string.h: string.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's|@''REPLACE_STRERROR_R''@|$(REPLACE_STRERROR_R)|g' \
              -e 's|@''REPLACE_STRERRORNAME_NP''@|$(REPLACE_STRERRORNAME_NP)|g' 
\
              -e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \
+             -e 's|@''REPLACE_STRVERSCMP''@|$(REPLACE_STRVERSCMP)|g' \
              -e 's|@''UNDEFINE_STRTOK_R''@|$(UNDEFINE_STRTOK_R)|g' \
              -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
              -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
@@ -3884,6 +3895,7 @@ time.h: time.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H) $(
              -e 's|@''REPLACE_TIME''@|$(REPLACE_TIME)|g' \
              -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \
              -e 's|@''REPLACE_TIMESPEC_GET''@|$(REPLACE_TIMESPEC_GET)|g' \
+             -e 's|@''REPLACE_TIMESPEC_GETRES''@|$(REPLACE_TIMESPEC_GETRES)|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'
 \
@@ -4141,6 +4153,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's|@''REPLACE_EXECVP''@|$(REPLACE_EXECVP)|g' \
              -e 's|@''REPLACE_EXECVPE''@|$(REPLACE_EXECVPE)|g' \
              -e 's|@''REPLACE_FACCESSAT''@|$(REPLACE_FACCESSAT)|g' \
+             -e 's|@''REPLACE_FCHDIR''@|$(REPLACE_FCHDIR)|g' \
              -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \
              -e 's|@''REPLACE_FDATASYNC''@|$(REPLACE_FDATASYNC)|g' \
              -e 's|@''REPLACE_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \
diff --git a/lib/group-member.c b/lib/group-member.c
index 96a09f94a8f..43b49831003 100644
--- a/lib/group-member.c
+++ b/lib/group-member.c
@@ -1,6 +1,6 @@
 /* group-member.c -- determine whether group id is in calling user's group list
 
-   Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2023 Free Software
+   Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2024 Free Software
    Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/idx.h b/lib/idx.h
index 23020b7ec0c..f9ce0acd57d 100644
--- a/lib/idx.h
+++ b/lib/idx.h
@@ -1,5 +1,5 @@
 /* A type for indices and sizes.
-   Copyright (C) 2020-2023 Free Software Foundation, Inc.
+   Copyright (C) 2020-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/ieee754.in.h b/lib/ieee754.in.h
index 8de4c32be5e..805048ca9fc 100644
--- a/lib/ieee754.in.h
+++ b/lib/ieee754.in.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/ignore-value.h b/lib/ignore-value.h
index f0b569af4a7..de4a240cef4 100644
--- a/lib/ignore-value.h
+++ b/lib/ignore-value.h
@@ -1,6 +1,6 @@
 /* ignore a function return without a compiler warning.  -*- coding: utf-8 -*-
 
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 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
diff --git a/lib/intprops-internal.h b/lib/intprops-internal.h
index 0467a9ca8f2..c8a87d2bb27 100644
--- a/lib/intprops-internal.h
+++ b/lib/intprops-internal.h
@@ -1,6 +1,6 @@
 /* intprops-internal.h -- properties of integer types not visible to users
 
-   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published
@@ -20,6 +20,11 @@
 
 #include <limits.h>
 
+/* Pacify GCC 13.2 in some calls to _GL_EXPR_SIGNED.  */
+#if defined __GNUC__ && 4 < __GNUC__ + (3 <= __GNUC_MINOR__)
+# pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
+
 /* Return a value with the common real type of E and V and the value of V.
    Do not evaluate E.  */
 #define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))
diff --git a/lib/intprops.h b/lib/intprops.h
index 44b5e60fb9a..43734f3440a 100644
--- a/lib/intprops.h
+++ b/lib/intprops.h
@@ -1,6 +1,6 @@
 /* intprops.h -- properties of integer types
 
-   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published
diff --git a/lib/inttypes.in.h b/lib/inttypes.in.h
index 22643876ab3..b9ab8a4b424 100644
--- a/lib/inttypes.in.h
+++ b/lib/inttypes.in.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006-2023 Free Software Foundation, Inc.
+/* Copyright (C) 2006-2024 Free Software Foundation, Inc.
    Written by Paul Eggert, Bruno Haible, Derek Price.
    This file is part of gnulib.
 
diff --git a/lib/lchmod.c b/lib/lchmod.c
index b2d1b8bfde1..8056f0b197d 100644
--- a/lib/lchmod.c
+++ b/lib/lchmod.c
@@ -1,6 +1,6 @@
 /* Implement lchmod on platforms where it does not work correctly.
 
-   Copyright 2020-2023 Free Software Foundation, Inc.
+   Copyright 2020-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/libc-config.h b/lib/libc-config.h
index 5f5ad010377..70114608fb1 100644
--- a/lib/libc-config.h
+++ b/lib/libc-config.h
@@ -1,6 +1,6 @@
 /* System definitions for code taken from the GNU C Library
 
-   Copyright 2017-2023 Free Software Foundation, Inc.
+   Copyright 2017-2024 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
diff --git a/lib/limits.in.h b/lib/limits.in.h
index e2e173eb2de..236fc58e525 100644
--- a/lib/limits.in.h
+++ b/lib/limits.in.h
@@ -1,6 +1,6 @@
 /* A GNU-like <limits.h>.
 
-   Copyright 2016-2023 Free Software Foundation, Inc.
+   Copyright 2016-2024 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
diff --git a/lib/lstat.c b/lib/lstat.c
index 00a4ce2ab87..7c09957e20d 100644
--- a/lib/lstat.c
+++ b/lib/lstat.c
@@ -1,6 +1,6 @@
 /* Work around a bug of lstat on some systems
 
-   Copyright (C) 1997-2006, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 1997-2006, 2008-2024 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
diff --git a/lib/malloc.c b/lib/malloc.c
index 3ade35cb63f..2a7867a1d1f 100644
--- a/lib/malloc.c
+++ b/lib/malloc.c
@@ -1,6 +1,6 @@
 /* malloc() function that is glibc compatible.
 
-   Copyright (C) 1997-1998, 2006-2007, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 1997-1998, 2006-2007, 2009-2024 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
diff --git a/lib/malloc/dynarray-skeleton.c b/lib/malloc/dynarray-skeleton.c
index 580c278b7c5..a95241abd2d 100644
--- a/lib/malloc/dynarray-skeleton.c
+++ b/lib/malloc/dynarray-skeleton.c
@@ -1,5 +1,5 @@
 /* Type-safe arrays which grow dynamically.
-   Copyright (C) 2017-2023 Free Software Foundation, Inc.
+   Copyright (C) 2017-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/dynarray.h b/lib/malloc/dynarray.h
index a9a3b0859c1..3163e2782b4 100644
--- a/lib/malloc/dynarray.h
+++ b/lib/malloc/dynarray.h
@@ -1,5 +1,5 @@
 /* Type-safe arrays which grow dynamically.  Shared definitions.
-   Copyright (C) 2017-2023 Free Software Foundation, Inc.
+   Copyright (C) 2017-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/dynarray_at_failure.c b/lib/malloc/dynarray_at_failure.c
index ebc9310982c..95e34e7aacd 100644
--- a/lib/malloc/dynarray_at_failure.c
+++ b/lib/malloc/dynarray_at_failure.c
@@ -1,5 +1,5 @@
 /* Report an dynamic array index out of bounds condition.
-   Copyright (C) 2017-2023 Free Software Foundation, Inc.
+   Copyright (C) 2017-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/dynarray_emplace_enlarge.c 
b/lib/malloc/dynarray_emplace_enlarge.c
index 65aabb1e4a5..7bdba1597e0 100644
--- a/lib/malloc/dynarray_emplace_enlarge.c
+++ b/lib/malloc/dynarray_emplace_enlarge.c
@@ -1,5 +1,5 @@
 /* Increase the size of a dynamic array in preparation of an emplace operation.
-   Copyright (C) 2017-2023 Free Software Foundation, Inc.
+   Copyright (C) 2017-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/dynarray_finalize.c b/lib/malloc/dynarray_finalize.c
index 673595a5fad..52764f73287 100644
--- a/lib/malloc/dynarray_finalize.c
+++ b/lib/malloc/dynarray_finalize.c
@@ -1,5 +1,5 @@
 /* Copy the dynamically-allocated area to an explicitly-sized heap allocation.
-   Copyright (C) 2017-2023 Free Software Foundation, Inc.
+   Copyright (C) 2017-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/dynarray_resize.c b/lib/malloc/dynarray_resize.c
index 014f98c330e..7323f8eeb0c 100644
--- a/lib/malloc/dynarray_resize.c
+++ b/lib/malloc/dynarray_resize.c
@@ -1,5 +1,5 @@
 /* Increase the size of a dynamic array.
-   Copyright (C) 2017-2023 Free Software Foundation, Inc.
+   Copyright (C) 2017-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/dynarray_resize_clear.c 
b/lib/malloc/dynarray_resize_clear.c
index bb23c522a14..aa17f740e57 100644
--- a/lib/malloc/dynarray_resize_clear.c
+++ b/lib/malloc/dynarray_resize_clear.c
@@ -1,5 +1,5 @@
 /* Increase the size of a dynamic array and clear the new part.
-   Copyright (C) 2017-2023 Free Software Foundation, Inc.
+   Copyright (C) 2017-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/scratch_buffer.h b/lib/malloc/scratch_buffer.h
index 33fd2b29cd5..b94f872757e 100644
--- a/lib/malloc/scratch_buffer.h
+++ b/lib/malloc/scratch_buffer.h
@@ -1,5 +1,5 @@
 /* Variable-sized buffer with on-stack default allocation.
-   Copyright (C) 2015-2023 Free Software Foundation, Inc.
+   Copyright (C) 2015-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/scratch_buffer_dupfree.c 
b/lib/malloc/scratch_buffer_dupfree.c
index 2f60fbb54e8..8a8506e1e1d 100644
--- a/lib/malloc/scratch_buffer_dupfree.c
+++ b/lib/malloc/scratch_buffer_dupfree.c
@@ -1,5 +1,5 @@
 /* Variable-sized buffer with on-stack default allocation.
-   Copyright (C) 2020-2023 Free Software Foundation, Inc.
+   Copyright (C) 2020-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/scratch_buffer_grow.c b/lib/malloc/scratch_buffer_grow.c
index a5e8f2f7230..c08275797d6 100644
--- a/lib/malloc/scratch_buffer_grow.c
+++ b/lib/malloc/scratch_buffer_grow.c
@@ -1,5 +1,5 @@
 /* Variable-sized buffer with on-stack default allocation.
-   Copyright (C) 2015-2023 Free Software Foundation, Inc.
+   Copyright (C) 2015-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/scratch_buffer_grow_preserve.c 
b/lib/malloc/scratch_buffer_grow_preserve.c
index c0b5d87b7e4..6891db86aaf 100644
--- a/lib/malloc/scratch_buffer_grow_preserve.c
+++ b/lib/malloc/scratch_buffer_grow_preserve.c
@@ -1,5 +1,5 @@
 /* Variable-sized buffer with on-stack default allocation.
-   Copyright (C) 2015-2023 Free Software Foundation, Inc.
+   Copyright (C) 2015-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/scratch_buffer_set_array_size.c 
b/lib/malloc/scratch_buffer_set_array_size.c
index 24c39350ade..0582bef7ce1 100644
--- a/lib/malloc/scratch_buffer_set_array_size.c
+++ b/lib/malloc/scratch_buffer_set_array_size.c
@@ -1,5 +1,5 @@
 /* Variable-sized buffer with on-stack default allocation.
-   Copyright (C) 2015-2023 Free Software Foundation, Inc.
+   Copyright (C) 2015-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/md5-stream.c b/lib/md5-stream.c
index ba76792cbbe..c82f18145e0 100644
--- a/lib/md5-stream.c
+++ b/lib/md5-stream.c
@@ -1,6 +1,6 @@
 /* Functions to compute MD5 message digest of files or memory blocks.
    according to the definition of MD5 in RFC 1321 from April 1992.
-   Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2023 Free Software
+   Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2024 Free Software
    Foundation, Inc.
    This file is part of the GNU C Library.
 
diff --git a/lib/md5.c b/lib/md5.c
index 4a6accf28ff..8e02f15d14d 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -1,6 +1,6 @@
 /* Functions to compute MD5 message digest of files or memory blocks.
    according to the definition of MD5 in RFC 1321 from April 1992.
-   Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2023 Free Software
+   Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2024 Free Software
    Foundation, Inc.
    This file is part of the GNU C Library.
 
diff --git a/lib/md5.h b/lib/md5.h
index 92dc6038988..2f470703f5c 100644
--- a/lib/md5.h
+++ b/lib/md5.h
@@ -1,6 +1,6 @@
 /* Declaration of functions and data types used for MD5 sum computing
    library functions.
-   Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2008-2023 Free Software
+   Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2008-2024 Free Software
    Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -32,7 +32,21 @@
 #  ifndef OPENSSL_API_COMPAT
 #   define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API.  */
 #  endif
-#  include <openssl/md5.h>
+/* If <openssl/macros.h> would give a compile-time error, don't use OpenSSL.  
*/
+#  include <openssl/opensslv.h>
+#  if OPENSSL_VERSION_MAJOR >= 3
+#   include <openssl/configuration.h>
+#   if (OPENSSL_CONFIGURED_API \
+        < (OPENSSL_API_COMPAT < 0x900000L ? OPENSSL_API_COMPAT : \
+           ((OPENSSL_API_COMPAT >> 28) & 0xF) * 10000 \
+           + ((OPENSSL_API_COMPAT >> 20) & 0xFF) * 100 \
+           + ((OPENSSL_API_COMPAT >> 12) & 0xFF)))
+#    undef HAVE_OPENSSL_MD5
+#   endif
+#  endif
+#  if HAVE_OPENSSL_MD5
+#   include <openssl/md5.h>
+#  endif
 # endif
 
 #define MD5_DIGEST_SIZE 16
@@ -49,7 +63,11 @@
 
 #ifndef __THROW
 # if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major__ >= 4)
-#  define __THROW       throw ()
+#  if __cplusplus >= 201103L
+#   define __THROW      noexcept (true)
+#  else
+#   define __THROW      throw ()
+#  endif
 # else
 #  define __THROW
 # endif
diff --git a/lib/memmem.c b/lib/memmem.c
index c0b48c1b25d..e9b8c5392b6 100644
--- a/lib/memmem.c
+++ b/lib/memmem.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2023 Free Software
+/* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2024 Free Software
    Foundation, Inc.
    This file is part of the GNU C Library.
 
diff --git a/lib/mempcpy.c b/lib/mempcpy.c
index 24a3135988f..638867782d6 100644
--- a/lib/mempcpy.c
+++ b/lib/mempcpy.c
@@ -1,5 +1,5 @@
 /* Copy memory area and return pointer after last written byte.
-   Copyright (C) 2003, 2007, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2007, 2009-2024 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
diff --git a/lib/memrchr.c b/lib/memrchr.c
index c5b1fe8b2e3..3df1f479c78 100644
--- a/lib/memrchr.c
+++ b/lib/memrchr.c
@@ -1,6 +1,6 @@
 /* memrchr -- find the last occurrence of a byte in a memory block
 
-   Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2023 Free Software
+   Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2024 Free Software
    Foundation, Inc.
 
    Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
diff --git a/lib/memset_explicit.c b/lib/memset_explicit.c
index 6d21a5e8797..cf6cc647847 100644
--- a/lib/memset_explicit.c
+++ b/lib/memset_explicit.c
@@ -1,5 +1,5 @@
 /* Erase sensitive data from memory.
-   Copyright 2022-2023 Free Software Foundation, Inc.
+   Copyright 2022-2024 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
diff --git a/lib/mini-gmp-gnulib.c b/lib/mini-gmp-gnulib.c
index b15ce0ff754..6e02d3cefb6 100644
--- a/lib/mini-gmp-gnulib.c
+++ b/lib/mini-gmp-gnulib.c
@@ -1,6 +1,6 @@
 /* Tailor mini-gmp.c for Gnulib-using applications.
 
-   Copyright 2018-2023 Free Software Foundation, Inc.
+   Copyright 2018-2024 Free Software Foundation, Inc.
 
    This file is free software.
    It is dual-licensed under "the GNU LGPLv3+ or the GNU GPLv2+".
diff --git a/lib/minmax.h b/lib/minmax.h
index 0ac40198e24..f3df58b0d70 100644
--- a/lib/minmax.h
+++ b/lib/minmax.h
@@ -1,5 +1,5 @@
 /* MIN, MAX macros.
-   Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2023 Free Software
+   Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2024 Free Software
    Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/mkostemp.c b/lib/mkostemp.c
index 5cd5b3ac583..d826627fe58 100644
--- a/lib/mkostemp.c
+++ b/lib/mkostemp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-1999, 2001, 2005-2007, 2009-2023 Free Software
+/* Copyright (C) 1998-1999, 2001, 2005-2007, 2009-2024 Free Software
    Foundation, Inc.
    This file is derived from the one in the GNU C Library.
 
diff --git a/lib/mktime-internal.h b/lib/mktime-internal.h
index 709c36bdf56..0693aaf1402 100644
--- a/lib/mktime-internal.h
+++ b/lib/mktime-internal.h
@@ -1,5 +1,5 @@
 /* Internals of mktime and related functions
-   Copyright 2016-2023 Free Software Foundation, Inc.
+   Copyright 2016-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Paul Eggert <eggert@cs.ucla.edu>.
 
diff --git a/lib/mktime.c b/lib/mktime.c
index 8e80bcdbd16..c704f415740 100644
--- a/lib/mktime.c
+++ b/lib/mktime.c
@@ -1,5 +1,5 @@
 /* Convert a 'struct tm' to a time_t value.
-   Copyright (C) 1993-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Paul Eggert <eggert@twinsun.com>.
 
diff --git a/lib/nanosleep.c b/lib/nanosleep.c
index 10974df461e..c6a76ec0eb4 100644
--- a/lib/nanosleep.c
+++ b/lib/nanosleep.c
@@ -1,6 +1,6 @@
 /* Provide a replacement for the POSIX nanosleep function.
 
-   Copyright (C) 1999-2000, 2002, 2004-2023 Free Software Foundation, Inc.
+   Copyright (C) 1999-2000, 2002, 2004-2024 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
diff --git a/lib/nproc.c b/lib/nproc.c
index e3de1873a96..92a07e82890 100644
--- a/lib/nproc.c
+++ b/lib/nproc.c
@@ -1,6 +1,6 @@
 /* Detect the number of processors.
 
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 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
diff --git a/lib/nproc.h b/lib/nproc.h
index 7b8b16d37cd..7054df5f7a3 100644
--- a/lib/nproc.h
+++ b/lib/nproc.h
@@ -1,6 +1,6 @@
 /* Detect the number of processors.
 
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 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
diff --git a/lib/nstrftime.c b/lib/nstrftime.c
index c4bef575fcd..69e4164dc0c 100644
--- a/lib/nstrftime.c
+++ b/lib/nstrftime.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/open.c b/lib/open.c
index 7ec8fdc35dc..e690c9ea779 100644
--- a/lib/open.c
+++ b/lib/open.c
@@ -1,5 +1,5 @@
 /* Open a descriptor to a file.
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 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
@@ -38,9 +38,13 @@ orig_open (const char *filename, int flags, mode_t mode)
 }
 
 /* Specification.  */
+#ifdef __osf__
 /* Write "fcntl.h" here, not <fcntl.h>, otherwise OSF/1 5.1 DTK cc eliminates
    this include because of the preliminary #include <fcntl.h> above.  */
-#include "fcntl.h"
+# include "fcntl.h"
+#else
+# include <fcntl.h>
+#endif
 
 #include "cloexec.h"
 
diff --git a/lib/openat-priv.h b/lib/openat-priv.h
index 1d31c4e83cb..7fd4beb5a73 100644
--- a/lib/openat-priv.h
+++ b/lib/openat-priv.h
@@ -1,6 +1,6 @@
 /* Internals for openat-like functions.
 
-   Copyright (C) 2005-2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2005-2006, 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/openat-proc.c b/lib/openat-proc.c
index 88f70be4f59..7ccb734f424 100644
--- a/lib/openat-proc.c
+++ b/lib/openat-proc.c
@@ -1,6 +1,6 @@
 /* Create /proc/self/fd-related names for subfiles of open directories.
 
-   Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/openat.h b/lib/openat.h
index 97f066d10f8..dc34092bb3f 100644
--- a/lib/openat.h
+++ b/lib/openat.h
@@ -1,5 +1,5 @@
 /* provide a replacement openat function
-   Copyright (C) 2004-2006, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2004-2006, 2008-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/pathmax.h b/lib/pathmax.h
index 6930283b82a..d6512c6f570 100644
--- a/lib/pathmax.h
+++ b/lib/pathmax.h
@@ -1,5 +1,5 @@
 /* Define PATH_MAX somehow.  Requires sys/types.h.
-   Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2023 Free Software
+   Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2024 Free Software
    Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/pipe2.c b/lib/pipe2.c
index 8f06575a1dd..7b476df3457 100644
--- a/lib/pipe2.c
+++ b/lib/pipe2.c
@@ -1,5 +1,5 @@
 /* Create a pipe, with specific opening flags.
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 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
diff --git a/lib/pselect.c b/lib/pselect.c
index 1b8c19130c2..54732e5cce3 100644
--- a/lib/pselect.c
+++ b/lib/pselect.c
@@ -1,6 +1,6 @@
 /* pselect - synchronous I/O multiplexing
 
-   Copyright 2011-2023 Free Software Foundation, Inc.
+   Copyright 2011-2024 Free Software Foundation, Inc.
 
    This file is part of gnulib.
 
diff --git a/lib/pthread_sigmask.c b/lib/pthread_sigmask.c
index 128107582a7..3b6e6e454ed 100644
--- a/lib/pthread_sigmask.c
+++ b/lib/pthread_sigmask.c
@@ -1,5 +1,5 @@
 /* POSIX compatible signal blocking for threads.
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 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
diff --git a/lib/qcopy-acl.c b/lib/qcopy-acl.c
index 0f4159b7fd9..dfc39cead05 100644
--- a/lib/qcopy-acl.c
+++ b/lib/qcopy-acl.c
@@ -1,6 +1,6 @@
 /* Copy access control list from one file to another.  -*- coding: utf-8 -*-
 
-   Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/rawmemchr.c b/lib/rawmemchr.c
index 45c6cd35276..013e7f8cced 100644
--- a/lib/rawmemchr.c
+++ b/lib/rawmemchr.c
@@ -1,5 +1,5 @@
 /* Searching in a string.
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 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
@@ -19,7 +19,7 @@
 /* Specification.  */
 #include <string.h>
 
-/* A function definition is only needed if HAVE_RAWMEMCHR is not defined.  */
+/* A function definition is needed only if HAVE_RAWMEMCHR is not defined.  */
 #if !HAVE_RAWMEMCHR
 
 # include <limits.h>
@@ -30,19 +30,30 @@
 void *
 rawmemchr (const void *s, int c_in)
 {
-  /* Change this typedef to experiment with performance.  */
+# ifdef __CHERI_PURE_CAPABILITY__
+  /* Most architectures let you read an aligned word,
+     even if the unsigned char array at S ends in the middle of the word.
+     However CHERI does not, so call memchr
+     with the underlying object's remaining length.
+     This cannot return NULL if S points to a C_IN-terminated array.
+     Use builtins rather than including <cheri.h> which is less stable.  */
+  return memchr (s, c_in, (__builtin_cheri_length_get (s)
+                           - __builtin_cheri_offset_get (s)));
+# else
+
+  /* You can change this typedef to experiment with performance.  */
   typedef uintptr_t longword;
-  /* If you change the "uintptr_t", you should change UINTPTR_WIDTH to match.
-     This verifies that the type does not have padding bits.  */
-  static_assert (UINTPTR_WIDTH == UCHAR_WIDTH * sizeof (longword));
+  /* Verify that the longword type lacks padding bits.  */
+  static_assert (UINTPTR_WIDTH == UCHAR_WIDTH * sizeof (uintptr_t));
 
   const unsigned char *char_ptr;
   unsigned char c = c_in;
 
   /* Handle the first few bytes by reading one byte at a time.
-     Do this until CHAR_PTR is aligned on a longword boundary.  */
+     Do this until CHAR_PTR is aligned on a natural longword boundary,
+     as using alignof (longword) might be slower.  */
   for (char_ptr = (const unsigned char *) s;
-       (uintptr_t) char_ptr % alignof (longword) != 0;
+       (uintptr_t) char_ptr % sizeof (longword) != 0;
        ++char_ptr)
     if (*char_ptr == c)
       return (void *) char_ptr;
@@ -118,6 +129,7 @@ rawmemchr (const void *s, int c_in)
   while (*char_ptr != c)
     char_ptr++;
   return (void *) char_ptr;
+# endif
 }
 
 #endif
diff --git a/lib/rawmemchr.valgrind b/lib/rawmemchr.valgrind
index f3e4cb0f655..bb201f73093 100644
--- a/lib/rawmemchr.valgrind
+++ b/lib/rawmemchr.valgrind
@@ -1,6 +1,6 @@
 # Suppress a valgrind message about use of uninitialized memory in rawmemchr().
 
-# Copyright (C) 2008-2023 Free Software Foundation, Inc.
+# Copyright (C) 2008-2024 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
diff --git a/lib/readlink.c b/lib/readlink.c
index 14bbb7f10ca..a5369fa977b 100644
--- a/lib/readlink.c
+++ b/lib/readlink.c
@@ -1,5 +1,5 @@
 /* Read the contents of a symbolic link.
-   Copyright (C) 2003-2007, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2003-2007, 2009-2024 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
diff --git a/lib/readlinkat.c b/lib/readlinkat.c
index 7738ba8bfd5..faf85401ae6 100644
--- a/lib/readlinkat.c
+++ b/lib/readlinkat.c
@@ -1,5 +1,5 @@
 /* Read a symlink relative to an open directory.
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/readutmp.h b/lib/readutmp.h
index fa30fa9a004..dcfd44dbbc9 100644
--- a/lib/readutmp.h
+++ b/lib/readutmp.h
@@ -1,6 +1,6 @@
 /* Declarations for GNU's read utmp module.
 
-   Copyright (C) 1992-2007, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 1992-2007, 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -114,21 +114,21 @@ enum { UT_HOST_SIZE = -1 };
 
      Field        Type                       Platforms
      ----------   ------                     ---------
-   ⎡ ut_user      char[]                     glibc, musl, macOS, FreeBSD, AIX, 
HP-UX, IRIX, Solaris, Cygwin
+   ⎡ ut_user      char[]                     glibc, musl, macOS, FreeBSD, AIX, 
HP-UX, IRIX, Solaris, Cygwin, Android
    ⎣ ut_name      char[]                     NetBSD, Minix
-     ut_id        char[]                     glibc, musl, macOS, FreeBSD, 
NetBSD, Minix, AIX, HP-UX, IRIX, Solaris, Cygwin
-     ut_line      char[]                     glibc, musl, macOS, FreeBSD, 
NetBSD, Minix, AIX, HP-UX, IRIX, Solaris, Cygwin
-     ut_pid       pid_t                      glibc, musl, macOS, FreeBSD, 
NetBSD, Minix, AIX, HP-UX, IRIX, Solaris, Cygwin
-     ut_type      short                      glibc, musl, macOS, FreeBSD, 
NetBSD, Minix, AIX, HP-UX, IRIX, Solaris, Cygwin
-   ⎡ ut_tv        struct                     glibc, musl, macOS, FreeBSD, 
NetBSD, Minix, AIX, HP-UX, IRIX, Solaris, Cygwin
+     ut_id        char[]                     glibc, musl, macOS, FreeBSD, 
NetBSD, Minix, AIX, HP-UX, IRIX, Solaris, Cygwin, Android
+     ut_line      char[]                     glibc, musl, macOS, FreeBSD, 
NetBSD, Minix, AIX, HP-UX, IRIX, Solaris, Cygwin, Android
+     ut_pid       pid_t                      glibc, musl, macOS, FreeBSD, 
NetBSD, Minix, AIX, HP-UX, IRIX, Solaris, Cygwin, Android
+     ut_type      short                      glibc, musl, macOS, FreeBSD, 
NetBSD, Minix, AIX, HP-UX, IRIX, Solaris, Cygwin, Android
+   ⎡ ut_tv        struct                     glibc, musl, macOS, FreeBSD, 
NetBSD, Minix, AIX, HP-UX, IRIX, Solaris, Cygwin, Android
    ⎢              { tv_sec; tv_usec; }
    ⎣ ut_time      time_t                     Cygwin
-     ut_host      char[]                     glibc, musl, macOS, FreeBSD, 
NetBSD, Minix, AIX, HP-UX, IRIX, Solaris, Cygwin
-     ut_exit      struct                     glibc, musl, NetBSD, Minix, 
HP-UX, IRIX, Solaris
+     ut_host      char[]                     glibc, musl, macOS, FreeBSD, 
NetBSD, Minix, AIX, HP-UX, IRIX, Solaris, Cygwin, Android
+     ut_exit      struct                     glibc, musl, NetBSD, Minix, 
HP-UX, IRIX, Solaris, Android
                   { e_termination; e_exit; }
-     ut_session   [long] int                 glibc, musl, NetBSD, Minix, IRIX, 
Solaris
+     ut_session   [long] int                 glibc, musl, NetBSD, Minix, IRIX, 
Solaris, Android
    ⎡ ut_addr      [long] int                 HP-UX, Cygwin
-   ⎢ ut_addr_v6   [u]int[4]                  glibc, musl
+   ⎢ ut_addr_v6   [u]int[4]                  glibc, musl, Android
    ⎣ ut_ss        struct sockaddr_storage    NetBSD, Minix
  */
 
@@ -177,6 +177,10 @@ struct utmpx32
 #  define UTMP_NAME_FUNCTION utmpxname
 # elif defined UTXDB_ACTIVE /* FreeBSD */
 #  define UTMP_NAME_FUNCTION(x) setutxdb (UTXDB_ACTIVE, x)
+# elif defined __ANDROID__ /* Android */
+/* As of Android NDK r26, the getutxent, setutxent functions are no-ops.
+   Therefore we can ignore the file name.  */
+#  define UTMP_NAME_FUNCTION(x) ((void) (x))
 # endif
 
 #elif HAVE_UTMP_H
diff --git a/lib/realloc.c b/lib/realloc.c
index 1063eb09874..0573139625e 100644
--- a/lib/realloc.c
+++ b/lib/realloc.c
@@ -1,6 +1,6 @@
 /* realloc() function that is glibc compatible.
 
-   Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2023 Free Software
+   Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2024 Free Software
    Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/regcomp.c b/lib/regcomp.c
index 1f6a131107b..696cf813f3c 100644
--- a/lib/regcomp.c
+++ b/lib/regcomp.c
@@ -1,5 +1,5 @@
 /* Extended regular expression matching and search library.
-   Copyright (C) 2002-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
 
diff --git a/lib/regex.c b/lib/regex.c
index 3beb0deb987..4b1a6ed68e3 100644
--- a/lib/regex.c
+++ b/lib/regex.c
@@ -1,5 +1,5 @@
 /* Extended regular expression matching and search library.
-   Copyright (C) 2002-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
 
@@ -26,10 +26,6 @@
 #  pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
 #  pragma GCC diagnostic ignored "-Wvla"
 # endif
-# if __GNUC_PREREQ (4, 3)
-#  pragma GCC diagnostic ignored "-Wold-style-definition"
-#  pragma GCC diagnostic ignored "-Wtype-limits"
-# endif
 #endif
 
 /* Make sure no one compiles this code with a C++ compiler.  */
diff --git a/lib/regex.h b/lib/regex.h
index 9ef0252ffff..ccf40cebc0e 100644
--- a/lib/regex.h
+++ b/lib/regex.h
@@ -1,6 +1,6 @@
 /* Definitions for data structures and routines for the regular
    expression library.
-   Copyright (C) 1985, 1989-2023 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1989-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/regex_internal.c b/lib/regex_internal.c
index 998a19b7241..8cd096ebcfb 100644
--- a/lib/regex_internal.c
+++ b/lib/regex_internal.c
@@ -1,5 +1,5 @@
 /* Extended regular expression matching and search library.
-   Copyright (C) 2002-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
 
diff --git a/lib/regex_internal.h b/lib/regex_internal.h
index 7e35a112ec2..6165cb17c70 100644
--- a/lib/regex_internal.h
+++ b/lib/regex_internal.h
@@ -1,5 +1,5 @@
 /* Extended regular expression matching and search library.
-   Copyright (C) 2002-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
 
diff --git a/lib/regexec.c b/lib/regexec.c
index f05f38ae0e0..9f065dfa020 100644
--- a/lib/regexec.c
+++ b/lib/regexec.c
@@ -1,5 +1,5 @@
 /* Extended regular expression matching and search library.
-   Copyright (C) 2002-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
 
diff --git a/lib/root-uid.h b/lib/root-uid.h
index 1905575e47b..ba50bfd4e6a 100644
--- a/lib/root-uid.h
+++ b/lib/root-uid.h
@@ -1,6 +1,6 @@
 /* The user ID that always has appropriate privileges in the POSIX sense.
 
-   Copyright 2012-2023 Free Software Foundation, Inc.
+   Copyright 2012-2024 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
diff --git a/lib/save-cwd.c b/lib/save-cwd.c
index 7c517d1c819..77835b55db6 100644
--- a/lib/save-cwd.c
+++ b/lib/save-cwd.c
@@ -1,6 +1,6 @@
 /* save-cwd.c -- Save and restore current working directory.
 
-   Copyright (C) 1995, 1997-1998, 2003-2006, 2009-2023 Free Software
+   Copyright (C) 1995, 1997-1998, 2003-2006, 2009-2024 Free Software
    Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
diff --git a/lib/save-cwd.h b/lib/save-cwd.h
index d089b0e2145..692e4b97be2 100644
--- a/lib/save-cwd.h
+++ b/lib/save-cwd.h
@@ -1,6 +1,6 @@
 /* Save and restore current working directory.
 
-   Copyright (C) 1995, 1997-1998, 2003, 2009-2023 Free Software Foundation,
+   Copyright (C) 1995, 1997-1998, 2003, 2009-2024 Free Software Foundation,
    Inc.
 
    This program is free software: you can redistribute it and/or modify
diff --git a/lib/scratch_buffer.h b/lib/scratch_buffer.h
index 4cf60d232b7..4f28203a469 100644
--- a/lib/scratch_buffer.h
+++ b/lib/scratch_buffer.h
@@ -1,5 +1,5 @@
 /* Variable-sized buffer with on-stack default allocation.
-   Copyright (C) 2017-2023 Free Software Foundation, Inc.
+   Copyright (C) 2017-2024 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
diff --git a/lib/set-permissions.c b/lib/set-permissions.c
index 1d6732cc78f..83a355faa5c 100644
--- a/lib/set-permissions.c
+++ b/lib/set-permissions.c
@@ -1,6 +1,6 @@
 /* Set permissions of a file.  -*- coding: utf-8 -*-
 
-   Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -22,6 +22,7 @@
 #include "acl.h"
 
 #include "acl-internal.h"
+#include "minmax.h"
 
 #if USE_ACL
 # if ! defined HAVE_ACL_FROM_MODE && defined HAVE_ACL_FROM_TEXT /* FreeBSD, 
IRIX, Tru64, Cygwin >= 2.5 */
diff --git a/lib/sha1.c b/lib/sha1.c
index 80f0b7a3314..24fcd0b0139 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -1,7 +1,7 @@
 /* sha1.c - Functions to compute SHA1 message digest of files or
    memory blocks according to the NIST specification FIPS-180-1.
 
-   Copyright (C) 2000-2001, 2003-2006, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2000-2001, 2003-2006, 2008-2024 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
diff --git a/lib/sha1.h b/lib/sha1.h
index 854213a9211..940163eb528 100644
--- a/lib/sha1.h
+++ b/lib/sha1.h
@@ -1,6 +1,6 @@
 /* Declarations of functions and data types used for SHA1 sum
    library functions.
-   Copyright (C) 2000-2001, 2003, 2005-2006, 2008-2023 Free Software
+   Copyright (C) 2000-2001, 2003, 2005-2006, 2008-2024 Free Software
    Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
@@ -31,7 +31,21 @@
 #  ifndef OPENSSL_API_COMPAT
 #   define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API.  */
 #  endif
-#  include <openssl/sha.h>
+/* If <openssl/macros.h> would give a compile-time error, don't use OpenSSL.  
*/
+#  include <openssl/opensslv.h>
+#  if OPENSSL_VERSION_MAJOR >= 3
+#   include <openssl/configuration.h>
+#   if (OPENSSL_CONFIGURED_API \
+        < (OPENSSL_API_COMPAT < 0x900000L ? OPENSSL_API_COMPAT : \
+           ((OPENSSL_API_COMPAT >> 28) & 0xF) * 10000 \
+           + ((OPENSSL_API_COMPAT >> 20) & 0xFF) * 100 \
+           + ((OPENSSL_API_COMPAT >> 12) & 0xFF)))
+#    undef HAVE_OPENSSL_SHA1
+#   endif
+#  endif
+#  if HAVE_OPENSSL_SHA1
+#   include <openssl/sha.h>
+#  endif
 # endif
 
 # ifdef __cplusplus
diff --git a/lib/sha256.c b/lib/sha256.c
index e5fea02bc2e..fe7c5446daf 100644
--- a/lib/sha256.c
+++ b/lib/sha256.c
@@ -1,7 +1,7 @@
 /* sha256.c - Functions to compute SHA256 and SHA224 message digest of files or
    memory blocks according to the NIST specification FIPS-180-2.
 
-   Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2005-2006, 2008-2024 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
diff --git a/lib/sha256.h b/lib/sha256.h
index 938b1067062..a9d7abb8a2c 100644
--- a/lib/sha256.h
+++ b/lib/sha256.h
@@ -1,6 +1,6 @@
 /* Declarations of functions and data types used for SHA256 and SHA224 sum
    library functions.
-   Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2005-2006, 2008-2024 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
@@ -30,7 +30,21 @@
 #  ifndef OPENSSL_API_COMPAT
 #   define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API.  */
 #  endif
-#  include <openssl/sha.h>
+/* If <openssl/macros.h> would give a compile-time error, don't use OpenSSL.  
*/
+#  include <openssl/opensslv.h>
+#  if OPENSSL_VERSION_MAJOR >= 3
+#   include <openssl/configuration.h>
+#   if (OPENSSL_CONFIGURED_API \
+        < (OPENSSL_API_COMPAT < 0x900000L ? OPENSSL_API_COMPAT : \
+           ((OPENSSL_API_COMPAT >> 28) & 0xF) * 10000 \
+           + ((OPENSSL_API_COMPAT >> 20) & 0xFF) * 100 \
+           + ((OPENSSL_API_COMPAT >> 12) & 0xFF)))
+#    undef HAVE_OPENSSL_SHA256
+#   endif
+#  endif
+#  if HAVE_OPENSSL_SHA256
+#   include <openssl/sha.h>
+#  endif
 # endif
 
 # ifdef __cplusplus
diff --git a/lib/sha512.c b/lib/sha512.c
index 8ca7fa319f5..9eb036fb327 100644
--- a/lib/sha512.c
+++ b/lib/sha512.c
@@ -1,7 +1,7 @@
 /* sha512.c - Functions to compute SHA512 and SHA384 message digest of files or
    memory blocks according to the NIST specification FIPS-180-2.
 
-   Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2005-2006, 2008-2024 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
diff --git a/lib/sha512.h b/lib/sha512.h
index f3465bc8a68..f6bac85488e 100644
--- a/lib/sha512.h
+++ b/lib/sha512.h
@@ -1,6 +1,6 @@
 /* Declarations of functions and data types used for SHA512 and SHA384 sum
    library functions.
-   Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2005-2006, 2008-2024 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
@@ -30,7 +30,21 @@
 #  ifndef OPENSSL_API_COMPAT
 #   define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API.  */
 #  endif
-#  include <openssl/sha.h>
+/* If <openssl/macros.h> would give a compile-time error, don't use OpenSSL.  
*/
+#  include <openssl/opensslv.h>
+#  if OPENSSL_VERSION_MAJOR >= 3
+#   include <openssl/configuration.h>
+#   if (OPENSSL_CONFIGURED_API \
+        < (OPENSSL_API_COMPAT < 0x900000L ? OPENSSL_API_COMPAT : \
+           ((OPENSSL_API_COMPAT >> 28) & 0xF) * 10000 \
+           + ((OPENSSL_API_COMPAT >> 20) & 0xFF) * 100 \
+           + ((OPENSSL_API_COMPAT >> 12) & 0xFF)))
+#    undef HAVE_OPENSSL_SHA512
+#   endif
+#  endif
+#  if HAVE_OPENSSL_SHA512
+#   include <openssl/sha.h>
+#  endif
 # endif
 
 # ifdef __cplusplus
diff --git a/lib/sig2str.c b/lib/sig2str.c
index c5219caaaed..c6b91e38498 100644
--- a/lib/sig2str.c
+++ b/lib/sig2str.c
@@ -1,6 +1,6 @@
 /* sig2str.c -- convert between signal names and numbers
 
-   Copyright (C) 2002, 2004, 2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004, 2006, 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/sig2str.h b/lib/sig2str.h
index 1e5253658e7..391da4b1d1c 100644
--- a/lib/sig2str.h
+++ b/lib/sig2str.h
@@ -1,6 +1,6 @@
 /* sig2str.h -- convert between signal names and numbers
 
-   Copyright (C) 2002, 2005, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2005, 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/sigdescr_np.c b/lib/sigdescr_np.c
index fc8a4ad47a2..fb5401522f4 100644
--- a/lib/sigdescr_np.c
+++ b/lib/sigdescr_np.c
@@ -1,5 +1,5 @@
 /* English descriptions of signals.
-   Copyright (C) 2020-2023 Free Software Foundation, Inc.
+   Copyright (C) 2020-2024 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
diff --git a/lib/signal.in.h b/lib/signal.in.h
index 418d59c582d..107226e3dcf 100644
--- a/lib/signal.in.h
+++ b/lib/signal.in.h
@@ -1,6 +1,6 @@
 /* A GNU-like <signal.h>.
 
-   Copyright (C) 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006-2024 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
diff --git a/lib/stat-time.c b/lib/stat-time.c
index bc282232ab3..1ab01f532cd 100644
--- a/lib/stat-time.c
+++ b/lib/stat-time.c
@@ -1,6 +1,6 @@
 /* stat-related time functions.
 
-   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Copyright (C) 2012-2024 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
diff --git a/lib/stat-time.h b/lib/stat-time.h
index 75eb27e549d..3cd8478f310 100644
--- a/lib/stat-time.h
+++ b/lib/stat-time.h
@@ -1,6 +1,6 @@
 /* stat-related time functions.
 
-   Copyright (C) 2005, 2007, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2007, 2009-2024 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
@@ -52,11 +52,13 @@ extern "C" {
 #if _GL_WINDOWS_STAT_TIMESPEC || defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
 # if _GL_WINDOWS_STAT_TIMESPEC || defined 
TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC
 #  define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim)
+#  define STAT_TIMESPEC_OFFSETOF(st_xtim) offsetof (struct stat, st_xtim)
 # else
 #  define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec)
 # endif
 #elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
 # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec)
+# define STAT_TIMESPEC_OFFSETOF(st_xtim) offsetof (struct stat, st_xtim##espec)
 #elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC
 # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec)
 #elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC
@@ -194,20 +196,21 @@ get_stat_birthtime (_GL_UNUSED struct stat const *st)
 }
 
 /* If a stat-like function returned RESULT, normalize the timestamps
-   in *ST, in case this platform suffers from the Solaris 11 bug where
+   in *ST, if this platform suffers from a macOS and Solaris bug where
    tv_nsec might be negative.  Return the adjusted RESULT, setting
    errno to EOVERFLOW if normalization overflowed.  This function
    is intended to be private to this .h file.  */
 _GL_STAT_TIME_INLINE int
 stat_time_normalize (int result, _GL_UNUSED struct stat *st)
 {
-#if defined __sun && defined STAT_TIMESPEC
+#if (((defined __APPLE__ && defined __MACH__) || defined __sun) \
+     && defined STAT_TIMESPEC_OFFSETOF)
   if (result == 0)
     {
       long int timespec_hz = 1000000000;
-      short int const ts_off[] = { offsetof (struct stat, st_atim),
-                                   offsetof (struct stat, st_mtim),
-                                   offsetof (struct stat, st_ctim) };
+      short int const ts_off[] = { STAT_TIMESPEC_OFFSETOF (st_atim),
+                                   STAT_TIMESPEC_OFFSETOF (st_mtim),
+                                   STAT_TIMESPEC_OFFSETOF (st_ctim) };
       int i;
       for (i = 0; i < sizeof ts_off / sizeof *ts_off; i++)
         {
diff --git a/lib/stdalign.in.h b/lib/stdalign.in.h
index b616c100fdc..ff9e5ec6d67 100644
--- a/lib/stdalign.in.h
+++ b/lib/stdalign.in.h
@@ -1,6 +1,6 @@
 /* A substitute for ISO C11 <stdalign.h>.
 
-   Copyright 2011-2023 Free Software Foundation, Inc.
+   Copyright 2011-2024 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
diff --git a/lib/stdckdint.in.h b/lib/stdckdint.in.h
index 71bab5f0c9e..91848806d8d 100644
--- a/lib/stdckdint.in.h
+++ b/lib/stdckdint.in.h
@@ -1,6 +1,6 @@
 /* stdckdint.h -- checked integer arithmetic
 
-   Copyright 2022-2023 Free Software Foundation, Inc.
+   Copyright 2022-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published
diff --git a/lib/stddef.in.h b/lib/stddef.in.h
index 431e819b8bf..fa8998d9b72 100644
--- a/lib/stddef.in.h
+++ b/lib/stddef.in.h
@@ -1,6 +1,6 @@
 /* A substitute for POSIX 2008 <stddef.h>, for platforms that have issues.
 
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 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
@@ -58,7 +58,7 @@
 
 /* On AIX 7.2, with xlc in 64-bit mode, <stddef.h> defines max_align_t to a
    type with alignment 4, but 'long' has alignment 8.  */
-#  if defined _AIX && defined __LP64__
+#  if defined _AIX && defined __LP64__ && !@HAVE_MAX_ALIGN_T@
 #   if !GNULIB_defined_max_align_t
 #    ifdef _MAX_ALIGN_T
 /* /usr/include/stddef.h has already defined max_align_t.  Override it.  */
@@ -101,11 +101,33 @@ typedef long max_align_t;
 #  ifndef _@GUARD_PREFIX@_STDDEF_H
 #   define _@GUARD_PREFIX@_STDDEF_H
 
-/* This file uses _Noreturn.  */
+/* This file uses _Noreturn, _GL_ATTRIBUTE_NOTHROW.  */
 #if !_GL_CONFIG_H_INCLUDED
  #error "Please include config.h first."
 #endif
 
+/* _GL_ATTRIBUTE_NOTHROW declares that the function does not throw exceptions.
+ */
+#ifndef _GL_ATTRIBUTE_NOTHROW
+# if defined __cplusplus
+#  if (__GNUC__ + (__GNUC_MINOR__ >= 8) > 2) || __clang_major >= 4
+#   if __cplusplus >= 201103L
+#    define _GL_ATTRIBUTE_NOTHROW noexcept (true)
+#   else
+#    define _GL_ATTRIBUTE_NOTHROW throw ()
+#   endif
+#  else
+#   define _GL_ATTRIBUTE_NOTHROW
+#  endif
+# else
+#  if (__GNUC__ + (__GNUC_MINOR__ >= 3) > 3) || defined __clang__
+#   define _GL_ATTRIBUTE_NOTHROW __attribute__ ((__nothrow__))
+#  else
+#   define _GL_ATTRIBUTE_NOTHROW
+#  endif
+# endif
+#endif
+
 /* Some platforms lack wchar_t.  */
 #if !@HAVE_WCHAR_T@
 # define wchar_t int
@@ -178,7 +200,7 @@ extern
 _Noreturn
 void abort (void)
 #  if defined __cplusplus && (__GLIBC__ >= 2)
-throw ()
+_GL_ATTRIBUTE_NOTHROW
 #  endif
 ;
 #  define unreachable() abort ()
diff --git a/lib/stdint.in.h b/lib/stdint.in.h
index 5ddc644b8ee..fea7483b9cc 100644
--- a/lib/stdint.in.h
+++ b/lib/stdint.in.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2002, 2004-2023 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2002, 2004-2024 Free Software Foundation, Inc.
    Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood.
    This file is part of gnulib.
 
@@ -306,6 +306,8 @@ typedef gl_uint_fast32_t gl_uint_fast16_t;
    uintptr_t to avoid conflicting declarations of system functions like
    _findclose in <io.h>.  */
 # if !((defined __KLIBC__ && defined _INTPTR_T_DECLARED) \
+       || (defined __INTPTR_WIDTH__ \
+           && __INTPTR_WIDTH__ != (defined _WIN64 ? LLONG_WIDTH : LONG_WIDTH)) 
\
        || defined __MINGW32__)
 #  undef intptr_t
 #  undef uintptr_t
diff --git a/lib/stdio-impl.h b/lib/stdio-impl.h
index 46608bed198..63ebf7c64b7 100644
--- a/lib/stdio-impl.h
+++ b/lib/stdio-impl.h
@@ -1,5 +1,5 @@
 /* Implementation details of FILE streams.
-   Copyright (C) 2007-2008, 2010-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2008, 2010-2024 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
diff --git a/lib/stdio.in.h b/lib/stdio.in.h
index 6be12c0525d..4947307e578 100644
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -1,6 +1,6 @@
 /* A GNU-like <stdio.h>.
 
-   Copyright (C) 2004, 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2007-2024 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
@@ -38,8 +38,14 @@
 
 /* Suppress macOS deprecation warnings for sprintf and vsprintf.  */
 #if (defined __APPLE__ && defined __MACH__) && !defined _POSIX_C_SOURCE
-# define _POSIX_C_SOURCE 200809L
-# define _GL_DEFINED__POSIX_C_SOURCE
+# ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
+#  include <AvailabilityMacros.h>
+# endif
+# if (defined MAC_OS_X_VERSION_MIN_REQUIRED \
+      && 130000 <= MAC_OS_X_VERSION_MIN_REQUIRED)
+#  define _POSIX_C_SOURCE 200809L
+#  define _GL_DEFINED__POSIX_C_SOURCE
+# endif
 #endif
 
 #define _GL_ALREADY_INCLUDING_STDIO_H
@@ -58,7 +64,8 @@
 #define _@GUARD_PREFIX@_STDIO_H
 
 /* This file uses _GL_ATTRIBUTE_DEALLOC, _GL_ATTRIBUTE_FORMAT,
-   _GL_ATTRIBUTE_MALLOC, GNULIB_POSIXCHECK, HAVE_RAW_DECL_*.  */
+   _GL_ATTRIBUTE_MALLOC, _GL_ATTRIBUTE_NOTHROW, GNULIB_POSIXCHECK,
+   HAVE_RAW_DECL_*.  */
 #if !_GL_CONFIG_H_INCLUDED
  #error "Please include config.h first."
 #endif
@@ -143,6 +150,28 @@
 # endif
 #endif
 
+/* _GL_ATTRIBUTE_NOTHROW declares that the function does not throw exceptions.
+ */
+#ifndef _GL_ATTRIBUTE_NOTHROW
+# if defined __cplusplus
+#  if (__GNUC__ + (__GNUC_MINOR__ >= 8) > 2) || __clang_major >= 4
+#   if __cplusplus >= 201103L
+#    define _GL_ATTRIBUTE_NOTHROW noexcept (true)
+#   else
+#    define _GL_ATTRIBUTE_NOTHROW throw ()
+#   endif
+#  else
+#   define _GL_ATTRIBUTE_NOTHROW
+#  endif
+# else
+#  if (__GNUC__ + (__GNUC_MINOR__ >= 3) > 3) || defined __clang__
+#   define _GL_ATTRIBUTE_NOTHROW __attribute__ ((__nothrow__))
+#  else
+#   define _GL_ATTRIBUTE_NOTHROW
+#  endif
+# endif
+#endif
+
 /* An __attribute__ __format__ specifier for a function that takes a format
    string and arguments, where the format string directives are the ones
    standardized by ISO C99 and POSIX.
@@ -344,10 +373,18 @@ _GL_CXXALIAS_MDA (fdopen, FILE *, (int fd, const char 
*mode));
 # else
 #  if __GNUC__ >= 11
 /* For -Wmismatched-dealloc: Associate fdopen with fclose or rpl_fclose.  */
+#   if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
 _GL_FUNCDECL_SYS (fdopen, FILE *,
                   (int fd, const char *mode)
+                  _GL_ATTRIBUTE_NOTHROW
                   _GL_ARG_NONNULL ((2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1)
                   _GL_ATTRIBUTE_MALLOC);
+#   else
+_GL_FUNCDECL_SYS (fdopen, FILE *,
+                  (int fd, const char *mode)
+                  _GL_ARG_NONNULL ((2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1)
+                  _GL_ATTRIBUTE_MALLOC);
+#   endif
 #  endif
 _GL_CXXALIAS_SYS (fdopen, FILE *, (int fd, const char *mode));
 # endif
@@ -355,10 +392,18 @@ _GL_CXXALIASWARN (fdopen);
 #else
 # if @GNULIB_FCLOSE@ && __GNUC__ >= 11 && !defined fdopen
 /* For -Wmismatched-dealloc: Associate fdopen with fclose or rpl_fclose.  */
+#  if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
 _GL_FUNCDECL_SYS (fdopen, FILE *,
                   (int fd, const char *mode)
+                  _GL_ATTRIBUTE_NOTHROW
                   _GL_ARG_NONNULL ((2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1)
                   _GL_ATTRIBUTE_MALLOC);
+#  else
+_GL_FUNCDECL_SYS (fdopen, FILE *,
+                  (int fd, const char *mode)
+                  _GL_ARG_NONNULL ((2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1)
+                  _GL_ATTRIBUTE_MALLOC);
+#  endif
 # endif
 # if defined GNULIB_POSIXCHECK
 #  undef fdopen
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index 1479a2b2871..b901d175aeb 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -1,6 +1,6 @@
 /* A GNU-like <stdlib.h>.
 
-   Copyright (C) 1995, 2001-2004, 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 1995, 2001-2004, 2006-2024 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
@@ -38,7 +38,8 @@
 #define _@GUARD_PREFIX@_STDLIB_H
 
 /* This file uses _Noreturn, _GL_ATTRIBUTE_DEALLOC, _GL_ATTRIBUTE_MALLOC,
-   _GL_ATTRIBUTE_PURE, GNULIB_POSIXCHECK, HAVE_RAW_DECL_*.  */
+   _GL_ATTRIBUTE_NOTHROW, _GL_ATTRIBUTE_PURE, GNULIB_POSIXCHECK,
+   HAVE_RAW_DECL_*.  */
 #if !_GL_CONFIG_H_INCLUDED
  #error "Please include config.h first."
 #endif
@@ -132,6 +133,28 @@ struct random_data
 # endif
 #endif
 
+/* _GL_ATTRIBUTE_NOTHROW declares that the function does not throw exceptions.
+ */
+#ifndef _GL_ATTRIBUTE_NOTHROW
+# if defined __cplusplus
+#  if (__GNUC__ + (__GNUC_MINOR__ >= 8) > 2) || __clang_major >= 4
+#   if __cplusplus >= 201103L
+#    define _GL_ATTRIBUTE_NOTHROW noexcept (true)
+#   else
+#    define _GL_ATTRIBUTE_NOTHROW throw ()
+#   endif
+#  else
+#   define _GL_ATTRIBUTE_NOTHROW
+#  endif
+# else
+#  if (__GNUC__ + (__GNUC_MINOR__ >= 3) > 3) || defined __clang__
+#   define _GL_ATTRIBUTE_NOTHROW __attribute__ ((__nothrow__))
+#  else
+#   define _GL_ATTRIBUTE_NOTHROW
+#  endif
+# endif
+#endif
+
 /* The __attribute__ feature is available in gcc versions 2.5 and later.
    The attribute __pure__ was added in gcc 2.96.  */
 #ifndef _GL_ATTRIBUTE_PURE
@@ -200,7 +223,7 @@ _GL_WARN_ON_USE (_Exit, "_Exit is unportable - "
 #   define free rpl_free
 #  endif
 #  if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
-_GL_FUNCDECL_RPL (free, void, (void *ptr) throw ());
+_GL_FUNCDECL_RPL (free, void, (void *ptr) _GL_ATTRIBUTE_NOTHROW);
 #  else
 _GL_FUNCDECL_RPL (free, void, (void *ptr));
 #  endif
@@ -234,9 +257,16 @@ _GL_CXXALIAS_RPL (aligned_alloc, void *, (size_t 
alignment, size_t size));
 #  if @HAVE_ALIGNED_ALLOC@
 #   if __GNUC__ >= 11
 /* For -Wmismatched-dealloc: Associate aligned_alloc with free or rpl_free.  */
+#    if __GLIBC__ + (__GLIBC_MINOR__ >= 16) > 2
+_GL_FUNCDECL_SYS (aligned_alloc, void *,
+                  (size_t alignment, size_t size)
+                  _GL_ATTRIBUTE_NOTHROW
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#    else
 _GL_FUNCDECL_SYS (aligned_alloc, void *,
                   (size_t alignment, size_t size)
                   _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#    endif
 #   endif
 _GL_CXXALIAS_SYS (aligned_alloc, void *, (size_t alignment, size_t size));
 #  endif
@@ -247,9 +277,16 @@ _GL_CXXALIASWARN (aligned_alloc);
 #else
 # if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined aligned_alloc
 /* For -Wmismatched-dealloc: Associate aligned_alloc with free or rpl_free.  */
+#  if __GLIBC__ + (__GLIBC_MINOR__ >= 16) > 2
+_GL_FUNCDECL_SYS (aligned_alloc, void *,
+                  (size_t alignment, size_t size)
+                  _GL_ATTRIBUTE_NOTHROW
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#  else
 _GL_FUNCDECL_SYS (aligned_alloc, void *,
                   (size_t alignment, size_t size)
                   _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#  endif
 # endif
 # if defined GNULIB_POSIXCHECK
 #  undef aligned_alloc
@@ -292,9 +329,16 @@ _GL_CXXALIAS_RPL (calloc, void *, (size_t nmemb, size_t 
size));
 # else
 #  if __GNUC__ >= 11
 /* For -Wmismatched-dealloc: Associate calloc with free or rpl_free.  */
+#   if __GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2
+_GL_FUNCDECL_SYS (calloc, void *,
+                  (size_t nmemb, size_t size)
+                  _GL_ATTRIBUTE_NOTHROW
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#   else
 _GL_FUNCDECL_SYS (calloc, void *,
                   (size_t nmemb, size_t size)
                   _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#   endif
 #  endif
 _GL_CXXALIAS_SYS (calloc, void *, (size_t nmemb, size_t size));
 # endif
@@ -304,9 +348,16 @@ _GL_CXXALIASWARN (calloc);
 #else
 # if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined calloc
 /* For -Wmismatched-dealloc: Associate calloc with free or rpl_free.  */
+#  if __GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2
 _GL_FUNCDECL_SYS (calloc, void *,
                   (size_t nmemb, size_t size)
+                  _GL_ATTRIBUTE_NOTHROW
                   _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#  else
+_GL_FUNCDECL_SYS (calloc, void *,
+                  (size_t nmemb, size_t size)
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#  endif
 # endif
 # if defined GNULIB_POSIXCHECK
 #  undef calloc
@@ -328,10 +379,18 @@ _GL_FUNCDECL_RPL (canonicalize_file_name, char *,
 _GL_CXXALIAS_RPL (canonicalize_file_name, char *, (const char *name));
 # else
 #  if !@HAVE_CANONICALIZE_FILE_NAME@ || __GNUC__ >= 11
+#   if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
+_GL_FUNCDECL_SYS (canonicalize_file_name, char *,
+                  (const char *name)
+                  _GL_ATTRIBUTE_NOTHROW
+                  _GL_ARG_NONNULL ((1))
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#   else
 _GL_FUNCDECL_SYS (canonicalize_file_name, char *,
                   (const char *name)
                   _GL_ARG_NONNULL ((1))
                   _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#   endif
 #  endif
 _GL_CXXALIAS_SYS (canonicalize_file_name, char *, (const char *name));
 # endif
@@ -344,10 +403,18 @@ _GL_CXXALIASWARN (canonicalize_file_name);
 # if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined canonicalize_file_name
 /* For -Wmismatched-dealloc: Associate canonicalize_file_name with free or
    rpl_free.  */
+#  if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
 _GL_FUNCDECL_SYS (canonicalize_file_name, char *,
                   (const char *name)
+                  _GL_ATTRIBUTE_NOTHROW
                   _GL_ARG_NONNULL ((1))
                   _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#  else
+_GL_FUNCDECL_SYS (canonicalize_file_name, char *,
+                  (const char *name)
+                  _GL_ARG_NONNULL ((1))
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#  endif
 # endif
 # if defined GNULIB_POSIXCHECK
 #  undef canonicalize_file_name
@@ -569,9 +636,16 @@ _GL_CXXALIAS_RPL (malloc, void *, (size_t size));
 # else
 #  if __GNUC__ >= 11
 /* For -Wmismatched-dealloc: Associate malloc with free or rpl_free.  */
+#   if __GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2
 _GL_FUNCDECL_SYS (malloc, void *,
                   (size_t size)
+                  _GL_ATTRIBUTE_NOTHROW
                   _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#   else
+_GL_FUNCDECL_SYS (malloc, void *,
+                  (size_t size)
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#   endif
 #  endif
 _GL_CXXALIAS_SYS (malloc, void *, (size_t size));
 # endif
@@ -581,9 +655,16 @@ _GL_CXXALIASWARN (malloc);
 #else
 # if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined malloc
 /* For -Wmismatched-dealloc: Associate malloc with free or rpl_free.  */
+#  if __GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2
+_GL_FUNCDECL_SYS (malloc, void *,
+                  (size_t size)
+                  _GL_ATTRIBUTE_NOTHROW
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#  else
 _GL_FUNCDECL_SYS (malloc, void *,
                   (size_t size)
                   _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#  endif
 # endif
 # if defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC
 #  undef malloc
@@ -966,6 +1047,10 @@ _GL_CXXALIAS_RPL (putenv, int, (char *string));
 #   define putenv _putenv
 #  endif
 _GL_CXXALIAS_MDA (putenv, int, (char *string));
+# elif defined __KLIBC__
+/* Need to cast, because on OS/2 kLIBC, the first parameter is
+                                     const char *string.  */
+_GL_CXXALIAS_SYS_CAST (putenv, int, (char *string));
 # else
 _GL_CXXALIAS_SYS (putenv, int, (char *string));
 # endif
@@ -982,6 +1067,10 @@ _GL_CXXALIASWARN (putenv);
 /* Need to cast, because on mingw, the parameter is either
    'const char *string' or 'char *string'.  */
 _GL_CXXALIAS_MDA_CAST (putenv, int, (char *string));
+# elif defined __KLIBC__
+/* Need to cast, because on OS/2 kLIBC, the first parameter is
+                                     const char *string.  */
+_GL_CXXALIAS_SYS_CAST (putenv, int, (char *string));
 # else
 _GL_CXXALIAS_SYS (putenv, int, (char *string));
 # endif
@@ -1023,7 +1112,9 @@ _GL_CXXALIAS_SYS (qsort_r, void, (void *base, size_t 
nmemb, size_t size,
                                   _gl_qsort_r_compar_fn compare,
                                   void *arg));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (qsort_r);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef qsort_r
 # if HAVE_RAW_DECL_QSORT_R
@@ -1033,11 +1124,26 @@ _GL_WARN_ON_USE (qsort_r, "qsort_r is not portable - "
 #endif
 
 
-#if @GNULIB_RANDOM_R@
-# if !@HAVE_RANDOM_R@
-#  ifndef RAND_MAX
-#   define RAND_MAX 2147483647
+#if @GNULIB_RAND@ || (@GNULIB_RANDOM_R@ && !@HAVE_RANDOM_R@)
+# ifndef RAND_MAX
+#  define RAND_MAX 2147483647
+# endif
+#endif
+
+
+#if @GNULIB_RAND@
+# if @REPLACE_RAND@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef rand
+#   define rand rpl_rand
 #  endif
+_GL_FUNCDECL_RPL (rand, int, (void));
+_GL_CXXALIAS_RPL (rand, int, (void));
+# else
+_GL_CXXALIAS_SYS (rand, int, (void));
+# endif
+# if __GLIBC__ >= 2
+_GL_CXXALIASWARN (rand);
 # endif
 #endif
 
@@ -1292,8 +1398,16 @@ _GL_CXXALIAS_RPL (realloc, void *, (void *ptr, size_t 
size));
 # else
 #  if __GNUC__ >= 11
 /* For -Wmismatched-dealloc: Associate realloc with free or rpl_free.  */
-_GL_FUNCDECL_SYS (realloc, void *, (void *ptr, size_t size)
-                                   _GL_ATTRIBUTE_DEALLOC_FREE);
+#   if __GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2
+_GL_FUNCDECL_SYS (realloc, void *,
+                  (void *ptr, size_t size)
+                  _GL_ATTRIBUTE_NOTHROW
+                  _GL_ATTRIBUTE_DEALLOC_FREE);
+#   else
+_GL_FUNCDECL_SYS (realloc, void *,
+                  (void *ptr, size_t size)
+                  _GL_ATTRIBUTE_DEALLOC_FREE);
+#   endif
 #  endif
 _GL_CXXALIAS_SYS (realloc, void *, (void *ptr, size_t size));
 # endif
@@ -1303,8 +1417,16 @@ _GL_CXXALIASWARN (realloc);
 #else
 # if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined realloc
 /* For -Wmismatched-dealloc: Associate realloc with free or rpl_free.  */
-_GL_FUNCDECL_SYS (realloc, void *, (void *ptr, size_t size)
-                                   _GL_ATTRIBUTE_DEALLOC_FREE);
+#  if __GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2
+_GL_FUNCDECL_SYS (realloc, void *,
+                  (void *ptr, size_t size)
+                  _GL_ATTRIBUTE_NOTHROW
+                  _GL_ATTRIBUTE_DEALLOC_FREE);
+#  else
+_GL_FUNCDECL_SYS (realloc, void *,
+                  (void *ptr, size_t size)
+                  _GL_ATTRIBUTE_DEALLOC_FREE);
+#  endif
 # endif
 # if defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC
 #  undef realloc
diff --git a/lib/stpcpy.c b/lib/stpcpy.c
index 73c1eb786ff..d4510054bf5 100644
--- a/lib/stpcpy.c
+++ b/lib/stpcpy.c
@@ -1,5 +1,5 @@
 /* stpcpy.c -- copy a string and return pointer to end of new string
-   Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2023 Free Software
+   Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2024 Free Software
    Foundation, Inc.
 
    NOTE: The canonical source of this file is maintained with the GNU C 
Library.
diff --git a/lib/str-two-way.h b/lib/str-two-way.h
index dfe702241c0..cf85e26817c 100644
--- a/lib/str-two-way.h
+++ b/lib/str-two-way.h
@@ -1,5 +1,5 @@
 /* Byte-wise substring search, using the Two-Way algorithm.
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Eric Blake <ebb9@byu.net>, 2008.
 
diff --git a/lib/strftime.h b/lib/strftime.h
index 88c1f73928f..d6efdb848a3 100644
--- a/lib/strftime.h
+++ b/lib/strftime.h
@@ -1,6 +1,6 @@
 /* declarations for strftime.c
 
-   Copyright (C) 2002, 2004, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004, 2008-2024 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
diff --git a/lib/string.in.h b/lib/string.in.h
index 912d0f7a306..44ec2e7ecdb 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -1,6 +1,6 @@
 /* A GNU-like <string.h>.
 
-   Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1995-1996, 2001-2024 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
@@ -45,7 +45,8 @@
 #define _@GUARD_PREFIX@_STRING_H
 
 /* This file uses _GL_ATTRIBUTE_DEALLOC, _GL_ATTRIBUTE_MALLOC,
-   _GL_ATTRIBUTE_PURE, GNULIB_POSIXCHECK, HAVE_RAW_DECL_*.  */
+   _GL_ATTRIBUTE_NOTHROW, _GL_ATTRIBUTE_PURE, GNULIB_POSIXCHECK,
+   HAVE_RAW_DECL_*.  */
 #if !_GL_CONFIG_H_INCLUDED
  #error "Please include config.h first."
 #endif
@@ -110,6 +111,28 @@
 # endif
 #endif
 
+/* _GL_ATTRIBUTE_NOTHROW declares that the function does not throw exceptions.
+ */
+#ifndef _GL_ATTRIBUTE_NOTHROW
+# if defined __cplusplus
+#  if (__GNUC__ + (__GNUC_MINOR__ >= 8) > 2) || __clang_major >= 4
+#   if __cplusplus >= 201103L
+#    define _GL_ATTRIBUTE_NOTHROW noexcept (true)
+#   else
+#    define _GL_ATTRIBUTE_NOTHROW throw ()
+#   endif
+#  else
+#   define _GL_ATTRIBUTE_NOTHROW
+#  endif
+# else
+#  if (__GNUC__ + (__GNUC_MINOR__ >= 3) > 3) || defined __clang__
+#   define _GL_ATTRIBUTE_NOTHROW __attribute__ ((__nothrow__))
+#  else
+#   define _GL_ATTRIBUTE_NOTHROW
+#  endif
+# endif
+#endif
+
 /* The __attribute__ feature is available in gcc versions 2.5 and later.
    The attribute __pure__ was added in gcc 2.96.  */
 #ifndef _GL_ATTRIBUTE_PURE
@@ -133,7 +156,7 @@
       && !(defined __cplusplus && defined GNULIB_NAMESPACE))
 /* We can't do '#define free rpl_free' here.  */
 #  if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
-_GL_EXTERN_C void rpl_free (void *) throw ();
+_GL_EXTERN_C void rpl_free (void *) _GL_ATTRIBUTE_NOTHROW;
 #  else
 _GL_EXTERN_C void rpl_free (void *);
 #  endif
@@ -148,7 +171,7 @@ _GL_EXTERN_C
      void __cdecl free (void *);
 #  else
 #   if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
-_GL_EXTERN_C void free (void *) throw ();
+_GL_EXTERN_C void free (void *) _GL_ATTRIBUTE_NOTHROW;
 #   else
 _GL_EXTERN_C void free (void *);
 #   endif
@@ -163,7 +186,7 @@ _GL_EXTERN_C
      void __cdecl free (void *);
 # else
 #  if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
-_GL_EXTERN_C void free (void *) throw ();
+_GL_EXTERN_C void free (void *) _GL_ATTRIBUTE_NOTHROW;
 #  else
 _GL_EXTERN_C void free (void *);
 #  endif
@@ -266,9 +289,12 @@ _GL_CXXALIAS_SYS_CAST2 (memchr,
 # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
      && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
          || defined __clang__)
-_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n) throw ());
+_GL_CXXALIASWARN1 (memchr, void *,
+                   (void *__s, int __c, size_t __n)
+                   _GL_ATTRIBUTE_NOTHROW);
 _GL_CXXALIASWARN1 (memchr, void const *,
-                   (void const *__s, int __c, size_t __n) throw ());
+                   (void const *__s, int __c, size_t __n)
+                   _GL_ATTRIBUTE_NOTHROW);
 # elif __GLIBC__ >= 2
 _GL_CXXALIASWARN (memchr);
 # endif
@@ -368,8 +394,12 @@ _GL_CXXALIAS_SYS_CAST2 (memrchr,
 # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
      && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
          || defined __clang__)
-_GL_CXXALIASWARN1 (memrchr, void *, (void *, int, size_t) throw ());
-_GL_CXXALIASWARN1 (memrchr, void const *, (void const *, int, size_t) throw 
());
+_GL_CXXALIASWARN1 (memrchr, void *,
+                   (void *, int, size_t)
+                   _GL_ATTRIBUTE_NOTHROW);
+_GL_CXXALIASWARN1 (memrchr, void const *,
+                   (void const *, int, size_t)
+                   _GL_ATTRIBUTE_NOTHROW);
 # elif __GLIBC__ >= 2
 _GL_CXXALIASWARN (memrchr);
 # endif
@@ -384,11 +414,21 @@ _GL_WARN_ON_USE (memrchr, "memrchr is unportable - "
 /* Overwrite a block of memory.  The compiler will not optimize
    effects away, even if the block is dead after the call.  */
 #if @GNULIB_MEMSET_EXPLICIT@
-# if ! @HAVE_MEMSET_EXPLICIT@
+# if @REPLACE_MEMSET_EXPLICIT@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef memset_explicit
+#   define memset_explicit rpl_memset_explicit
+#  endif
+_GL_FUNCDECL_RPL (memset_explicit, void *,
+                  (void *__dest, int __c, size_t __n) _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (memset_explicit, void *, (void *__dest, int __c, size_t 
__n));
+# else
+#  if !@HAVE_MEMSET_EXPLICIT@
 _GL_FUNCDECL_SYS (memset_explicit, void *,
                   (void *__dest, int __c, size_t __n) _GL_ARG_NONNULL ((1)));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (memset_explicit, void *, (void *__dest, int __c, size_t 
__n));
+# endif
 _GL_CXXALIASWARN (memset_explicit);
 #elif defined GNULIB_POSIXCHECK
 # undef memset_explicit
@@ -416,9 +456,12 @@ _GL_CXXALIAS_SYS_CAST2 (rawmemchr,
 # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
      && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
          || defined __clang__)
-_GL_CXXALIASWARN1 (rawmemchr, void *, (void *__s, int __c_in) throw ());
+_GL_CXXALIASWARN1 (rawmemchr, void *,
+                   (void *__s, int __c_in)
+                   _GL_ATTRIBUTE_NOTHROW);
 _GL_CXXALIASWARN1 (rawmemchr, void const *,
-                   (void const *__s, int __c_in) throw ());
+                   (void const *__s, int __c_in)
+                   _GL_ATTRIBUTE_NOTHROW);
 # else
 _GL_CXXALIASWARN (rawmemchr);
 # endif
@@ -538,9 +581,12 @@ _GL_CXXALIAS_SYS_CAST2 (strchrnul,
 # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
      && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
          || defined __clang__)
-_GL_CXXALIASWARN1 (strchrnul, char *, (char *__s, int __c_in) throw ());
+_GL_CXXALIASWARN1 (strchrnul, char *,
+                   (char *__s, int __c_in)
+                   _GL_ATTRIBUTE_NOTHROW);
 _GL_CXXALIASWARN1 (strchrnul, char const *,
-                   (char const *__s, int __c_in) throw ());
+                   (char const *__s, int __c_in)
+                   _GL_ATTRIBUTE_NOTHROW);
 # elif __GLIBC__ >= 2
 _GL_CXXALIASWARN (strchrnul);
 # endif
@@ -576,10 +622,18 @@ _GL_CXXALIAS_MDA (strdup, char *, (char const *__s));
 #   undef strdup
 #  endif
 #  if (!@HAVE_DECL_STRDUP@ || __GNUC__ >= 11) && !defined strdup
+#   if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
+_GL_FUNCDECL_SYS (strdup, char *,
+                  (char const *__s)
+                  _GL_ATTRIBUTE_NOTHROW
+                  _GL_ARG_NONNULL ((1))
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#   else
 _GL_FUNCDECL_SYS (strdup, char *,
                   (char const *__s)
                   _GL_ARG_NONNULL ((1))
                   _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#   endif
 #  endif
 _GL_CXXALIAS_SYS (strdup, char *, (char const *__s));
 # endif
@@ -587,10 +641,18 @@ _GL_CXXALIASWARN (strdup);
 #else
 # if __GNUC__ >= 11 && !defined strdup
 /* For -Wmismatched-dealloc: Associate strdup with free or rpl_free.  */
+#  if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
 _GL_FUNCDECL_SYS (strdup, char *,
                   (char const *__s)
+                  _GL_ATTRIBUTE_NOTHROW
                   _GL_ARG_NONNULL ((1))
                   _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#  else
+_GL_FUNCDECL_SYS (strdup, char *,
+                  (char const *__s)
+                  _GL_ARG_NONNULL ((1))
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#  endif
 # endif
 # if defined GNULIB_POSIXCHECK
 #  undef strdup
@@ -659,10 +721,18 @@ _GL_FUNCDECL_RPL (strndup, char *,
 _GL_CXXALIAS_RPL (strndup, char *, (char const *__s, size_t __n));
 # else
 #  if !@HAVE_DECL_STRNDUP@ || (__GNUC__ >= 11 && !defined strndup)
+#   if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
+_GL_FUNCDECL_SYS (strndup, char *,
+                  (char const *__s, size_t __n)
+                  _GL_ATTRIBUTE_NOTHROW
+                  _GL_ARG_NONNULL ((1))
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#   else
 _GL_FUNCDECL_SYS (strndup, char *,
                   (char const *__s, size_t __n)
                   _GL_ARG_NONNULL ((1))
                   _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#   endif
 #  endif
 _GL_CXXALIAS_SYS (strndup, char *, (char const *__s, size_t __n));
 # endif
@@ -670,10 +740,18 @@ _GL_CXXALIASWARN (strndup);
 #else
 # if __GNUC__ >= 11 && !defined strndup
 /* For -Wmismatched-dealloc: Associate strndup with free or rpl_free.  */
+#  if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
+_GL_FUNCDECL_SYS (strndup, char *,
+                  (char const *__s, size_t __n)
+                  _GL_ATTRIBUTE_NOTHROW
+                  _GL_ARG_NONNULL ((1))
+                  _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#  else
 _GL_FUNCDECL_SYS (strndup, char *,
                   (char const *__s, size_t __n)
                   _GL_ARG_NONNULL ((1))
                   _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE);
+#  endif
 # endif
 # if defined GNULIB_POSIXCHECK
 #  undef strndup
@@ -742,9 +820,12 @@ _GL_CXXALIAS_SYS_CAST2 (strpbrk,
 # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \
      && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
          || defined __clang__)
-_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept) throw 
());
+_GL_CXXALIASWARN1 (strpbrk, char *,
+                   (char *__s, char const *__accept)
+                   _GL_ATTRIBUTE_NOTHROW);
 _GL_CXXALIASWARN1 (strpbrk, char const *,
-                   (char const *__s, char const *__accept) throw ());
+                   (char const *__s, char const *__accept)
+                   _GL_ATTRIBUTE_NOTHROW);
 # elif __GLIBC__ >= 2
 _GL_CXXALIASWARN (strpbrk);
 # endif
@@ -852,9 +933,11 @@ _GL_CXXALIAS_SYS_CAST2 (strstr,
      && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
          || defined __clang__)
 _GL_CXXALIASWARN1 (strstr, char *,
-                   (char *haystack, const char *needle) throw ());
+                   (char *haystack, const char *needle)
+                   _GL_ATTRIBUTE_NOTHROW);
 _GL_CXXALIASWARN1 (strstr, const char *,
-                   (const char *haystack, const char *needle) throw ());
+                   (const char *haystack, const char *needle)
+                   _GL_ATTRIBUTE_NOTHROW);
 # elif __GLIBC__ >= 2
 _GL_CXXALIASWARN (strstr);
 # endif
@@ -903,9 +986,11 @@ _GL_CXXALIAS_SYS_CAST2 (strcasestr,
      && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
          || defined __clang__)
 _GL_CXXALIASWARN1 (strcasestr, char *,
-                   (char *haystack, const char *needle) throw ());
+                   (char *haystack, const char *needle)
+                   _GL_ATTRIBUTE_NOTHROW);
 _GL_CXXALIASWARN1 (strcasestr, const char *,
-                   (const char *haystack, const char *needle) throw ());
+                   (const char *haystack, const char *needle)
+                   _GL_ATTRIBUTE_NOTHROW);
 # elif __GLIBC__ >= 2
 _GL_CXXALIASWARN (strcasestr);
 # endif
@@ -1344,12 +1429,22 @@ _GL_WARN_ON_USE (strsignal, "strsignal is unportable - "
 #endif
 
 #if @GNULIB_STRVERSCMP@
-# if !@HAVE_STRVERSCMP@
+# if @REPLACE_STRVERSCMP@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   define strverscmp rpl_strverscmp
+#  endif
+_GL_FUNCDECL_RPL (strverscmp, int, (const char *, const char *)
+                                   _GL_ATTRIBUTE_PURE
+                                   _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (strverscmp, int, (const char *, const char *));
+# else
+#  if !@HAVE_STRVERSCMP@
 _GL_FUNCDECL_SYS (strverscmp, int, (const char *, const char *)
                                    _GL_ATTRIBUTE_PURE
                                    _GL_ARG_NONNULL ((1, 2)));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (strverscmp, int, (const char *, const char *));
+# endif
 _GL_CXXALIASWARN (strverscmp);
 #elif defined GNULIB_POSIXCHECK
 # undef strverscmp
diff --git a/lib/strnlen.c b/lib/strnlen.c
index 09c010eac42..80857ec22b0 100644
--- a/lib/strnlen.c
+++ b/lib/strnlen.c
@@ -1,5 +1,5 @@
 /* Find the length of STRING, but scan at most MAXLEN characters.
-   Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2005-2007, 2009-2024 Free Software Foundation, Inc.
    Written by Simon Josefsson.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/strtoimax.c b/lib/strtoimax.c
index f7977e28e64..1bc62621ec5 100644
--- a/lib/strtoimax.c
+++ b/lib/strtoimax.c
@@ -1,6 +1,6 @@
 /* Convert string representation of a number into an intmax_t value.
 
-   Copyright (C) 1999, 2001-2004, 2006, 2009-2023 Free Software Foundation,
+   Copyright (C) 1999, 2001-2004, 2006, 2009-2024 Free Software Foundation,
    Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/strtol.c b/lib/strtol.c
index b93483dca49..914cf5b57ab 100644
--- a/lib/strtol.c
+++ b/lib/strtol.c
@@ -1,6 +1,6 @@
 /* Convert string representation of a number into an integer value.
 
-   Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2023 Free Software
+   Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2024 Free Software
    Foundation, Inc.
 
    NOTE: The canonical source of this file is maintained with the GNU C
diff --git a/lib/strtoll.c b/lib/strtoll.c
index 9fdfa19b220..d3f5e47fc12 100644
--- a/lib/strtoll.c
+++ b/lib/strtoll.c
@@ -1,5 +1,5 @@
 /* Function to parse a 'long long int' from text.
-   Copyright (C) 1995-1997, 1999, 2001, 2009-2023 Free Software Foundation,
+   Copyright (C) 1995-1997, 1999, 2001, 2009-2024 Free Software Foundation,
    Inc.
    This file is part of the GNU C Library.
 
diff --git a/lib/symlink.c b/lib/symlink.c
index b5009ae8355..6ba83666e17 100644
--- a/lib/symlink.c
+++ b/lib/symlink.c
@@ -1,5 +1,5 @@
 /* Stub for symlink().
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 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
diff --git a/lib/sys_random.in.h b/lib/sys_random.in.h
index b240033bcbf..22f67b17635 100644
--- a/lib/sys_random.in.h
+++ b/lib/sys_random.in.h
@@ -1,5 +1,5 @@
 /* Substitute for <sys/random.h>.
-   Copyright (C) 2020-2023 Free Software Foundation, Inc.
+   Copyright (C) 2020-2024 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
diff --git a/lib/sys_select.in.h b/lib/sys_select.in.h
index 3abfc48af09..de29c77949a 100644
--- a/lib/sys_select.in.h
+++ b/lib/sys_select.in.h
@@ -1,5 +1,5 @@
 /* Substitute for <sys/select.h>.
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 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
diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h
index ad4da17fa46..bf08f33536d 100644
--- a/lib/sys_stat.in.h
+++ b/lib/sys_stat.in.h
@@ -1,5 +1,5 @@
 /* Provide a more complete sys/stat.h header file.
-   Copyright (C) 2005-2023 Free Software Foundation, Inc.
+   Copyright (C) 2005-2024 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
@@ -55,17 +55,41 @@
 #ifndef _@GUARD_PREFIX@_SYS_STAT_H
 #define _@GUARD_PREFIX@_SYS_STAT_H
 
-/* This file uses GNULIB_POSIXCHECK, HAVE_RAW_DECL_*.  */
+/* This file uses _GL_ATTRIBUTE_NOTHROW, GNULIB_POSIXCHECK, HAVE_RAW_DECL_*.  
*/
 #if !_GL_CONFIG_H_INCLUDED
  #error "Please include config.h first."
 #endif
 
+
+/* _GL_ATTRIBUTE_NOTHROW declares that the function does not throw exceptions.
+ */
+#ifndef _GL_ATTRIBUTE_NOTHROW
+# if defined __cplusplus
+#  if (__GNUC__ + (__GNUC_MINOR__ >= 8) > 2) || __clang_major >= 4
+#   if __cplusplus >= 201103L
+#    define _GL_ATTRIBUTE_NOTHROW noexcept (true)
+#   else
+#    define _GL_ATTRIBUTE_NOTHROW throw ()
+#   endif
+#  else
+#   define _GL_ATTRIBUTE_NOTHROW
+#  endif
+# else
+#  if (__GNUC__ + (__GNUC_MINOR__ >= 3) > 3) || defined __clang__
+#   define _GL_ATTRIBUTE_NOTHROW __attribute__ ((__nothrow__))
+#  else
+#   define _GL_ATTRIBUTE_NOTHROW
+#  endif
+# endif
+#endif
+
 /* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
 
 /* The definition of _GL_ARG_NONNULL is copied here.  */
 
 /* The definition of _GL_WARN_ON_USE is copied here.  */
 
+
 /* Before doing "#define mknod rpl_mknod" below, we need to include all
    headers that may declare mknod().  OS/2 kLIBC declares mknod() in
    <unistd.h>, not in <sys/stat.h>.  */
@@ -575,7 +599,11 @@ _GL_WARN_ON_USE (futimens, "futimens is not portable - "
 
 #if @GNULIB_GETUMASK@
 # if !@HAVE_GETUMASK@
+#  if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2
+_GL_FUNCDECL_SYS (getumask, mode_t, (void) _GL_ATTRIBUTE_NOTHROW);
+#  else
 _GL_FUNCDECL_SYS (getumask, mode_t, (void));
+#  endif
 # endif
 _GL_CXXALIAS_SYS (getumask, mode_t, (void));
 # if @HAVE_GETUMASK@
diff --git a/lib/sys_time.in.h b/lib/sys_time.in.h
index 59cce1440da..4a301c48ba1 100644
--- a/lib/sys_time.in.h
+++ b/lib/sys_time.in.h
@@ -1,6 +1,6 @@
 /* Provide a more complete sys/time.h.
 
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 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
diff --git a/lib/sys_types.in.h b/lib/sys_types.in.h
index ea77e140be9..0a0ccc3c379 100644
--- a/lib/sys_types.in.h
+++ b/lib/sys_types.in.h
@@ -1,6 +1,6 @@
 /* Provide a more complete sys/types.h.
 
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 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
diff --git a/lib/tempname.c b/lib/tempname.c
index bf362db6e17..446ddeaef19 100644
--- a/lib/tempname.c
+++ b/lib/tempname.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -193,7 +193,7 @@ try_tempname_len (char *tmpl, int suffixlen, void *args,
   char *XXXXXX;
   unsigned int count;
   int fd = -1;
-  int save_errno = errno;
+  int saved_errno = errno;
 
   /* A lower bound on the number of temporary files to attempt to
      generate.  The maximum total number of temporary file names that
@@ -258,7 +258,7 @@ try_tempname_len (char *tmpl, int suffixlen, void *args,
       fd = tryfunc (tmpl, args);
       if (fd >= 0)
         {
-          __set_errno (save_errno);
+          __set_errno (saved_errno);
           return fd;
         }
       else if (errno != EEXIST)
diff --git a/lib/tempname.h b/lib/tempname.h
index 36a51381548..7cbdac95dea 100644
--- a/lib/tempname.h
+++ b/lib/tempname.h
@@ -1,6 +1,6 @@
 /* Create a temporary file or directory.
 
-   Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2009-2024 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
diff --git a/lib/time-internal.h b/lib/time-internal.h
index 51423c94ca9..816684a1172 100644
--- a/lib/time-internal.h
+++ b/lib/time-internal.h
@@ -1,6 +1,6 @@
 /* Time internal interface
 
-   Copyright 2015-2023 Free Software Foundation, Inc.
+   Copyright 2015-2024 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
diff --git a/lib/time.in.h b/lib/time.in.h
index 06824da9d3d..ce28f1af25d 100644
--- a/lib/time.in.h
+++ b/lib/time.in.h
@@ -1,6 +1,6 @@
 /* A more-standard <time.h>.
 
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 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
@@ -154,11 +154,21 @@ _GL_WARN_ON_USE (timespec_get, "timespec_get is 
unportable - "
 /* Set *TS to the current time resolution, and return BASE.
    Upon failure, return 0.  */
 # if @GNULIB_TIMESPEC_GETRES@
-#  if ! @HAVE_TIMESPEC_GETRES@
+#  if @REPLACE_TIMESPEC_GETRES@
+#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#    undef timespec_getres
+#    define timespec_getres rpl_timespec_getres
+#   endif
+_GL_FUNCDECL_RPL (timespec_getres, int, (struct timespec *ts, int base)
+                                        _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (timespec_getres, int, (struct timespec *ts, int base));
+#  else
+#   if !@HAVE_TIMESPEC_GETRES@
 _GL_FUNCDECL_SYS (timespec_getres, int, (struct timespec *ts, int base)
                                         _GL_ARG_NONNULL ((1)));
-#  endif
+#   endif
 _GL_CXXALIAS_SYS (timespec_getres, int, (struct timespec *ts, int base));
+#  endif
 _GL_CXXALIASWARN (timespec_getres);
 # elif defined GNULIB_POSIXCHECK
 #  undef timespec_getres
diff --git a/lib/time_r.c b/lib/time_r.c
index 97be4fd0544..3ef0b36802c 100644
--- a/lib/time_r.c
+++ b/lib/time_r.c
@@ -1,6 +1,6 @@
 /* Reentrant time functions like localtime_r.
 
-   Copyright (C) 2003, 2006-2007, 2010-2023 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2006-2007, 2010-2024 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
diff --git a/lib/time_rz.c b/lib/time_rz.c
index da0d57b8b1a..468d7539ce1 100644
--- a/lib/time_rz.c
+++ b/lib/time_rz.c
@@ -1,6 +1,6 @@
 /* Time zone functions such as tzalloc and localtime_rz
 
-   Copyright 2015-2023 Free Software Foundation, Inc.
+   Copyright 2015-2024 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
diff --git a/lib/timegm.c b/lib/timegm.c
index b47025a0545..e5cf30c0198 100644
--- a/lib/timegm.c
+++ b/lib/timegm.c
@@ -1,6 +1,6 @@
 /* Convert UTC calendar time to simple time.  Like mktime but assumes UTC.
 
-   Copyright (C) 1994-2023 Free Software Foundation, Inc.
+   Copyright (C) 1994-2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/timespec-add.c b/lib/timespec-add.c
index 38c4dfc24c2..e10c19842cd 100644
--- a/lib/timespec-add.c
+++ b/lib/timespec-add.c
@@ -1,6 +1,6 @@
 /* Add two struct timespec values.
 
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/timespec-sub.c b/lib/timespec-sub.c
index f8052400410..315cc638369 100644
--- a/lib/timespec-sub.c
+++ b/lib/timespec-sub.c
@@ -1,6 +1,6 @@
 /* Subtract two struct timespec values.
 
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/timespec.c b/lib/timespec.c
index 5f7ffbdd45f..8cee9870c71 100644
--- a/lib/timespec.c
+++ b/lib/timespec.c
@@ -1,6 +1,6 @@
 /* Inline functions for <timespec.h>.
 
-   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Copyright (C) 2012-2024 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
diff --git a/lib/timespec.h b/lib/timespec.h
index e94da75defe..69ce348569d 100644
--- a/lib/timespec.h
+++ b/lib/timespec.h
@@ -1,6 +1,6 @@
 /* timespec -- System time interface
 
-   Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2023 Free Software
+   Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2024 Free Software
    Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
diff --git a/lib/u64.c b/lib/u64.c
index ca088b45463..f788470b8f4 100644
--- a/lib/u64.c
+++ b/lib/u64.c
@@ -1,6 +1,6 @@
 /* uint64_t-like operations that work even on hosts lacking uint64_t
 
-   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Copyright (C) 2012-2024 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
diff --git a/lib/u64.h b/lib/u64.h
index 8a99335b6aa..63339cca0fc 100644
--- a/lib/u64.h
+++ b/lib/u64.h
@@ -1,6 +1,6 @@
 /* uint64_t-like operations that work even on hosts lacking uint64_t
 
-   Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2009-2024 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
diff --git a/lib/unistd.c b/lib/unistd.c
index be7a8255033..f3b3f7bd2fe 100644
--- a/lib/unistd.c
+++ b/lib/unistd.c
@@ -1,6 +1,6 @@
 /* Inline functions for <unistd.h>.
 
-   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Copyright (C) 2012-2024 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
@@ -18,5 +18,5 @@
 #include <config.h>
 
 #define _GL_UNISTD_INLINE _GL_EXTERN_INLINE
-#include "unistd.h"
+#include <unistd.h>
 typedef int dummy;
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 2ae040a76b3..b412966367d 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -1,5 +1,5 @@
 /* Substitute for and wrapper around <unistd.h>.
-   Copyright (C) 2003-2023 Free Software Foundation, Inc.
+   Copyright (C) 2003-2024 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
@@ -971,23 +971,28 @@ _GL_WARN_ON_USE (faccessat, "faccessat is not portable - "
    Return 0 if successful, otherwise -1 and errno set.
    See the POSIX:2008 specification
    <https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html>.  
*/
-# if ! @HAVE_FCHDIR@
+# if @REPLACE_FCHDIR@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef fchdir
+#   define fchdir rpl_fchdir
+#  endif
+_GL_FUNCDECL_RPL (fchdir, int, (int /*fd*/));
+_GL_CXXALIAS_RPL (fchdir, int, (int /*fd*/));
+# else
+#  if !@HAVE_FCHDIR@ || !@HAVE_DECL_FCHDIR@
 _GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/));
-
+#  endif
+_GL_CXXALIAS_SYS (fchdir, int, (int /*fd*/));
+# endif
+_GL_CXXALIASWARN (fchdir);
+# if @REPLACE_FCHDIR@ || !@HAVE_FCHDIR@
 /* Gnulib internal hooks needed to maintain the fchdir metadata.  */
 _GL_EXTERN_C int _gl_register_fd (int fd, const char *filename)
      _GL_ARG_NONNULL ((2));
 _GL_EXTERN_C void _gl_unregister_fd (int fd);
 _GL_EXTERN_C int _gl_register_dup (int oldfd, int newfd);
 _GL_EXTERN_C const char *_gl_directory_name (int fd);
-
-# else
-#  if !@HAVE_DECL_FCHDIR@
-_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/));
-#  endif
 # endif
-_GL_CXXALIAS_SYS (fchdir, int, (int /*fd*/));
-_GL_CXXALIASWARN (fchdir);
 #elif defined GNULIB_POSIXCHECK
 # undef fchdir
 # if HAVE_RAW_DECL_FCHDIR
@@ -1113,10 +1118,10 @@ _GL_WARN_ON_USE (ftruncate, "ftruncate is unportable - "
    or SIZE was too small.
    See the POSIX:2008 specification
    <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html>.
-   Additionally, the gnulib module 'getcwd' guarantees the following GNU
-   extension: If BUF is NULL, an array is allocated with 'malloc'; the array
-   is SIZE bytes long, unless SIZE == 0, in which case it is as big as
-   necessary.  */
+   Additionally, the gnulib module 'getcwd' or 'getcwd-lgpl' guarantees the
+   following GNU extension: If BUF is NULL, an array is allocated with
+   'malloc'; the array is SIZE bytes long, unless SIZE == 0, in which case
+   it is as big as necessary.  */
 # if @REPLACE_GETCWD@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
 #   define getcwd rpl_getcwd
diff --git a/lib/unlocked-io.h b/lib/unlocked-io.h
index 4830df4a747..0cd9bbf3c98 100644
--- a/lib/unlocked-io.h
+++ b/lib/unlocked-io.h
@@ -1,6 +1,6 @@
 /* Prefer faster, non-thread-safe stdio functions if available.
 
-   Copyright (C) 2001-2004, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2004, 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -101,7 +101,7 @@
 #  define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
 # endif
 
-# if HAVE_DECL_GETC_UNLOCKED || defined get_unlocked
+# if HAVE_DECL_GETC_UNLOCKED || defined getc_unlocked
 #  undef getc
 #  define getc(x) getc_unlocked (x)
 # else
diff --git a/lib/utimens.c b/lib/utimens.c
index faa197e6cb5..4bfb9c91a7b 100644
--- a/lib/utimens.c
+++ b/lib/utimens.c
@@ -1,6 +1,6 @@
 /* Set file access and modification times.
 
-   Copyright (C) 2003-2023 Free Software Foundation, Inc.
+   Copyright (C) 2003-2024 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
@@ -231,8 +231,8 @@ fdutimens (int fd, char const *file, struct timespec const 
timespec[2])
 
          The same bug occurs in Solaris 11.1 (Apr 2013).
 
-         FIXME: Simplify this for Linux in 2016 and for Solaris in
-         2024, when file system bugs are no longer common.  */
+         FIXME: Simplify this in 2024, when these file system bugs are
+         no longer common on Gnulib target platforms.  */
       if (adjustment_needed == 2)
         {
           if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
diff --git a/lib/utimens.h b/lib/utimens.h
index 4a21792a7e4..7c740afd36d 100644
--- a/lib/utimens.h
+++ b/lib/utimens.h
@@ -1,6 +1,6 @@
 /* Set file access and modification times.
 
-   Copyright 2012-2023 Free Software Foundation, Inc.
+   Copyright 2012-2024 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
diff --git a/lib/utimensat.c b/lib/utimensat.c
index 5cff11cd0a9..1321264269e 100644
--- a/lib/utimensat.c
+++ b/lib/utimensat.c
@@ -1,5 +1,5 @@
 /* Set the access and modification time of a file relative to directory fd.
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/verify.h b/lib/verify.h
index e4af91517e6..08268c2498f 100644
--- a/lib/verify.h
+++ b/lib/verify.h
@@ -1,6 +1,6 @@
 /* Compile-time assert-like macros.
 
-   Copyright (C) 2005-2006, 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2005-2006, 2009-2024 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
@@ -188,9 +188,9 @@ template <int w>
     _gl_verify_type<(R) ? 1 : -1>
 #elif defined _GL_HAVE__STATIC_ASSERT
 # define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \
-    struct {                                   \
-      _Static_assert (R, DIAGNOSTIC);          \
-      int _gl_dummy;                          \
+    struct { \
+      _Static_assert (R, DIAGNOSTIC); \
+      int _gl_dummy; \
     }
 #else
 # define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \
@@ -212,8 +212,8 @@ template <int w>
 #elif defined _GL_HAVE__STATIC_ASSERT
 # define _GL_VERIFY(R, DIAGNOSTIC, ...) _Static_assert (R, DIAGNOSTIC)
 #else
-# define _GL_VERIFY(R, DIAGNOSTIC, ...)                                \
-    extern int (*_GL_GENSYM (_gl_verify_function) (void))             \
+# define _GL_VERIFY(R, DIAGNOSTIC, ...) \
+    extern int (*_GL_GENSYM (_gl_verify_function) (void)) \
       [_GL_VERIFY_TRUE (R, DIAGNOSTIC)]
 # if 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
 #  pragma GCC diagnostic ignored "-Wnested-externs"
diff --git a/lib/vla.h b/lib/vla.h
index 55f112a060a..a999d127822 100644
--- a/lib/vla.h
+++ b/lib/vla.h
@@ -1,6 +1,6 @@
 /* vla.h - variable length arrays
 
-   Copyright 2014-2023 Free Software Foundation, Inc.
+   Copyright 2014-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
diff --git a/lib/warn-on-use.h b/lib/warn-on-use.h
index 30756034aff..8f4d40dcbeb 100644
--- a/lib/warn-on-use.h
+++ b/lib/warn-on-use.h
@@ -1,5 +1,5 @@
 /* A C macro for emitting warnings if a function is used.
-   Copyright (C) 2010-2023 Free Software Foundation, Inc.
+   Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published
diff --git a/lib/xalloc-oversized.h b/lib/xalloc-oversized.h
index 5dbdfb5506a..0b7bb2cee85 100644
--- a/lib/xalloc-oversized.h
+++ b/lib/xalloc-oversized.h
@@ -1,6 +1,6 @@
 /* xalloc-oversized.h -- memory allocation size checking
 
-   Copyright (C) 1990-2000, 2003-2004, 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 1990-2000, 2003-2004, 2006-2024 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
@@ -48,13 +48,13 @@
 #if 7 <= __GNUC__ && !defined __clang__ && PTRDIFF_MAX < SIZE_MAX
 # define xalloc_oversized(n, s) \
    __builtin_mul_overflow_p (n, s, (ptrdiff_t) 1)
-#elif (5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__ \
-       && PTRDIFF_MAX < SIZE_MAX)
+#elif 5 <= __GNUC__ && !defined __ICC && PTRDIFF_MAX < SIZE_MAX
 # define xalloc_oversized(n, s) \
    (__builtin_constant_p (n) && __builtin_constant_p (s) \
     ? __xalloc_oversized (n, s) \
-    : ({ ptrdiff_t __xalloc_count; \
-         __builtin_mul_overflow (n, s, &__xalloc_count); }))
+    : __extension__ \
+        ({ ptrdiff_t __xalloc_count; \
+           __builtin_mul_overflow (n, s, &__xalloc_count); }))
 
 /* Other compilers use integer division; this may be slower but is
    more portable.  */
diff --git a/lisp/ChangeLog.1 b/lisp/ChangeLog.1
index 9dfff744e28..49296aaf3a7 100644
--- a/lisp/ChangeLog.1
+++ b/lisp/ChangeLog.1
@@ -3244,7 +3244,7 @@
                Set current buffer variables from defaults
                in case user's init file has changed them.
 
-  Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.10 b/lisp/ChangeLog.10
index fb88141e136..9bc34ea94e7 100644
--- a/lisp/ChangeLog.10
+++ b/lisp/ChangeLog.10
@@ -23541,7 +23541,7 @@ See ChangeLog.9 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-    Copyright (C) 2001-2023 Free Software Foundation, Inc.
+    Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.11 b/lisp/ChangeLog.11
index cbdf3ec57e0..65a55cd7dfb 100644
--- a/lisp/ChangeLog.11
+++ b/lisp/ChangeLog.11
@@ -14322,7 +14322,7 @@ See ChangeLog.10 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2003-2011, 2013-2023 Free Software Foundation, Inc.
+  Copyright (C) 2003-2011, 2013-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.12 b/lisp/ChangeLog.12
index 88d3a41461c..e042d023292 100644
--- a/lisp/ChangeLog.12
+++ b/lisp/ChangeLog.12
@@ -10678,7 +10678,7 @@
        for root variables.
 
        * progmodes/gdb-ui.el (gdb-pc-address): Rename from gdb-frame-address.
-       (gdb-frame-address): Re-use to identify frame for watch expression.
+       (gdb-frame-address): Reuse to identify frame for watch expression.
        (gdb-var-list, gdb-var-create-handler): Add frame address for root
        variables.
        (gdb-init-1, gdb-source, gdb-post-prompt)
@@ -33335,7 +33335,7 @@ See ChangeLog.11 for earlier changes.
 ;; add-log-time-zone-rule: t
 ;; End:
 
-    Copyright (C) 2005-2023 Free Software Foundation, Inc.
+    Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.13 b/lisp/ChangeLog.13
index ac382e1685d..414cd1d25f8 100644
--- a/lisp/ChangeLog.13
+++ b/lisp/ChangeLog.13
@@ -12592,7 +12592,7 @@
 
        * textmodes/org.el (org-agenda-skip): Allow a form for
        `org-agenda-skip-function'.
-       (org-agenda-redo): Re-use local settings.
+       (org-agenda-redo): Reuse local settings.
        (org-agenda): Store local settings.
        (org-agenda-deadline-faces): New option.
        (org-agenda-deadline-face): New function.
@@ -16697,7 +16697,7 @@ See ChangeLog.12 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2007-2023 Free Software Foundation, Inc.
+  Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.14 b/lisp/ChangeLog.14
index efaac2869c8..3d6df493041 100644
--- a/lisp/ChangeLog.14
+++ b/lisp/ChangeLog.14
@@ -16505,7 +16505,7 @@
        (diary-list-entries-2): Simplify finding start of date.
        (diary-show-all-entries, make-diary-entry): Respect non-nil values of
        pop-up-frames.
-       (diary-mark-entries-1): Re-use offset in abbreviated-year case.
+       (diary-mark-entries-1): Reuse offset in abbreviated-year case.
        (mark-sexp-diary-entries): Remove superfluous call to diary-pull-attrs.
 
 2008-03-27  Dan Nicolaescu  <dann@ics.uci.edu>
@@ -17072,14 +17072,14 @@
        * calendar/cal-bahai.el (calendar-bahai-leap-year-p)
        (calendar-bahai-leap-base, calendar-bahai-from-absolute): Doc fixes.
        (calendar-absolute-from-bahai): Fix the leap-year case.
-       (calendar-bahai-from-absolute): Re-use the Gregorian month.
+       (calendar-bahai-from-absolute): Reuse the Gregorian month.
        (calendar-bahai-date-string, calendar-bahai-print-date):
        Handle pre-Bahai dates.
 
        * calendar/cal-china.el (chinese-calendar-celestial-stem)
        (chinese-calendar-terrestrial-branch): Make defcustoms.
 
-       * calendar/cal-menu.el (calendar-mouse-holidays): Re-use the title.
+       * calendar/cal-menu.el (calendar-mouse-holidays): Reuse the title.
        (calendar-mouse-view-diary-entries): Use or.
        (calendar-mouse-chinese-date): Remove unused command.
        (cal-menu-load-hook): Mark as obsolete.
@@ -20547,7 +20547,7 @@ See ChangeLog.13 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-    Copyright (C) 2008-2023 Free Software Foundation, Inc.
+    Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.15 b/lisp/ChangeLog.15
index c6026b8b9a8..a441dc46ad3 100644
--- a/lisp/ChangeLog.15
+++ b/lisp/ChangeLog.15
@@ -7702,7 +7702,7 @@
 
        * finder.el: Load finder-inf using `require'.
        (finder-list-matches): Sorting by status is now the default.
-       (finder-compile-keywords): Simpify printing.
+       (finder-compile-keywords): Simplify printing.
 
 2010-08-30  Stefan Monnier  <monnier@iro.umontreal.ca>
 
@@ -22802,7 +22802,7 @@ See ChangeLog.14 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2009-2023 Free Software Foundation, Inc.
+  Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.16 b/lisp/ChangeLog.16
index 39649ec8ae0..fa956ac8784 100644
--- a/lisp/ChangeLog.16
+++ b/lisp/ChangeLog.16
@@ -1770,7 +1770,7 @@
        (jit-lock--debug-fontifying): New var.
        (jit-lock--debug-fontify): New function.
        * subr.el (condition-case-unless-debug): Don't prevent catching the
-       error, just let the debbugger run.
+       error, just let the debugger run.
        * emacs-lisp/timer.el (timer-event-handler): Don't prevent debugging
        timer code and don't drop errors silently.
 
@@ -4784,7 +4784,7 @@
        Convert to defcustom.
        (gdb-get-source-file): Don't bind pop-up-windows.
 
-       * progmodes/gud.el (gud-display-line): Don't specially re-use
+       * progmodes/gud.el (gud-display-line): Don't specially reuse
        other frames for the gdb-mi case (Bug#12648).
 
 2012-10-18  Stefan Monnier  <monnier@iro.umontreal.ca>
@@ -25222,7 +25222,7 @@ See ChangeLog.15 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2011-2023 Free Software Foundation, Inc.
+  Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.17 b/lisp/ChangeLog.17
index 19b8e1e28eb..0e69fd5e461 100644
--- a/lisp/ChangeLog.17
+++ b/lisp/ChangeLog.17
@@ -4339,7 +4339,7 @@
        (verilog-beg-of-statement-1, verilog-at-constraint-p):
        Fix hanging with many curly-bracket pairs, bug663.
        (verilog-do-indent): Fix electric tab deleting form-feeds.
-       Note caused by indent-line-to deleting tabls pre 24.5.
+       Note caused by indent-line-to deleting tables pre 24.5.
        (verilog-auto-output, verilog-auto-input, verilog-auto-inout)
        (verilog-auto-inout-module, verilog-auto-inout-in): Doc fixes.
        (verilog-read-always-signals, verilog-auto-sense-sigs)
@@ -26294,7 +26294,7 @@ See ChangeLog.16 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2011-2023 Free Software Foundation, Inc.
+  Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.2 b/lisp/ChangeLog.2
index 039f9abd13d..4e8813668ab 100644
--- a/lisp/ChangeLog.2
+++ b/lisp/ChangeLog.2
@@ -3992,7 +3992,7 @@
 
 See ChangeLog.1 for earlier changes.
 
-    Copyright (C) 1986-1988, 2001-2023 Free Software Foundation, Inc.
+    Copyright (C) 1986-1988, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.3 b/lisp/ChangeLog.3
index 29585129a8a..843492958dd 100644
--- a/lisp/ChangeLog.3
+++ b/lisp/ChangeLog.3
@@ -12433,7 +12433,7 @@ See ChangeLog.2 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-    Copyright (C) 1989, 1993, 2001-2023 Free Software Foundation, Inc.
+    Copyright (C) 1989, 1993, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.4 b/lisp/ChangeLog.4
index 702a059ce65..3d8421a1c7e 100644
--- a/lisp/ChangeLog.4
+++ b/lisp/ChangeLog.4
@@ -8935,7 +8935,7 @@ See ChangeLog.3 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-    Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+    Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.5 b/lisp/ChangeLog.5
index a9f1beaaae8..1cbd1f923d0 100644
--- a/lisp/ChangeLog.5
+++ b/lisp/ChangeLog.5
@@ -9268,7 +9268,7 @@ See ChangeLog.4 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-    Copyright (C) 1994-1995, 2001-2023 Free Software Foundation, Inc.
+    Copyright (C) 1994-1995, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.6 b/lisp/ChangeLog.6
index fcad77bd38f..84253b2d079 100644
--- a/lisp/ChangeLog.6
+++ b/lisp/ChangeLog.6
@@ -8021,7 +8021,7 @@ See ChangeLog.5 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-    Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc.
+    Copyright (C) 1995-1996, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.7 b/lisp/ChangeLog.7
index 17464042b76..efd01a86166 100644
--- a/lisp/ChangeLog.7
+++ b/lisp/ChangeLog.7
@@ -5232,7 +5232,7 @@
 
 1998-03-29  Ralph Schleicher  <rs@purple.UL.BaWue.DE>
 
-       * battery.el (battery-linux-proc-apm): Re-use the temporary
+       * battery.el (battery-linux-proc-apm): Reuse the temporary
        buffer.
 
        * battery.el (battery-insert-file-contents): Disable code
@@ -23111,7 +23111,7 @@ See ChangeLog.6 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-       Copyright (C) 1997-1998, 2001-2023 Free Software Foundation,
+       Copyright (C) 1997-1998, 2001-2024 Free Software Foundation,
        Inc.
 
   This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.8 b/lisp/ChangeLog.8
index 9c5096e56c5..b557c62b9ac 100644
--- a/lisp/ChangeLog.8
+++ b/lisp/ChangeLog.8
@@ -9993,7 +9993,7 @@ See ChangeLog.7 for earlier changes.
 ;; add-log-time-zone-rule: t
 ;; End:
 
-    Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+    Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/ChangeLog.9 b/lisp/ChangeLog.9
index 063b9ea4991..ca962d92987 100644
--- a/lisp/ChangeLog.9
+++ b/lisp/ChangeLog.9
@@ -20685,7 +20685,7 @@ See ChangeLog.8 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-    Copyright (C) 2000-2011, 2013-2023 Free Software Foundation, Inc.
+    Copyright (C) 2000-2011, 2013-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/Makefile.in b/lisp/Makefile.in
index d47997ef688..adeace63ef2 100644
--- a/lisp/Makefile.in
+++ b/lisp/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 2000-2023 Free Software Foundation, Inc.
+# Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/lisp/abbrev.el b/lisp/abbrev.el
index e916cf25bf0..2bd9faad69d 100644
--- a/lisp/abbrev.el
+++ b/lisp/abbrev.el
@@ -1,6 +1,6 @@
 ;;; abbrev.el --- abbrev mode commands for Emacs -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: abbrev convenience
@@ -1275,7 +1275,7 @@ which see."
   (setq font-lock-multiline nil))
 
 (defun abbrev--possibly-save (query &optional arg)
-  "Hook function for use by `save-some-buffer-functions'.
+  "Hook function for use by `save-some-buffers-functions'.
 
 Maybe save abbrevs, and record whether we either saved them or asked to."
   ;; Query mode.
diff --git a/lisp/align.el b/lisp/align.el
index 4daa20ddd2a..fa95f24fa02 100644
--- a/lisp/align.el
+++ b/lisp/align.el
@@ -1,6 +1,6 @@
 ;;; align.el --- align text to a specific column, by regexp -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/allout-widgets.el b/lisp/allout-widgets.el
index be9cf06c523..7f5831d4124 100644
--- a/lisp/allout-widgets.el
+++ b/lisp/allout-widgets.el
@@ -1,6 +1,6 @@
 ;;; allout-widgets.el --- Visually highlight allout outline structure.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Ken Manheimer <ken dot manheimer at gmail...>
 ;; Version: 1.0
diff --git a/lisp/allout.el b/lisp/allout.el
index d3203800168..a7121efb14a 100644
--- a/lisp/allout.el
+++ b/lisp/allout.el
@@ -1,11 +1,11 @@
 ;;; allout.el --- extensive outline mode for use alone and with other modes  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: Ken Manheimer <ken dot manheimer at gmail...>
 ;; Created: Dec 1991 -- first release to usenet
 ;; Version: 2.3
-;; Keywords: outlines, wp, languages, PGP, GnuPG
+;; Keywords: outlines, text, languages, PGP, GnuPG
 ;; Website: https://myriadicity.net/software-and-systems/craft/emacs-allout
 
 ;; This file is part of GNU Emacs.
@@ -6195,7 +6195,7 @@ for details on preparing Emacs for automatic allout 
activation."
       (allout-open-topic 2)
       (insert (substitute-command-keys
                (concat "Dummy outline topic header -- see"
-                       " `allout-mode' docstring: `\\[describe-mode]'.")))
+                       " `allout-mode' docstring: \\[describe-mode]")))
       (allout-adjust-file-variable
        "allout-layout" (or allout-layout '(-1 : 0))))))
 ;;;_   > allout-file-vars-section-data ()
diff --git a/lisp/ansi-color.el b/lisp/ansi-color.el
index 0461ced6956..1d053f718f8 100644
--- a/lisp/ansi-color.el
+++ b/lisp/ansi-color.el
@@ -1,6 +1,6 @@
 ;;; ansi-color.el --- translate ANSI escape sequences into faces -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <alex@gnu.org>
 ;; Version: 3.4.2
diff --git a/lisp/ansi-osc.el b/lisp/ansi-osc.el
index 886291a2c78..8dbaeb45132 100644
--- a/lisp/ansi-osc.el
+++ b/lisp/ansi-osc.el
@@ -1,6 +1,6 @@
 ;;; ansi-osc.el --- Support for OSC escape sequences      -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Augusto Stoffel <arstoffel@gmail.com>
 ;;         Matthias Meulien <orontee@gmail.com>
@@ -121,7 +121,8 @@ and `shell-dirtrack-mode'."
   (let ((url (url-generic-parse-url text)))
     (when (and (string= (url-type url) "file")
                (or (null (url-host url))
-                   (string= (url-host url) (system-name))))
+                   ;; Use `downcase' to match `url-generic-parse-url' behavior
+                   (string= (url-host url) (downcase (system-name)))))
       (ignore-errors
         (cd-absolute (url-unhex-string (url-filename url)))))))
 
diff --git a/lisp/apropos.el b/lisp/apropos.el
index 0e286f3069d..6c6cd0b593d 100644
--- a/lisp/apropos.el
+++ b/lisp/apropos.el
@@ -1,6 +1,6 @@
 ;;; apropos.el --- apropos commands for users and programmers  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1989-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989-2024 Free Software Foundation, Inc.
 
 ;; Author: Joe Wells <jbw@bigbird.bu.edu>
 ;;     Daniel Pfeiffer <occitan@esperanto.org> (rewrite)
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index c861c835966..9a8dd6679e3 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -1,6 +1,6 @@
 ;;; arc-mode.el --- simple editing of archives  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995, 1997-1998, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1995, 1997-1998, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Morten Welinder <terra@gnu.org>
@@ -2108,16 +2108,14 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
    (t
     (archive-extract-by-stdout
      archive
-     ;; unzip expands wildcards in NAME, so we need to quote it.  But
-     ;; not on DOS/Windows, since that fails extraction on those
-     ;; systems (unless w32-quote-process-args is nil), and file names
-     ;; with wildcards in zip archives don't work there anyway.
-     ;; FIXME: Does pkunzip need similar treatment?
-     (if (and (or (not (memq system-type '(windows-nt ms-dos)))
-                 (and (boundp 'w32-quote-process-args)
-                      (null w32-quote-process-args)))
-             (equal (car archive-zip-extract) "unzip"))
-        (shell-quote-argument name)
+     ;; unzip expands wildcard characters in NAME, so we need to quote
+     ;; wildcard characters in a special way: replace each such
+     ;; character C with a single-character alternative [C].  We
+     ;; cannot use 'shell-quote-argument' here because that doesn't
+     ;; protect wildcard characters from being expanded by unzip
+     ;; itself.
+     (if (equal (car archive-zip-extract) "unzip")
+         (replace-regexp-in-string "[[?*]" "[\\&]" name)
        name)
      archive-zip-extract))))
 
diff --git a/lisp/array.el b/lisp/array.el
index b2f961d187b..99e67be2d90 100644
--- a/lisp/array.el
+++ b/lisp/array.el
@@ -1,6 +1,6 @@
 ;;; array.el --- array editing commands for GNU Emacs  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1987, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: David M. Brown
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index 0f51755a250..03fd1f35811 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -1,6 +1,6 @@
 ;;; auth-source-pass.el --- Integrate auth-source with password-store -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015, 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Damien Cassou <damien@cassou.me>,
 ;;         Nicolas Petton <nicolas@petton.fr>
diff --git a/lisp/auth-source.el b/lisp/auth-source.el
index 583b6e57897..1f233f9f60f 100644
--- a/lisp/auth-source.el
+++ b/lisp/auth-source.el
@@ -1,6 +1,6 @@
 ;;; auth-source.el --- authentication sources for Gnus and Emacs -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Ted Zlatanov <tzz@lifelogs.com>
 ;; Keywords: news
@@ -233,8 +233,8 @@ EPA/EPG set up, the file will be encrypted and decrypted
 automatically.  See Info node `(epa)Encrypting/decrypting gpg files'
 for details.
 
-It's best to customize this with `\\[customize-variable]' because the choices
-can get pretty complex."
+It's best to customize this with \\[customize-variable] because
+the choices can get pretty complex."
   :version "26.1" ; neither new nor changed default
   :type `(repeat :tag "Authentication Sources"
                  (choice
@@ -330,7 +330,6 @@ If the value is not a list, symmetric encryption will be 
used."
 
 (defun auth-source-read-char-choice (prompt choices)
   "Read one of CHOICES by `read-char-choice', or `read-char'.
-`dropdown-list' support is disabled because it doesn't work reliably.
 Only one of CHOICES will be returned.  The PROMPT is augmented
 with \"[a/b/c] \" if CHOICES is \(?a ?b ?c)."
   (when choices
@@ -1946,18 +1945,20 @@ entries for git.gnus.org:
          (returned-keys (delete-dups (append
                                      '(:host :login :port :secret)
                                      search-keys)))
-         ;; Extract host and port from spec
+         ;; Extract host, port and user from spec
          (hosts (plist-get spec :host))
-         (hosts (if (and hosts (listp hosts)) hosts `(,hosts)))
+         (hosts (if (consp hosts) hosts `(,hosts)))
          (ports (plist-get spec :port))
-         (ports (if (and ports (listp ports)) ports `(,ports)))
+         (ports (if (consp ports) ports `(,ports)))
          (users (plist-get spec :user))
-         (users (if (and users (listp users)) users `(,users)))
+         (users (if (consp users) users `(,users)))
          ;; Loop through all combinations of host/port and pass each of these 
to
-         ;; auth-source-macos-keychain-search-items
+         ;; auth-source-macos-keychain-search-items.  Convert numeric port to
+         ;; string (bug#68376).
          (items (catch 'match
                   (dolist (host hosts)
                     (dolist (port ports)
+                      (when (numberp port) (setq port (number-to-string port)))
                       (dolist (user users)
                         (let ((items (apply
                                       #'auth-source-macos-keychain-search-items
@@ -2019,7 +2020,7 @@ entries for git.gnus.org:
     (when port
       (if keychain-generic
           (setq args (append args (list "-s" port)))
-        (setq args (append args (if (string-match "[0-9]+" port)
+        (setq args (append args (if (string-match-p "\\`[[:digit:]]+\\'" port)
                                     (list "-P" port)
                                   (list "-r" (substring
                                               (format "%-4s" port)
diff --git a/lisp/autoinsert.el b/lisp/autoinsert.el
index 3d95ce60ae3..f2631422c62 100644
--- a/lisp/autoinsert.el
+++ b/lisp/autoinsert.el
@@ -1,6 +1,6 @@
 ;;; autoinsert.el --- automatic mode-dependent insertion of text into new 
files  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Author: Charlie Martin <crm@cs.duke.edu>
 ;; Adapted-By: Daniel Pfeiffer <occitan@esperanto.org>
diff --git a/lisp/autorevert.el b/lisp/autorevert.el
index 23b7ca0a1d4..a23d536879d 100644
--- a/lisp/autorevert.el
+++ b/lisp/autorevert.el
@@ -1,6 +1,6 @@
 ;;; autorevert.el --- revert buffers when files on disk change  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1997-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Anders Lindgren
 ;; Keywords: convenience
diff --git a/lisp/avoid.el b/lisp/avoid.el
index eea6e88bd9b..c9b10ce3975 100644
--- a/lisp/avoid.el
+++ b/lisp/avoid.el
@@ -1,6 +1,6 @@
 ;;; avoid.el --- make mouse pointer stay out of the way of editing  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1993-1994, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Boris Goldowsky <boris@gnu.org>
 ;; Keywords: mouse
diff --git a/lisp/battery.el b/lisp/battery.el
index c55fcbbee8c..4aae3e0ef54 100644
--- a/lisp/battery.el
+++ b/lisp/battery.el
@@ -1,6 +1,6 @@
 ;;; battery.el --- display battery status information  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Ralph Schleicher <rs@ralph-schleicher.de>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/bind-key.el b/lisp/bind-key.el
index 3cff0f7f3a9..94a39f795cd 100644
--- a/lisp/bind-key.el
+++ b/lisp/bind-key.el
@@ -1,6 +1,6 @@
 ;;; bind-key.el --- A simple way to manage personal keybindings  -*- 
lexical-binding: t; -*-
 
-;; Copyright (c) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (c) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@newartisans.com>
 ;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/bindings.el b/lisp/bindings.el
index fab77669595..4690897fed4 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -1,6 +1,6 @@
 ;;; bindings.el --- define standard key bindings and some variables  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index 71d76cb4291..60dd61a5ac8 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -1,6 +1,6 @@
 ;;; bookmark.el --- set bookmarks, maybe annotate them, jump to them later -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1993-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Karl Fogel <kfogel@red-bean.com>
 ;; Created: July, 1993
@@ -142,7 +142,7 @@ Nil means don't prompt for confirmation."
   "Non-nil means show annotations when jumping to a bookmark."
   :type 'boolean)
 
-(defconst bookmark-bmenu-buffer "*Bookmark List*"
+(defvar bookmark-bmenu-buffer "*Bookmark List*"
   "Name of buffer used for Bookmark List.")
 
 (defvar bookmark-bmenu-use-header-line t
diff --git a/lisp/bs.el b/lisp/bs.el
index 70868591196..9db93ea0423 100644
--- a/lisp/bs.el
+++ b/lisp/bs.el
@@ -1,6 +1,6 @@
 ;;; bs.el --- menu for selecting and displaying buffers -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Olaf Sylvester <Olaf.Sylvester@netsurf.de>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el
index 29c981c1364..5796544c534 100644
--- a/lisp/buff-menu.el
+++ b/lisp/buff-menu.el
@@ -1,6 +1,6 @@
 ;;; buff-menu.el --- Interface for viewing and manipulating buffers -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: convenience
@@ -416,7 +416,7 @@ When called interactively prompt for MARK;  RET remove all 
marks."
 
 (defun Buffer-menu-delete (&optional arg)
   "Mark the buffer on this Buffer Menu buffer line for deletion.
-A subsequent \\<Buffer-menu-mode-map>`\\[Buffer-menu-execute]' command
+A subsequent \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command \
 will delete it.
 
 If prefix argument ARG is non-nil, it specifies the number of
@@ -437,16 +437,16 @@ buffers to delete; a negative ARG means to delete 
backwards."
 
 (defun Buffer-menu-delete-backwards (&optional arg)
   "Mark the buffer on this Buffer Menu line for deletion, and move up.
-A subsequent \\<Buffer-menu-mode-map>`\\[Buffer-menu-execute]'
-command will delete the marked buffer.  Prefix ARG means move
-that many lines."
+A subsequent \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] command \
+will delete the marked buffer.  Prefix ARG
+ means move that many lines."
   (interactive "p" Buffer-menu-mode)
   (Buffer-menu-delete (- (or arg 1))))
 
 (defun Buffer-menu-save ()
   "Mark the buffer on this Buffer Menu line for saving.
-A subsequent \\<Buffer-menu-mode-map>`\\[Buffer-menu-execute]' command
-will save it."
+A subsequent \\<Buffer-menu-mode-map>\\[Buffer-menu-execute] \
+command will save it."
   (interactive nil Buffer-menu-mode)
   (when (Buffer-menu-buffer)
     (tabulated-list-set-col 2 "S" t)
@@ -463,8 +463,8 @@ it as modified."
 
 (defun Buffer-menu-execute ()
   "Save and/or delete marked buffers in the Buffer Menu.
-Buffers marked with \\<Buffer-menu-mode-map>`\\[Buffer-menu-save]' are saved.
-Buffers marked with \\<Buffer-menu-mode-map>`\\[Buffer-menu-delete]' are 
deleted."
+Buffers marked with \\<Buffer-menu-mode-map>\\[Buffer-menu-save] are saved.
+Buffers marked with \\<Buffer-menu-mode-map>\\[Buffer-menu-delete] are 
deleted."
   (interactive nil Buffer-menu-mode)
   (save-excursion
     (Buffer-menu-beginning)
@@ -492,7 +492,7 @@ Buffers marked with 
\\<Buffer-menu-mode-map>`\\[Buffer-menu-delete]' are deleted
 
 (defun Buffer-menu-select ()
   "Select this line's buffer; also, display buffers marked with `>'.
-You can mark buffers with the \\<Buffer-menu-mode-map>`\\[Buffer-menu-mark]' 
command.
+You can mark buffers with the \\<Buffer-menu-mode-map>\\[Buffer-menu-mark] 
command.
 
 This command deletes and replaces all the previously existing windows
 in the selected frame, and will remove any marks."
diff --git a/lisp/button.el b/lisp/button.el
index ed11c9583d8..c0584729172 100644
--- a/lisp/button.el
+++ b/lisp/button.el
@@ -1,6 +1,6 @@
 ;;; button.el --- clickable buttons -*- lexical-binding: t -*-
 ;;
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Miles Bader <miles@gnu.org>
 ;; Keywords: extensions, hypermedia
@@ -494,7 +494,7 @@ pushing a button, use the `button-describe' command."
                (button-activate str t)
               (if (eq (car-safe pos) 'touchscreen-down)
                   ;; If touch-screen-track tap returns nil, then the
-                  ;; tap was cancelled.
+                  ;; tap was canceled.
                   (when (touch-screen-track-tap pos nil nil t)
                     (push-button (posn-point posn) t))
                 (push-button (posn-point posn) t))))))
diff --git a/lisp/calc/calc-aent.el b/lisp/calc/calc-aent.el
index 66ede3295ae..a21efc0238d 100644
--- a/lisp/calc/calc-aent.el
+++ b/lisp/calc/calc-aent.el
@@ -1,6 +1,6 @@
 ;;; calc-aent.el --- algebraic entry functions for Calc  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Gillespie <daveg@synaptics.com>
 
@@ -505,6 +505,7 @@ The value t means abort and give an error message.")
     ("⅝" "(5:8)") ; 5/8
     ("⅞" "(7:8)") ; 7/8
     ("⅟" "1:")    ; 1/...
+    ("⁄" ":")     ; arbitrary fractions of the form 123⁄456
     ;; superscripts
     ("⁰" "0")  ; 0
     ("¹" "1")  ; 1
@@ -547,22 +548,41 @@ The value t means abort and give an error message.")
   "₀₁₂₃₄₅₆₇₈₉₊₋₍₎" ; 0123456789+-()
   "A string consisting of the subscripts allowed by Calc.")
 
+(defvar math--read-preprocess-re-cache nil
+  "Cached regexp and tag: (REGEXP REPLACEMENTS SUPERSCRIPTS SUBSCRIPTS)")
+
 ;;;###autoload
 (defun math-read-preprocess-string (str)
   "Replace some substrings of STR by Calc equivalents."
-  (setq str
-        (replace-regexp-in-string (concat "[" math-read-superscripts "]+")
-                                  "^(\\&)" str))
-  (setq str
-        (replace-regexp-in-string (concat "[" math-read-subscripts "]+")
-                                  "_(\\&)" str))
-  (let ((rep-list math-read-replacement-list))
-    (while rep-list
-      (setq str
-            (replace-regexp-in-string (nth 0 (car rep-list))
-                                      (nth 1 (car rep-list)) str))
-      (setq rep-list (cdr rep-list))))
-  str)
+  (unless (and (eq (nth 1 math--read-preprocess-re-cache)
+                   math-read-replacement-list)
+               (eq (nth 2 math--read-preprocess-re-cache)
+                   math-read-superscripts)
+               (eq (nth 3 math--read-preprocess-re-cache)
+                   math-read-subscripts))
+    ;; Cache invalid, recompute.
+    (setq math--read-preprocess-re-cache
+          (list (rx-to-string
+                 `(or (or (+ (in ,math-read-superscripts))
+                          (group (+ (in ,math-read-subscripts))))
+                      (group (or ,@(mapcar #'car math-read-replacement-list))))
+                 t)
+                math-read-replacement-list
+                math-read-superscripts
+                math-read-subscripts)))
+  (replace-regexp-in-string
+   (nth 0 math--read-preprocess-re-cache)
+   (lambda (s)
+     (if (match-beginning 2)
+         (cadr (assoc s math-read-replacement-list))  ; not super/subscript
+       (concat (if (match-beginning 1) "_" "^")
+               "("
+               (mapconcat (lambda (c)
+                            (cadr (assoc (char-to-string c)
+                                         math-read-replacement-list)))
+                          s)
+               ")")))
+   str t))
 
 ;; The next few variables are local to math-read-exprs (and math-read-expr
 ;; in calc-ext.el), but are set in functions they call.
diff --git a/lisp/calc/calc-alg.el b/lisp/calc/calc-alg.el
index 95f7a34a4ae..81340b43221 100644
--- a/lisp/calc/calc-alg.el
+++ b/lisp/calc/calc-alg.el
@@ -1,6 +1,6 @@
 ;;; calc-alg.el --- algebraic functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-arith.el b/lisp/calc/calc-arith.el
index 54f0a5649a3..7ab642dd2c3 100644
--- a/lisp/calc/calc-arith.el
+++ b/lisp/calc/calc-arith.el
@@ -1,6 +1,6 @@
 ;;; calc-arith.el --- arithmetic functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-bin.el b/lisp/calc/calc-bin.el
index 16ebe7552f4..790528e428d 100644
--- a/lisp/calc/calc-bin.el
+++ b/lisp/calc/calc-bin.el
@@ -1,6 +1,6 @@
 ;;; calc-bin.el --- binary functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-comb.el b/lisp/calc/calc-comb.el
index a1ebd68f571..8e8a0aee9c2 100644
--- a/lisp/calc/calc-comb.el
+++ b/lisp/calc/calc-comb.el
@@ -1,6 +1,6 @@
 ;;; calc-comb.el --- combinatoric functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-cplx.el b/lisp/calc/calc-cplx.el
index 63e450d86bb..d5fe7a779f1 100644
--- a/lisp/calc/calc-cplx.el
+++ b/lisp/calc/calc-cplx.el
@@ -1,6 +1,6 @@
 ;;; calc-cplx.el --- Complex number functions for Calc  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-embed.el b/lisp/calc/calc-embed.el
index 284d68adeeb..dad3f6a0ce1 100644
--- a/lisp/calc/calc-embed.el
+++ b/lisp/calc/calc-embed.el
@@ -1,6 +1,6 @@
 ;;; calc-embed.el --- embed Calc in a buffer  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-ext.el b/lisp/calc/calc-ext.el
index 52c0fa4f69f..191149892a8 100644
--- a/lisp/calc/calc-ext.el
+++ b/lisp/calc/calc-ext.el
@@ -1,6 +1,6 @@
 ;;; calc-ext.el --- various extension functions for Calc  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-fin.el b/lisp/calc/calc-fin.el
index 30da613f988..b14e95703ce 100644
--- a/lisp/calc/calc-fin.el
+++ b/lisp/calc/calc-fin.el
@@ -1,6 +1,6 @@
 ;;; calc-fin.el --- financial functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-forms.el b/lisp/calc/calc-forms.el
index a75842ad172..c5d050444e3 100644
--- a/lisp/calc/calc-forms.el
+++ b/lisp/calc/calc-forms.el
@@ -1,6 +1,6 @@
 ;;; calc-forms.el --- data format conversion functions for Calc  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-frac.el b/lisp/calc/calc-frac.el
index b57c1d6c760..d067ccc82fe 100644
--- a/lisp/calc/calc-frac.el
+++ b/lisp/calc/calc-frac.el
@@ -1,6 +1,6 @@
 ;;; calc-frac.el --- fraction functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-funcs.el b/lisp/calc/calc-funcs.el
index cb9f7887ddc..62ac27c6dbd 100644
--- a/lisp/calc/calc-funcs.el
+++ b/lisp/calc/calc-funcs.el
@@ -1,6 +1,6 @@
 ;;; calc-funcs.el --- well-known functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-graph.el b/lisp/calc/calc-graph.el
index 1b9d25daf3b..fb817b1bc3d 100644
--- a/lisp/calc/calc-graph.el
+++ b/lisp/calc/calc-graph.el
@@ -1,6 +1,6 @@
 ;;; calc-graph.el --- graph output functions for Calc  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-help.el b/lisp/calc/calc-help.el
index 6b3e5cd64b1..6ba49137b73 100644
--- a/lisp/calc/calc-help.el
+++ b/lisp/calc/calc-help.el
@@ -1,6 +1,6 @@
 ;;; calc-help.el --- help display functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-incom.el b/lisp/calc/calc-incom.el
index 16cb991dfa6..d94c8a99593 100644
--- a/lisp/calc/calc-incom.el
+++ b/lisp/calc/calc-incom.el
@@ -1,6 +1,6 @@
 ;;; calc-incom.el --- complex data type input functions for Calc  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-keypd.el b/lisp/calc/calc-keypd.el
index 060099b8892..1e079bba37f 100644
--- a/lisp/calc/calc-keypd.el
+++ b/lisp/calc/calc-keypd.el
@@ -1,6 +1,6 @@
 ;;; calc-keypd.el --- mouse-capable keypad input for Calc  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-lang.el b/lisp/calc/calc-lang.el
index f2d8aaa20a7..94133efdca9 100644
--- a/lisp/calc/calc-lang.el
+++ b/lisp/calc/calc-lang.el
@@ -1,6 +1,6 @@
 ;;; calc-lang.el --- calc language functions  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-macs.el b/lisp/calc/calc-macs.el
index 9421f74a8ed..ffb876dd45f 100644
--- a/lisp/calc/calc-macs.el
+++ b/lisp/calc/calc-macs.el
@@ -1,6 +1,6 @@
 ;;; calc-macs.el --- important macros for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-map.el b/lisp/calc/calc-map.el
index 7496537494b..f8dad435c75 100644
--- a/lisp/calc/calc-map.el
+++ b/lisp/calc/calc-map.el
@@ -1,6 +1,6 @@
 ;;; calc-map.el --- higher-order functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-math.el b/lisp/calc/calc-math.el
index 7b4c14efad0..64820149eff 100644
--- a/lisp/calc/calc-math.el
+++ b/lisp/calc/calc-math.el
@@ -1,6 +1,6 @@
 ;;; calc-math.el --- mathematical functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-menu.el b/lisp/calc/calc-menu.el
index bc6bb761f26..2329803d76e 100644
--- a/lisp/calc/calc-menu.el
+++ b/lisp/calc/calc-menu.el
@@ -1,6 +1,6 @@
 ;;; calc-menu.el --- a menu for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/calc/calc-misc.el b/lisp/calc/calc-misc.el
index 4b1aab837af..8c692ac006c 100644
--- a/lisp/calc/calc-misc.el
+++ b/lisp/calc/calc-misc.el
@@ -1,6 +1,6 @@
 ;;; calc-misc.el --- miscellaneous functions for Calc  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-mode.el b/lisp/calc/calc-mode.el
index 71a0171e7de..32ce4123e98 100644
--- a/lisp/calc/calc-mode.el
+++ b/lisp/calc/calc-mode.el
@@ -1,6 +1,6 @@
 ;;; calc-mode.el --- calculator modes for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-mtx.el b/lisp/calc/calc-mtx.el
index 0a5f2a2c208..3ce2f9dff2b 100644
--- a/lisp/calc/calc-mtx.el
+++ b/lisp/calc/calc-mtx.el
@@ -1,6 +1,6 @@
 ;;; calc-mtx.el --- matrix functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-nlfit.el b/lisp/calc/calc-nlfit.el
index 72b906ff69b..6dd3f3e7f63 100644
--- a/lisp/calc/calc-nlfit.el
+++ b/lisp/calc/calc-nlfit.el
@@ -1,6 +1,6 @@
 ;;; calc-nlfit.el --- nonlinear curve fitting for Calc  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/calc/calc-poly.el b/lisp/calc/calc-poly.el
index c32b5be5849..c5a7ee66cc8 100644
--- a/lisp/calc/calc-poly.el
+++ b/lisp/calc/calc-poly.el
@@ -1,6 +1,6 @@
 ;;; calc-poly.el --- polynomial functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-prog.el b/lisp/calc/calc-prog.el
index 8502b5196d2..03210995eb3 100644
--- a/lisp/calc/calc-prog.el
+++ b/lisp/calc/calc-prog.el
@@ -1,6 +1,6 @@
 ;;; calc-prog.el --- user programmability functions for Calc  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-rewr.el b/lisp/calc/calc-rewr.el
index b7b3b7b16d4..cc70ded17c2 100644
--- a/lisp/calc/calc-rewr.el
+++ b/lisp/calc/calc-rewr.el
@@ -1,6 +1,6 @@
 ;;; calc-rewr.el --- rewriting functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-rules.el b/lisp/calc/calc-rules.el
index 2d012d7ff63..da34c03ad05 100644
--- a/lisp/calc/calc-rules.el
+++ b/lisp/calc/calc-rules.el
@@ -1,6 +1,6 @@
 ;;; calc-rules.el --- rules for simplifying algebraic expressions in Calc  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-sel.el b/lisp/calc/calc-sel.el
index 8d020d02aa7..1a14cd418c3 100644
--- a/lisp/calc/calc-sel.el
+++ b/lisp/calc/calc-sel.el
@@ -1,6 +1,6 @@
 ;;; calc-sel.el --- data selection functions for Calc  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-stat.el b/lisp/calc/calc-stat.el
index bc5d575f257..e4f101acf19 100644
--- a/lisp/calc/calc-stat.el
+++ b/lisp/calc/calc-stat.el
@@ -1,6 +1,6 @@
 ;;; calc-stat.el --- statistical functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-store.el b/lisp/calc/calc-store.el
index 97d1a76d0dc..df584760606 100644
--- a/lisp/calc/calc-store.el
+++ b/lisp/calc/calc-store.el
@@ -1,6 +1,6 @@
 ;;; calc-store.el --- value storage functions for Calc  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-stuff.el b/lisp/calc/calc-stuff.el
index 595fef85224..8ecb208138c 100644
--- a/lisp/calc/calc-stuff.el
+++ b/lisp/calc/calc-stuff.el
@@ -1,6 +1,6 @@
 ;;; calc-stuff.el --- miscellaneous functions for Calc  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-trail.el b/lisp/calc/calc-trail.el
index 945de4ae493..6678bc6bfc1 100644
--- a/lisp/calc/calc-trail.el
+++ b/lisp/calc/calc-trail.el
@@ -1,6 +1,6 @@
 ;;; calc-trail.el --- functions for manipulating the Calc "trail"  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-undo.el b/lisp/calc/calc-undo.el
index cb6254f4ab6..65db157759b 100644
--- a/lisp/calc/calc-undo.el
+++ b/lisp/calc/calc-undo.el
@@ -1,6 +1,6 @@
 ;;; calc-undo.el --- undo functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-units.el b/lisp/calc/calc-units.el
index 05a603c3f56..fba2b9c50fb 100644
--- a/lisp/calc/calc-units.el
+++ b/lisp/calc/calc-units.el
@@ -1,6 +1,6 @@
 ;;; calc-units.el --- unit conversion functions for Calc  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-vec.el b/lisp/calc/calc-vec.el
index 90239d58808..39ac6fa0347 100644
--- a/lisp/calc/calc-vec.el
+++ b/lisp/calc/calc-vec.el
@@ -1,6 +1,6 @@
 ;;; calc-vec.el --- vector functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc-yank.el b/lisp/calc/calc-yank.el
index a2a91dc8fb8..0f9e8f09019 100644
--- a/lisp/calc/calc-yank.el
+++ b/lisp/calc/calc-yank.el
@@ -1,6 +1,6 @@
 ;;; calc-yank.el --- kill-ring functionality for Calc  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el
index 41aeb17c252..e6448625cee 100644
--- a/lisp/calc/calc.el
+++ b/lisp/calc/calc.el
@@ -1,6 +1,6 @@
 ;;; calc.el --- the GNU Emacs calculator  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 ;; Keywords: convenience, extensions
@@ -1285,6 +1285,8 @@ the trail buffer."
           (setq calc-trail-buffer nil)
           t))))
 
+(defvar touch-screen-display-keyboard)
+
 (defun calc-mode ()
   "Calculator major mode.
 
diff --git a/lisp/calc/calcalg2.el b/lisp/calc/calcalg2.el
index e60c4539608..5e9ae8a3e5a 100644
--- a/lisp/calc/calcalg2.el
+++ b/lisp/calc/calcalg2.el
@@ -1,6 +1,6 @@
 ;;; calcalg2.el --- more algebraic functions for Calc  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calcalg3.el b/lisp/calc/calcalg3.el
index af0daa55309..26952b8b10c 100644
--- a/lisp/calc/calcalg3.el
+++ b/lisp/calc/calcalg3.el
@@ -1,6 +1,6 @@
 ;;; calcalg3.el --- more algebraic functions for Calc  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calccomp.el b/lisp/calc/calccomp.el
index c42e62853ed..9d9e9383c32 100644
--- a/lisp/calc/calccomp.el
+++ b/lisp/calc/calccomp.el
@@ -1,6 +1,6 @@
 ;;; calccomp.el --- composition functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calc/calcsel2.el b/lisp/calc/calcsel2.el
index 8935511db6e..bf62b7e1447 100644
--- a/lisp/calc/calcsel2.el
+++ b/lisp/calc/calcsel2.el
@@ -1,6 +1,6 @@
 ;;; calcsel2.el --- selection functions for Calc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Gillespie <daveg@synaptics.com>
 
diff --git a/lisp/calculator.el b/lisp/calculator.el
index 00afa2457fe..ef1e6d8dbc3 100644
--- a/lisp/calculator.el
+++ b/lisp/calculator.el
@@ -1,6 +1,6 @@
 ;;; calculator.el --- a calculator for Emacs  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Eli Barzilay <eli@barzilay.org>
 ;; Keywords: tools, convenience
diff --git a/lisp/calendar/appt.el b/lisp/calendar/appt.el
index c761bb6a89d..7572e706283 100644
--- a/lisp/calendar/appt.el
+++ b/lisp/calendar/appt.el
@@ -1,6 +1,6 @@
 ;;; appt.el --- appointment notification functions  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1989-1990, 1994, 1998, 2001-2023 Free Software
+;; Copyright (C) 1989-1990, 1994, 1998, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Neil Mager <neilm@juliet.ll.mit.edu>
diff --git a/lisp/calendar/cal-bahai.el b/lisp/calendar/cal-bahai.el
index 202c38916a9..0934f926d53 100644
--- a/lisp/calendar/cal-bahai.el
+++ b/lisp/calendar/cal-bahai.el
@@ -1,6 +1,6 @@
 ;;; cal-bahai.el --- calendar functions for the Bahá’í calendar.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Keywords: calendar
diff --git a/lisp/calendar/cal-china.el b/lisp/calendar/cal-china.el
index b31d056941c..8145b99182e 100644
--- a/lisp/calendar/cal-china.el
+++ b/lisp/calendar/cal-china.el
@@ -1,6 +1,6 @@
 ;;; cal-china.el --- calendar functions for the Chinese calendar  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-coptic.el b/lisp/calendar/cal-coptic.el
index 123b1f11f55..1700d1c262b 100644
--- a/lisp/calendar/cal-coptic.el
+++ b/lisp/calendar/cal-coptic.el
@@ -1,6 +1,6 @@
 ;;; cal-coptic.el --- calendar functions for the Coptic/Ethiopic calendars  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-dst.el b/lisp/calendar/cal-dst.el
index a96fb0adf7c..b54738c464f 100644
--- a/lisp/calendar/cal-dst.el
+++ b/lisp/calendar/cal-dst.el
@@ -1,6 +1,6 @@
 ;;; cal-dst.el --- calendar functions for daylight saving rules  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1993-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Paul Eggert <eggert@cs.ucla.edu>
 ;;         Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/cal-french.el b/lisp/calendar/cal-french.el
index cc523c28f49..fcc0d44c7c8 100644
--- a/lisp/calendar/cal-french.el
+++ b/lisp/calendar/cal-french.el
@@ -1,6 +1,6 @@
 ;;; cal-french.el --- calendar functions for the French Revolutionary calendar 
 -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1988-1989, 1992, 1994-1995, 1997, 2001-2023 Free
+;; Copyright (C) 1988-1989, 1992, 1994-1995, 1997, 2001-2024 Free
 ;; Software Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/cal-hebrew.el b/lisp/calendar/cal-hebrew.el
index b6c60185029..fea8e957e46 100644
--- a/lisp/calendar/cal-hebrew.el
+++ b/lisp/calendar/cal-hebrew.el
@@ -1,6 +1,6 @@
 ;;; cal-hebrew.el --- calendar functions for the Hebrew calendar  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Nachum Dershowitz <nachum@cs.uiuc.edu>
 ;;         Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/cal-html.el b/lisp/calendar/cal-html.el
index c85c476a109..919b3d5918f 100644
--- a/lisp/calendar/cal-html.el
+++ b/lisp/calendar/cal-html.el
@@ -1,6 +1,6 @@
 ;;; cal-html.el --- functions for printing HTML calendars  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Anna M. Bigatti <bigatti@dima.unige.it>
 ;; Keywords: calendar
diff --git a/lisp/calendar/cal-islam.el b/lisp/calendar/cal-islam.el
index 172e54edca6..9fb3fd631bd 100644
--- a/lisp/calendar/cal-islam.el
+++ b/lisp/calendar/cal-islam.el
@@ -1,6 +1,6 @@
 ;;; cal-islam.el --- calendar functions for the Islamic calendar  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-iso.el b/lisp/calendar/cal-iso.el
index a4a3e585745..37b3f1d93cc 100644
--- a/lisp/calendar/cal-iso.el
+++ b/lisp/calendar/cal-iso.el
@@ -1,6 +1,6 @@
 ;;; cal-iso.el --- calendar functions for the ISO calendar  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-julian.el b/lisp/calendar/cal-julian.el
index f45150455b0..1ae4049890e 100644
--- a/lisp/calendar/cal-julian.el
+++ b/lisp/calendar/cal-julian.el
@@ -1,6 +1,6 @@
 ;;; cal-julian.el --- calendar functions for the Julian calendar  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-mayan.el b/lisp/calendar/cal-mayan.el
index 8ec867454ff..e62e9d10ccf 100644
--- a/lisp/calendar/cal-mayan.el
+++ b/lisp/calendar/cal-mayan.el
@@ -1,6 +1,6 @@
 ;;; cal-mayan.el --- calendar functions for the Mayan calendars  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1992-1993, 1995, 1997, 2001-2023 Free Software
+;; Copyright (C) 1992-1993, 1995, 1997, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Stewart M. Clamen <clamen@cs.cmu.edu>
diff --git a/lisp/calendar/cal-menu.el b/lisp/calendar/cal-menu.el
index edf5534581c..b63c931f7c6 100644
--- a/lisp/calendar/cal-menu.el
+++ b/lisp/calendar/cal-menu.el
@@ -1,6 +1,6 @@
 ;;; cal-menu.el --- calendar functions for menu bar and popup menu support  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1994-1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
 ;;         Lara Rios <lrios@coewl.cen.uiuc.edu>
diff --git a/lisp/calendar/cal-move.el b/lisp/calendar/cal-move.el
index b494659a8ee..4a486d1cde7 100644
--- a/lisp/calendar/cal-move.el
+++ b/lisp/calendar/cal-move.el
@@ -1,6 +1,6 @@
 ;;; cal-move.el --- calendar functions for movement in the calendar  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-persia.el b/lisp/calendar/cal-persia.el
index 822f2153c50..d01881f0a13 100644
--- a/lisp/calendar/cal-persia.el
+++ b/lisp/calendar/cal-persia.el
@@ -1,6 +1,6 @@
 ;;; cal-persia.el --- calendar functions for the Persian calendar  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-tex.el b/lisp/calendar/cal-tex.el
index 8399d77b4c4..ea396329e4c 100644
--- a/lisp/calendar/cal-tex.el
+++ b/lisp/calendar/cal-tex.el
@@ -1,6 +1,6 @@
 ;;; cal-tex.el --- calendar functions for printing calendars with LaTeX  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Steve Fisk <fisk@bowdoin.edu>
 ;;         Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/cal-x.el b/lisp/calendar/cal-x.el
index 58eea324e82..1e1e2613d80 100644
--- a/lisp/calendar/cal-x.el
+++ b/lisp/calendar/cal-x.el
@@ -1,6 +1,6 @@
 ;;; cal-x.el --- calendar windows in dedicated frames  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1994-1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;;         Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el
index 02167d84b3e..2c3e7d28301 100644
--- a/lisp/calendar/calendar.el
+++ b/lisp/calendar/calendar.el
@@ -1,6 +1,6 @@
 ;;; calendar.el --- calendar functions  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1988-1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1988-1995, 1997, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
@@ -2337,10 +2337,12 @@ returned is (month year)."
          (defmon (aref month-array (1- (calendar-extract-month default-date))))
          (completion-ignore-case t)
          (month (cdr (assoc-string
-                      (completing-read
-                       (format-prompt "Month name" defmon)
-                       (append month-array nil)
-                       nil t nil nil defmon)
+                      (let ((completion-extra-properties
+                             '(:category calendar-month)))
+                        (completing-read
+                         (format-prompt "Month name" defmon)
+                         (append month-array nil)
+                         nil t nil nil defmon))
                       (calendar-make-alist month-array 1) t)))
          (defday (calendar-extract-day default-date))
          (last (calendar-last-day-of-month month year)))
diff --git a/lisp/calendar/diary-lib.el b/lisp/calendar/diary-lib.el
index 0d894f10013..63bbae4d8ed 100644
--- a/lisp/calendar/diary-lib.el
+++ b/lisp/calendar/diary-lib.el
@@ -1,6 +1,6 @@
 ;;; diary-lib.el --- diary functions  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1989-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989-2024 Free Software Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/holidays.el b/lisp/calendar/holidays.el
index a65beca0e5b..c7499938c6a 100644
--- a/lisp/calendar/holidays.el
+++ b/lisp/calendar/holidays.el
@@ -1,6 +1,6 @@
 ;;; holidays.el --- holiday functions for the calendar package  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1989-1990, 1992-1994, 1997, 2001-2023 Free Software
+;; Copyright (C) 1989-1990, 1992-1994, 1997, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el
index 51e6a7d1170..d7e62e1baf3 100644
--- a/lisp/calendar/icalendar.el
+++ b/lisp/calendar/icalendar.el
@@ -1,8 +1,9 @@
 ;;; icalendar.el --- iCalendar implementation -*- lexical-binding: t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author:         Ulf Jasper <ulf.jasper@web.de>
+;; Maintainer:     emacs-devel@gnu.org
 ;; Created:        August 2002
 ;; Keywords:       calendar
 ;; Human-Keywords: calendar, diary, iCalendar, vCalendar
diff --git a/lisp/calendar/iso8601.el b/lisp/calendar/iso8601.el
index d7d064d9c2a..a32b52564c9 100644
--- a/lisp/calendar/iso8601.el
+++ b/lisp/calendar/iso8601.el
@@ -1,6 +1,6 @@
 ;;; iso8601.el --- parse ISO 8601 date/time strings  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Keywords: dates
 
diff --git a/lisp/calendar/lunar.el b/lisp/calendar/lunar.el
index a9c3597a3f9..87c47304c24 100644
--- a/lisp/calendar/lunar.el
+++ b/lisp/calendar/lunar.el
@@ -1,6 +1,6 @@
 ;;; lunar.el --- calendar functions for phases of the moon  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1992-1993, 1995, 1997, 2001-2023 Free Software
+;; Copyright (C) 1992-1993, 1995, 1997, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/parse-time.el b/lisp/calendar/parse-time.el
index a62361121fc..c34329a4002 100644
--- a/lisp/calendar/parse-time.el
+++ b/lisp/calendar/parse-time.el
@@ -1,6 +1,6 @@
 ;;; parse-time.el --- parsing time strings -*- lexical-binding: t -*-
 
-;; Copyright (C) 1996, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Erik Naggum <erik@naggum.no>
 ;; Keywords: util
diff --git a/lisp/calendar/solar.el b/lisp/calendar/solar.el
index d82215a6d35..ecb3a47be71 100644
--- a/lisp/calendar/solar.el
+++ b/lisp/calendar/solar.el
@@ -1,6 +1,6 @@
 ;;; solar.el --- calendar functions for solar events  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1992-1993, 1995, 1997, 2001-2023 Free Software
+;; Copyright (C) 1992-1993, 1995, 1997, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el
index 319d1d1b91c..e96e2e7e2db 100644
--- a/lisp/calendar/time-date.el
+++ b/lisp/calendar/time-date.el
@@ -1,6 +1,6 @@
 ;;; time-date.el --- Date and time handling functions  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     Masanobu Umeda <umerin@mse.kyutech.ac.jp>
@@ -408,6 +408,7 @@ right of \"%x\", trailing zero units are not output."
   "Formatting used by the function `seconds-to-string'.")
 ;;;###autoload
 (defun seconds-to-string (delay)
+  ;; FIXME: There's a similar (tho fancier) function in mastodon.el!
   "Convert the time interval in seconds to a short string."
   (cond ((> 0 delay) (concat "-" (seconds-to-string (- delay))))
         ((= 0 delay) "0s")
diff --git a/lisp/calendar/timeclock.el b/lisp/calendar/timeclock.el
index 7606805a99b..cc5d19522bd 100644
--- a/lisp/calendar/timeclock.el
+++ b/lisp/calendar/timeclock.el
@@ -1,6 +1,6 @@
 ;;; timeclock.el --- mode for keeping track of how much you work  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Created: 25 Mar 1999
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el
index ab9d629d9fc..f2ee94ec8f7 100644
--- a/lisp/calendar/todo-mode.el
+++ b/lisp/calendar/todo-mode.el
@@ -1,6 +1,6 @@
 ;;; todo-mode.el --- facilities for making and maintaining todo lists  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Oliver Seidel <privat@os10000.net>
 ;;     Stephen Berman <stephen.berman@gmx.net>
@@ -677,7 +677,7 @@ current (i.e., last displayed) category.
 
 In Todo mode just the category's unfinished todo items are shown
 by default.  The done items are hidden, but typing
-`\\[todo-toggle-view-done-items]' displays them below the todo
+\\[todo-toggle-view-done-items] displays them below the todo
 items.  With non-nil user option `todo-show-with-done' both todo
 and done items are always shown on visiting a category."
   (interactive "P\np")
@@ -1553,7 +1553,7 @@ the archive of the file moved to, creating it if it does 
not exist."
                 (prin1 todo-categories (current-buffer)))
              ;; If archive was just created, save it to avoid "File
              ;; <xyz> no longer exists!" message on invoking
-             ;; `todo-view-archived-items'.
+             ;; `todo-find-archive'.
              (unless (file-exists-p (buffer-file-name))
                (save-buffer))
              (todo-category-number (or new cat))
@@ -3570,12 +3570,12 @@ categories display according to priority."
 
 In the initial display the lines of the table are numbered,
 indicating the current order of the categories when sequentially
-navigating through the todo file with `\\[todo-forward-category]'
-and `\\[todo-backward-category]'.  You can reorder the lines, and
-hence the category sequence, by typing `\\[todo-raise-category]'
-or `\\[todo-lower-category]' to raise or lower the category at
-point, or by typing `\\[todo-set-category-number]' and entering a
-number at the prompt or by typing `\\[todo-set-category-number]'
+navigating through the todo file with \\[todo-forward-category]
+and \\[todo-backward-category].  You can reorder the lines, and
+hence the category sequence, by typing \\[todo-raise-category]
+or \\[todo-lower-category] to raise or lower the category at
+point, or by typing \\[todo-set-category-number] and entering a
+number at the prompt or by typing \\[todo-set-category-number]
 with a numeric prefix.  If you save the todo file after
 reordering the categories, the new order persists in subsequent
 Emacs sessions.
@@ -3584,8 +3584,8 @@ The labels above the category names and item counts are 
buttons,
 and clicking these changes the display: sorted by category name
 or by the respective item counts (alternately descending or
 ascending).  In these displays the categories are not numbered
-and `\\[todo-set-category-number]', `\\[todo-raise-category]' and
-`\\[todo-lower-category]' are disabled.  (Programmatically, the
+and \\[todo-set-category-number], \\[todo-raise-category] and
+\\[todo-lower-category] are disabled.  (Programmatically, the
 sorting is triggered by passing a non-nil SORTKEY argument.)
 
 In addition, the lines with the category names and item counts
@@ -4065,8 +4065,8 @@ face."
 (defcustom todo-top-priorities-overrides nil
   "List of rules specifying number of top priority items to show.
 These rules override `todo-top-priorities' on invocations of
-`\\[todo-filter-top-priorities]' and
-`\\[todo-filter-top-priorities-multifile]'.  Each rule is a list
+\\[todo-filter-top-priorities] and
+\\[todo-filter-top-priorities-multifile].  Each rule is a list
 of the form (FILE NUM ALIST), where FILE is a member of
 `todo-files', NUM is a number specifying the default number of
 top priority items for each category in that file, and ALIST,
@@ -4075,8 +4075,8 @@ number specifying the default number of top priority 
items in
 that category, which overrides NUM.
 
 This variable should be set interactively by
-`\\[todo-set-top-priorities-in-file]' or
-`\\[todo-set-top-priorities-in-category]'."
+\\[todo-set-top-priorities-in-file] or
+\\[todo-set-top-priorities-in-category]."
   :type 'sexp
   :group 'todo-filtered)
 
diff --git a/lisp/case-table.el b/lisp/case-table.el
index f5cfbae2c9c..b7c1719743e 100644
--- a/lisp/case-table.el
+++ b/lisp/case-table.el
@@ -1,6 +1,6 @@
 ;;; case-table.el --- code to extend the character set and support case tables 
 -*- lexical-binding: t -*-
 
-;; Copyright (C) 1988, 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Howard Gayle
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/cdl.el b/lisp/cdl.el
index 57504f4dae0..38a1bea9c31 100644
--- a/lisp/cdl.el
+++ b/lisp/cdl.el
@@ -1,6 +1,6 @@
 ;;; cdl.el --- Common Data Language (CDL) utility functions for GNU Emacs -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Ata Etemadi <ATAE@spva.physics.imperial.ac.uk>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/cedet/ChangeLog.1 b/lisp/cedet/ChangeLog.1
index 5242c73062b..3f72bda75af 100644
--- a/lisp/cedet/ChangeLog.1
+++ b/lisp/cedet/ChangeLog.1
@@ -1515,7 +1515,7 @@
        * semantic/complete.el (semantic-complete-post-command-hook):
        Exit completion when user has deleted all characters from the prefix.
        (semantic-displayor-focus-request): Return to previous window when
-       focussing tags.
+       focusing tags.
 
        * semantic/db-el.el (semanticdb-normalize-one-tag): Make obsolete.
        (semanticdb-elisp-sym->tag): Use help-function-arglist instead.
@@ -3459,7 +3459,7 @@
 ;; coding: utf-8
 ;; End:
 
-       Copyright (C) 2009-2023 Free Software Foundation, Inc.
+       Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/cedet/cedet-cscope.el b/lisp/cedet/cedet-cscope.el
index da86847a8f2..02e79db64ef 100644
--- a/lisp/cedet/cedet-cscope.el
+++ b/lisp/cedet/cedet-cscope.el
@@ -1,6 +1,6 @@
 ;;; cedet-cscope.el --- CScope support for CEDET  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Package: cedet
diff --git a/lisp/cedet/cedet-files.el b/lisp/cedet/cedet-files.el
index 1c82b7165a9..236ee5df0e9 100644
--- a/lisp/cedet/cedet-files.el
+++ b/lisp/cedet/cedet-files.el
@@ -1,6 +1,6 @@
 ;;; cedet-files.el --- Common routines dealing with file names.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Package: cedet
diff --git a/lisp/cedet/cedet-global.el b/lisp/cedet/cedet-global.el
index 7d502cf60a2..3294a88d2c1 100644
--- a/lisp/cedet/cedet-global.el
+++ b/lisp/cedet/cedet-global.el
@@ -1,6 +1,6 @@
 ;;; cedet-global.el --- GNU Global support for CEDET.  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Package: cedet
diff --git a/lisp/cedet/cedet-idutils.el b/lisp/cedet/cedet-idutils.el
index e82ffd0990c..41b4d64238f 100644
--- a/lisp/cedet/cedet-idutils.el
+++ b/lisp/cedet/cedet-idutils.el
@@ -1,6 +1,6 @@
 ;;; cedet-idutils.el --- ID Utils support for CEDET.  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Old-Version: 0.2
diff --git a/lisp/cedet/cedet.el b/lisp/cedet/cedet.el
index 337a5be1cd8..28208e39285 100644
--- a/lisp/cedet/cedet.el
+++ b/lisp/cedet/cedet.el
@@ -1,6 +1,6 @@
 ;;; cedet.el --- Setup CEDET environment  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 ;; Maintainer: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/data-debug.el b/lisp/cedet/data-debug.el
index 837d75ea158..83ff451fa99 100644
--- a/lisp/cedet/data-debug.el
+++ b/lisp/cedet/data-debug.el
@@ -1,6 +1,6 @@
 ;;; data-debug.el --- Data structure debugger  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Old-Version: 0.2
diff --git a/lisp/cedet/ede.el b/lisp/cedet/ede.el
index 272633f5cac..b5993f9faac 100644
--- a/lisp/cedet/ede.el
+++ b/lisp/cedet/ede.el
@@ -1,6 +1,6 @@
 ;;; ede.el --- Emacs Development Environment gloss  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
diff --git a/lisp/cedet/ede/auto.el b/lisp/cedet/ede/auto.el
index 901fe958560..d923809b2e2 100644
--- a/lisp/cedet/ede/auto.el
+++ b/lisp/cedet/ede/auto.el
@@ -1,6 +1,6 @@
 ;;; ede/auto.el --- Autoload features for EDE  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/autoconf-edit.el b/lisp/cedet/ede/autoconf-edit.el
index 6663dd03576..d1cfdeb44d8 100644
--- a/lisp/cedet/ede/autoconf-edit.el
+++ b/lisp/cedet/ede/autoconf-edit.el
@@ -1,6 +1,6 @@
 ;;; ede/autoconf-edit.el --- Keymap for autoconf  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2000, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2000, 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project
diff --git a/lisp/cedet/ede/base.el b/lisp/cedet/ede/base.el
index c32d2edd7b7..91dd0a4749b 100644
--- a/lisp/cedet/ede/base.el
+++ b/lisp/cedet/ede/base.el
@@ -1,6 +1,6 @@
 ;;; ede/base.el --- Baseclasses for EDE  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/config.el b/lisp/cedet/ede/config.el
index 39a65d6e393..a27b336dc93 100644
--- a/lisp/cedet/ede/config.el
+++ b/lisp/cedet/ede/config.el
@@ -1,6 +1,6 @@
 ;;; ede/config.el --- Configuration Handler baseclass  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/cpp-root.el b/lisp/cedet/ede/cpp-root.el
index d30f45f8619..795d5189567 100644
--- a/lisp/cedet/ede/cpp-root.el
+++ b/lisp/cedet/ede/cpp-root.el
@@ -1,6 +1,6 @@
 ;;; ede/cpp-root.el --- A simple way to wrap a C++ project with a single root  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/custom.el b/lisp/cedet/ede/custom.el
index 81edaa01ad4..959437d1c5d 100644
--- a/lisp/cedet/ede/custom.el
+++ b/lisp/cedet/ede/custom.el
@@ -1,6 +1,6 @@
 ;;; ede/custom.el --- customization of EDE projects.  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/detect.el b/lisp/cedet/ede/detect.el
index 445b540e826..0da5dc71be3 100644
--- a/lisp/cedet/ede/detect.el
+++ b/lisp/cedet/ede/detect.el
@@ -1,6 +1,6 @@
 ;;; ede/detect.el --- EDE project detection and file associations  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/dired.el b/lisp/cedet/ede/dired.el
index 850b1b2b5e2..fbfd9111dc0 100644
--- a/lisp/cedet/ede/dired.el
+++ b/lisp/cedet/ede/dired.el
@@ -1,6 +1,6 @@
 ;;; ede/dired.el --- EDE extensions to dired.  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1998-2000, 2003, 2009-2023 Free Software Foundation,
+;; Copyright (C) 1998-2000, 2003, 2009-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/emacs.el b/lisp/cedet/ede/emacs.el
index 4ae16f6226e..e2d228e7e83 100644
--- a/lisp/cedet/ede/emacs.el
+++ b/lisp/cedet/ede/emacs.el
@@ -1,6 +1,6 @@
 ;;; ede/emacs.el --- Special project for Emacs  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/files.el b/lisp/cedet/ede/files.el
index 28dc788c736..4dbe498877e 100644
--- a/lisp/cedet/ede/files.el
+++ b/lisp/cedet/ede/files.el
@@ -1,6 +1,6 @@
 ;;; ede/files.el --- Associate projects with files and directories.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/generic.el b/lisp/cedet/ede/generic.el
index c3e6d5ef520..c3e8b9eb761 100644
--- a/lisp/cedet/ede/generic.el
+++ b/lisp/cedet/ede/generic.el
@@ -1,6 +1,6 @@
 ;;; ede/generic.el --- Base Support for generic build systems  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/linux.el b/lisp/cedet/ede/linux.el
index 0208475a8c7..234059dc26f 100644
--- a/lisp/cedet/ede/linux.el
+++ b/lisp/cedet/ede/linux.el
@@ -1,6 +1,6 @@
 ;;; ede/linux.el --- Special project for Linux  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/locate.el b/lisp/cedet/ede/locate.el
index c356979839d..56782ff4d36 100644
--- a/lisp/cedet/ede/locate.el
+++ b/lisp/cedet/ede/locate.el
@@ -1,6 +1,6 @@
 ;;; ede/locate.el --- Locate support  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/make.el b/lisp/cedet/ede/make.el
index 5d4bc9f556e..49b84f66e2c 100644
--- a/lisp/cedet/ede/make.el
+++ b/lisp/cedet/ede/make.el
@@ -1,6 +1,6 @@
 ;;; ede/make.el --- General information about "make"  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/makefile-edit.el b/lisp/cedet/ede/makefile-edit.el
index 9a35c74d841..461274876a0 100644
--- a/lisp/cedet/ede/makefile-edit.el
+++ b/lisp/cedet/ede/makefile-edit.el
@@ -1,6 +1,6 @@
 ;;; makefile-edit.el --- Makefile editing/scanning commands.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/pconf.el b/lisp/cedet/ede/pconf.el
index 610d0a1dcb6..57dc4263af5 100644
--- a/lisp/cedet/ede/pconf.el
+++ b/lisp/cedet/ede/pconf.el
@@ -1,6 +1,6 @@
 ;;; ede/pconf.el --- configure.ac maintenance for EDE  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project
diff --git a/lisp/cedet/ede/pmake.el b/lisp/cedet/ede/pmake.el
index 954683a22bb..e6d989946db 100644
--- a/lisp/cedet/ede/pmake.el
+++ b/lisp/cedet/ede/pmake.el
@@ -1,6 +1,6 @@
 ;;; ede-pmake.el --- EDE Generic Project Makefile code generator  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj-archive.el b/lisp/cedet/ede/proj-archive.el
index 9f84497351c..7f8ccc11158 100644
--- a/lisp/cedet/ede/proj-archive.el
+++ b/lisp/cedet/ede/proj-archive.el
@@ -1,6 +1,6 @@
 ;;; ede/proj-archive.el --- EDE Generic Project archive support  -*- 
lexical-binding: t -*-
 
-;;  Copyright (C) 1998-2001, 2009-2023 Free Software Foundation, Inc.
+;;  Copyright (C) 1998-2001, 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj-aux.el b/lisp/cedet/ede/proj-aux.el
index 50fcb8ac201..6a8c81a9ce2 100644
--- a/lisp/cedet/ede/proj-aux.el
+++ b/lisp/cedet/ede/proj-aux.el
@@ -1,6 +1,6 @@
 ;;; ede/proj-aux.el --- EDE Generic Project auxiliary file support  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1998-2000, 2007, 2009-2023 Free Software Foundation,
+;; Copyright (C) 1998-2000, 2007, 2009-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/proj-comp.el b/lisp/cedet/ede/proj-comp.el
index a31313bfe3d..1b2024d64c7 100644
--- a/lisp/cedet/ede/proj-comp.el
+++ b/lisp/cedet/ede/proj-comp.el
@@ -1,6 +1,6 @@
 ;;; ede/proj-comp.el --- EDE Generic Project compiler/rule driver  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2001, 2004-2005, 2007, 2009-2023 Free Software
+;; Copyright (C) 1999-2001, 2004-2005, 2007, 2009-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/proj-elisp.el b/lisp/cedet/ede/proj-elisp.el
index 1aa637c94fe..951c7173653 100644
--- a/lisp/cedet/ede/proj-elisp.el
+++ b/lisp/cedet/ede/proj-elisp.el
@@ -1,6 +1,6 @@
 ;;; ede-proj-elisp.el --- EDE Generic Project Emacs Lisp support  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj-info.el b/lisp/cedet/ede/proj-info.el
index 07fe5031ecf..1a9c2070116 100644
--- a/lisp/cedet/ede/proj-info.el
+++ b/lisp/cedet/ede/proj-info.el
@@ -1,6 +1,6 @@
 ;;; ede-proj-info.el --- EDE Generic Project texinfo support  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj-misc.el b/lisp/cedet/ede/proj-misc.el
index 3433443f5d8..961b1e26b22 100644
--- a/lisp/cedet/ede/proj-misc.el
+++ b/lisp/cedet/ede/proj-misc.el
@@ -1,6 +1,6 @@
 ;;; ede-proj-misc.el --- EDE Generic Project Emacs Lisp support  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1998-2001, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2001, 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj-obj.el b/lisp/cedet/ede/proj-obj.el
index 50eedf62eca..2a529c56e25 100644
--- a/lisp/cedet/ede/proj-obj.el
+++ b/lisp/cedet/ede/proj-obj.el
@@ -1,6 +1,6 @@
 ;;; ede/proj-obj.el --- EDE Generic Project Object code generation support  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj-prog.el b/lisp/cedet/ede/proj-prog.el
index ce782eb4d0b..e5439f345d9 100644
--- a/lisp/cedet/ede/proj-prog.el
+++ b/lisp/cedet/ede/proj-prog.el
@@ -1,6 +1,6 @@
 ;;; ede-proj-prog.el --- EDE Generic Project program support  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2001, 2005, 2008-2023 Free Software Foundation,
+;; Copyright (C) 1998-2001, 2005, 2008-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/proj-scheme.el b/lisp/cedet/ede/proj-scheme.el
index aa2b8c7fd86..a7482bd2bf2 100644
--- a/lisp/cedet/ede/proj-scheme.el
+++ b/lisp/cedet/ede/proj-scheme.el
@@ -1,6 +1,6 @@
 ;;; ede/proj-scheme.el --- EDE Generic Project scheme (guile) support  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1998-2000, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2000, 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make, scheme
diff --git a/lisp/cedet/ede/proj-shared.el b/lisp/cedet/ede/proj-shared.el
index 34c9dbb5cf4..5e063251c5d 100644
--- a/lisp/cedet/ede/proj-shared.el
+++ b/lisp/cedet/ede/proj-shared.el
@@ -1,6 +1,6 @@
 ;;; ede-proj-shared.el --- EDE Generic Project shared library support  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj.el b/lisp/cedet/ede/proj.el
index 3d680b3cb8c..9137d7eb59f 100644
--- a/lisp/cedet/ede/proj.el
+++ b/lisp/cedet/ede/proj.el
@@ -1,6 +1,6 @@
 ;;; ede/proj.el --- EDE Generic Project file driver  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1998-2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
diff --git a/lisp/cedet/ede/project-am.el b/lisp/cedet/ede/project-am.el
index 0f28afa7416..8810683d05d 100644
--- a/lisp/cedet/ede/project-am.el
+++ b/lisp/cedet/ede/project-am.el
@@ -1,6 +1,6 @@
 ;;; project-am.el --- A project management scheme based on automake files.  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2000, 2003, 2005, 2007-2023 Free Software
+;; Copyright (C) 1998-2000, 2003, 2005, 2007-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/shell.el b/lisp/cedet/ede/shell.el
index 4d58797e30b..8b47ba46670 100644
--- a/lisp/cedet/ede/shell.el
+++ b/lisp/cedet/ede/shell.el
@@ -1,6 +1,6 @@
 ;;; ede/shell.el --- A shell controlled by EDE.  -*- lexical-binding: t; -*-
 ;;
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/simple.el b/lisp/cedet/ede/simple.el
index 071e8d79eb5..6b62986f942 100644
--- a/lisp/cedet/ede/simple.el
+++ b/lisp/cedet/ede/simple.el
@@ -1,6 +1,6 @@
 ;;; ede/simple.el --- Overlay an EDE structure on an existing project  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/source.el b/lisp/cedet/ede/source.el
index 8c699e8976f..fbe21c16a4f 100644
--- a/lisp/cedet/ede/source.el
+++ b/lisp/cedet/ede/source.el
@@ -1,6 +1,6 @@
 ;; ede/source.el --- EDE source code object  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2000, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
diff --git a/lisp/cedet/ede/speedbar.el b/lisp/cedet/ede/speedbar.el
index aa3c95fec0c..65fb26d41d0 100644
--- a/lisp/cedet/ede/speedbar.el
+++ b/lisp/cedet/ede/speedbar.el
@@ -1,6 +1,6 @@
 ;;; ede/speedbar.el --- Speedbar viewing of EDE projects  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1998-2001, 2003, 2005, 2007-2023 Free Software
+;; Copyright (C) 1998-2001, 2003, 2005, 2007-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/srecode.el b/lisp/cedet/ede/srecode.el
index b2f5e4779c8..0d305abf8e0 100644
--- a/lisp/cedet/ede/srecode.el
+++ b/lisp/cedet/ede/srecode.el
@@ -1,6 +1,6 @@
 ;;; ede/srecode.el --- EDE utilities on top of SRecoder  -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/ede/system.el b/lisp/cedet/ede/system.el
index dbd48308769..a912856ec4f 100644
--- a/lisp/cedet/ede/system.el
+++ b/lisp/cedet/ede/system.el
@@ -1,6 +1,6 @@
 ;;; ede-system.el --- EDE working with the system (VC, FTP, ETC)  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2001-2003, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2003, 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make, vc
diff --git a/lisp/cedet/ede/util.el b/lisp/cedet/ede/util.el
index 739a2e34e86..8e346f5b9e3 100644
--- a/lisp/cedet/ede/util.el
+++ b/lisp/cedet/ede/util.el
@@ -1,6 +1,6 @@
 ;;; ede/util.el --- EDE utilities  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2000, 2005, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2005, 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
diff --git a/lisp/cedet/mode-local.el b/lisp/cedet/mode-local.el
index 62b51d8ee8b..5754d725272 100644
--- a/lisp/cedet/mode-local.el
+++ b/lisp/cedet/mode-local.el
@@ -1,6 +1,6 @@
 ;;; mode-local.el --- Support for mode local facilities  -*- lexical-binding:t 
-*-
 ;;
-;; Copyright (C) 2004-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2005, 2007-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: David Ponce <david@dponce.com>
 ;; Created: 27 Apr 2004
diff --git a/lisp/cedet/pulse.el b/lisp/cedet/pulse.el
index 38ccf5b975f..d9f6a40865a 100644
--- a/lisp/cedet/pulse.el
+++ b/lisp/cedet/pulse.el
@@ -1,6 +1,6 @@
 ;;; pulse.el --- Pulsing Overlays  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Version: 1.0
diff --git a/lisp/cedet/semantic.el b/lisp/cedet/semantic.el
index 0c15a2a453e..3c3ae2ac160 100644
--- a/lisp/cedet/semantic.el
+++ b/lisp/cedet/semantic.el
@@ -1,6 +1,6 @@
 ;;; semantic.el --- Semantic buffer evaluator.  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax tools
diff --git a/lisp/cedet/semantic/analyze.el b/lisp/cedet/semantic/analyze.el
index 405b1b136e3..d536b26f7ac 100644
--- a/lisp/cedet/semantic/analyze.el
+++ b/lisp/cedet/semantic/analyze.el
@@ -1,6 +1,6 @@
 ;;; semantic/analyze.el --- Analyze semantic tags against local context  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/analyze/complete.el 
b/lisp/cedet/semantic/analyze/complete.el
index 8c8ae6a271d..b42fe5e9f5d 100644
--- a/lisp/cedet/semantic/analyze/complete.el
+++ b/lisp/cedet/semantic/analyze/complete.el
@@ -1,6 +1,6 @@
 ;;; semantic/analyze/complete.el --- Smart Completions  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/analyze/debug.el 
b/lisp/cedet/semantic/analyze/debug.el
index 6f195c24337..ad3786b5b59 100644
--- a/lisp/cedet/semantic/analyze/debug.el
+++ b/lisp/cedet/semantic/analyze/debug.el
@@ -1,6 +1,6 @@
 ;;; semantic/analyze/debug.el --- Debug the analyzer  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/analyze/fcn.el 
b/lisp/cedet/semantic/analyze/fcn.el
index d2c4e1aecb4..4404616007b 100644
--- a/lisp/cedet/semantic/analyze/fcn.el
+++ b/lisp/cedet/semantic/analyze/fcn.el
@@ -1,6 +1,6 @@
 ;;; semantic/analyze/fcn.el --- Analyzer support functions.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/analyze/refs.el 
b/lisp/cedet/semantic/analyze/refs.el
index c3acec6a37b..977eabc9f5a 100644
--- a/lisp/cedet/semantic/analyze/refs.el
+++ b/lisp/cedet/semantic/analyze/refs.el
@@ -1,6 +1,6 @@
 ;;; semantic/analyze/refs.el --- Analysis of the references between tags.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/bovine.el b/lisp/cedet/semantic/bovine.el
index 1fe4bbf76f5..79435913dd6 100644
--- a/lisp/cedet/semantic/bovine.el
+++ b/lisp/cedet/semantic/bovine.el
@@ -1,6 +1,6 @@
 ;;; semantic/bovine.el --- LL Parser/Analyzer core  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2004, 2006-2007, 2009-2023 Free Software
+;; Copyright (C) 1999-2004, 2006-2007, 2009-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/bovine/c.el b/lisp/cedet/semantic/bovine/c.el
index 4e6f6568501..cf5ce1761a8 100644
--- a/lisp/cedet/semantic/bovine/c.el
+++ b/lisp/cedet/semantic/bovine/c.el
@@ -1,6 +1,6 @@
 ;;; semantic/bovine/c.el --- Semantic details for C  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/bovine/debug.el 
b/lisp/cedet/semantic/bovine/debug.el
index f583dbbc691..a13f4ad7c93 100644
--- a/lisp/cedet/semantic/bovine/debug.el
+++ b/lisp/cedet/semantic/bovine/debug.el
@@ -1,6 +1,6 @@
 ;;; semantic/bovine/debug.el --- Debugger support for bovinator  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/bovine/el.el b/lisp/cedet/semantic/bovine/el.el
index 294616f70d9..ef3e5d53af9 100644
--- a/lisp/cedet/semantic/bovine/el.el
+++ b/lisp/cedet/semantic/bovine/el.el
@@ -1,6 +1,6 @@
 ;;; semantic/bovine/el.el --- Semantic details for Emacs Lisp  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/bovine/gcc.el 
b/lisp/cedet/semantic/bovine/gcc.el
index 4c687fa43be..47700959a2b 100644
--- a/lisp/cedet/semantic/bovine/gcc.el
+++ b/lisp/cedet/semantic/bovine/gcc.el
@@ -1,6 +1,6 @@
 ;;; semantic/bovine/gcc.el --- gcc querying special code for the C parser  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/bovine/grammar.el 
b/lisp/cedet/semantic/bovine/grammar.el
index 1b9b65eaaf9..4a9324492c8 100644
--- a/lisp/cedet/semantic/bovine/grammar.el
+++ b/lisp/cedet/semantic/bovine/grammar.el
@@ -1,6 +1,6 @@
 ;;; semantic/bovine/grammar.el --- Bovine's input grammar mode  -*- 
lexical-binding: t; -*-
 ;;
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: David Ponce <david@dponce.com>
 ;; Created: 26 Aug 2002
diff --git a/lisp/cedet/semantic/bovine/make.el 
b/lisp/cedet/semantic/bovine/make.el
index 2171136ae9d..a95f7da27cf 100644
--- a/lisp/cedet/semantic/bovine/make.el
+++ b/lisp/cedet/semantic/bovine/make.el
@@ -1,6 +1,6 @@
 ;;; semantic/bovine/make.el --- Makefile parsing rules.  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2000-2004, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2004, 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/bovine/scm.el 
b/lisp/cedet/semantic/bovine/scm.el
index c0852eca8dd..6d19acf0282 100644
--- a/lisp/cedet/semantic/bovine/scm.el
+++ b/lisp/cedet/semantic/bovine/scm.el
@@ -1,6 +1,6 @@
 ;;; semantic/bovine/scm.el --- Semantic details for Scheme (guile)  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/chart.el b/lisp/cedet/semantic/chart.el
index 880d86fac49..a87ae19ee0c 100644
--- a/lisp/cedet/semantic/chart.el
+++ b/lisp/cedet/semantic/chart.el
@@ -1,6 +1,6 @@
 ;;; semantic/chart.el --- Utilities for use with semantic tag tables  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2001, 2003, 2005, 2008-2023 Free Software
+;; Copyright (C) 1999-2001, 2003, 2005, 2008-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/complete.el b/lisp/cedet/semantic/complete.el
index 84040b572bc..7adf9abfdcb 100644
--- a/lisp/cedet/semantic/complete.el
+++ b/lisp/cedet/semantic/complete.el
@@ -1,6 +1,6 @@
 ;;; semantic/complete.el --- Routines for performing tag completion  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
@@ -1046,7 +1046,7 @@ Output must be in semanticdb Find result format."
                     (and last-prefix (string-prefix-p last-prefix prefix t)))
                 ;; We have the same prefix, or last-prefix is a
                 ;; substring of the of new prefix, in which case we are
-                ;; refining our symbol so just re-use cache.
+                ;; refining our symbol so just reuse cache.
                 (oref obj last-all-completions))
                ((and last-prefix
                      (> (length prefix) 1)
diff --git a/lisp/cedet/semantic/ctxt.el b/lisp/cedet/semantic/ctxt.el
index 84e6c6ebecb..3b7af17a96d 100644
--- a/lisp/cedet/semantic/ctxt.el
+++ b/lisp/cedet/semantic/ctxt.el
@@ -1,6 +1,6 @@
 ;;; semantic/ctxt.el --- Context calculations for Semantic tools  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/db-debug.el b/lisp/cedet/semantic/db-debug.el
index c2ab5f0483c..817c8f07263 100644
--- a/lisp/cedet/semantic/db-debug.el
+++ b/lisp/cedet/semantic/db-debug.el
@@ -1,6 +1,6 @@
 ;;; semantic/db-debug.el --- Extra level debugging routines for Semantic  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/db-ebrowse.el 
b/lisp/cedet/semantic/db-ebrowse.el
index 3e54b9e76cf..3b387477850 100644
--- a/lisp/cedet/semantic/db-ebrowse.el
+++ b/lisp/cedet/semantic/db-ebrowse.el
@@ -1,6 +1,6 @@
 ;;; semantic/db-ebrowse.el --- Semanticdb backend using ebrowse.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Authors: Eric M. Ludlam <zappo@gnu.org>
 ;;     Joakim Verona
diff --git a/lisp/cedet/semantic/db-el.el b/lisp/cedet/semantic/db-el.el
index b97a8264a95..6357953a746 100644
--- a/lisp/cedet/semantic/db-el.el
+++ b/lisp/cedet/semantic/db-el.el
@@ -1,6 +1,6 @@
 ;;; semantic/db-el.el --- Semantic database extensions for Emacs Lisp  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: tags
diff --git a/lisp/cedet/semantic/db-file.el b/lisp/cedet/semantic/db-file.el
index 11c3cb7c55f..393072501f3 100644
--- a/lisp/cedet/semantic/db-file.el
+++ b/lisp/cedet/semantic/db-file.el
@@ -1,6 +1,6 @@
 ;;; semantic/db-file.el --- Save a semanticdb to a cache file.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: tags
diff --git a/lisp/cedet/semantic/db-find.el b/lisp/cedet/semantic/db-find.el
index 675ff72cfd3..6d42c3125c0 100644
--- a/lisp/cedet/semantic/db-find.el
+++ b/lisp/cedet/semantic/db-find.el
@@ -1,6 +1,6 @@
 ;;; semantic/db-find.el --- Searching through semantic databases.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: tags
diff --git a/lisp/cedet/semantic/db-global.el b/lisp/cedet/semantic/db-global.el
index b8dfc3c245f..7e5dee60fbe 100644
--- a/lisp/cedet/semantic/db-global.el
+++ b/lisp/cedet/semantic/db-global.el
@@ -1,6 +1,6 @@
 ;;; semantic/db-global.el --- Semantic database extensions for GLOBAL  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2006, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2006, 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: tags
diff --git a/lisp/cedet/semantic/db-javascript.el 
b/lisp/cedet/semantic/db-javascript.el
index b1c33e25018..9baa4e82b8f 100644
--- a/lisp/cedet/semantic/db-javascript.el
+++ b/lisp/cedet/semantic/db-javascript.el
@@ -1,6 +1,6 @@
 ;;; semantic/db-javascript.el --- Semantic database extensions for javascript  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Joakim Verona
 
diff --git a/lisp/cedet/semantic/db-mode.el b/lisp/cedet/semantic/db-mode.el
index 4e40424acb4..45a524fe849 100644
--- a/lisp/cedet/semantic/db-mode.el
+++ b/lisp/cedet/semantic/db-mode.el
@@ -1,6 +1,6 @@
 ;;; semantic/db-mode.el --- Semanticdb Minor Mode  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/db-ref.el b/lisp/cedet/semantic/db-ref.el
index 2ed7d8d8937..964ecaec258 100644
--- a/lisp/cedet/semantic/db-ref.el
+++ b/lisp/cedet/semantic/db-ref.el
@@ -1,6 +1,6 @@
 ;;; semantic/db-ref.el --- Handle cross-db file references  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/db-typecache.el 
b/lisp/cedet/semantic/db-typecache.el
index 1864e567c9a..7ca4c70abc9 100644
--- a/lisp/cedet/semantic/db-typecache.el
+++ b/lisp/cedet/semantic/db-typecache.el
@@ -1,6 +1,6 @@
 ;;; semantic/db-typecache.el --- Manage Datatypes  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/db.el b/lisp/cedet/semantic/db.el
index 0c78493542f..e4fbf28a64e 100644
--- a/lisp/cedet/semantic/db.el
+++ b/lisp/cedet/semantic/db.el
@@ -1,6 +1,6 @@
 ;;; semantic/db.el --- Semantic tag database manager  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: tags
@@ -393,9 +393,7 @@ If a database for DIRECTORY has already been created, 
return it.
 If DIRECTORY doesn't exist, create a new one."
   (let ((db (semanticdb-directory-loaded-p directory)))
     (unless db
-      (setq db (semanticdb-project-database
-               (file-name-nondirectory directory)
-               :tables nil))
+      (setq db (semanticdb-project-database :tables nil))
       ;; Set this up here.   We can't put it in the constructor because it
       ;; would be saved, and we want DB files to be portable.
       (setf (slot-value db 'reference-directory) (file-truename directory)))
diff --git a/lisp/cedet/semantic/debug.el b/lisp/cedet/semantic/debug.el
index 11e44538d31..7e3c0de9410 100644
--- a/lisp/cedet/semantic/debug.el
+++ b/lisp/cedet/semantic/debug.el
@@ -1,6 +1,6 @@
 ;;; semantic/debug.el --- Language Debugger framework  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2003-2005, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2005, 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/decorate.el b/lisp/cedet/semantic/decorate.el
index 27cfea6a65c..8c07155be37 100644
--- a/lisp/cedet/semantic/decorate.el
+++ b/lisp/cedet/semantic/decorate.el
@@ -1,6 +1,6 @@
 ;;; semantic/decorate.el --- Utilities for decorating/highlighting tokens.  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/decorate/include.el 
b/lisp/cedet/semantic/decorate/include.el
index 96bf8cec3b2..c4629b68bca 100644
--- a/lisp/cedet/semantic/decorate/include.el
+++ b/lisp/cedet/semantic/decorate/include.el
@@ -1,6 +1,6 @@
 ;;; semantic/decorate/include.el --- Decoration modes for include statements  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/decorate/mode.el 
b/lisp/cedet/semantic/decorate/mode.el
index 5adcf636cef..c0d8d791a39 100644
--- a/lisp/cedet/semantic/decorate/mode.el
+++ b/lisp/cedet/semantic/decorate/mode.el
@@ -1,6 +1,6 @@
 ;;; semantic/decorate/mode.el --- Minor mode for decorating tags  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/dep.el b/lisp/cedet/semantic/dep.el
index bd01581feb1..0d0e4f08120 100644
--- a/lisp/cedet/semantic/dep.el
+++ b/lisp/cedet/semantic/dep.el
@@ -1,6 +1,6 @@
 ;;; semantic/dep.el --- Methods for tracking dependencies (include files)  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/doc.el b/lisp/cedet/semantic/doc.el
index 09b66e5cfac..80229fe5081 100644
--- a/lisp/cedet/semantic/doc.el
+++ b/lisp/cedet/semantic/doc.el
@@ -1,6 +1,6 @@
 ;;; semantic/doc.el --- Routines for documentation strings  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2003, 2005, 2008-2023 Free Software Foundation,
+;; Copyright (C) 1999-2003, 2005, 2008-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/ede-grammar.el 
b/lisp/cedet/semantic/ede-grammar.el
index 42ffe50ca63..49a6ee94c84 100644
--- a/lisp/cedet/semantic/ede-grammar.el
+++ b/lisp/cedet/semantic/ede-grammar.el
@@ -1,6 +1,6 @@
 ;;; semantic/ede-grammar.el --- EDE support for Semantic Grammar Files  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2004, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: project, make
diff --git a/lisp/cedet/semantic/edit.el b/lisp/cedet/semantic/edit.el
index 4eeb7745370..9dfb96f1fa1 100644
--- a/lisp/cedet/semantic/edit.el
+++ b/lisp/cedet/semantic/edit.el
@@ -1,6 +1,6 @@
 ;;; semantic/edit.el --- Edit Management for Semantic  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/find.el b/lisp/cedet/semantic/find.el
index 9094fcf0739..14fbcbc00f8 100644
--- a/lisp/cedet/semantic/find.el
+++ b/lisp/cedet/semantic/find.el
@@ -1,6 +1,6 @@
 ;;; semantic/find.el --- Search routines for Semantic  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1999-2005, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2005, 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/format.el b/lisp/cedet/semantic/format.el
index c808da3b093..1e4c4d92d81 100644
--- a/lisp/cedet/semantic/format.el
+++ b/lisp/cedet/semantic/format.el
@@ -1,6 +1,6 @@
 ;;; semantic/format.el --- Routines for formatting tags  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1999-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/fw.el b/lisp/cedet/semantic/fw.el
index 184a74c8c2e..1a7af803a6b 100644
--- a/lisp/cedet/semantic/fw.el
+++ b/lisp/cedet/semantic/fw.el
@@ -1,6 +1,6 @@
 ;;; semantic/fw.el --- Framework for Semantic  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/grammar.el b/lisp/cedet/semantic/grammar.el
index 15ad18ad886..54dc7807ef6 100644
--- a/lisp/cedet/semantic/grammar.el
+++ b/lisp/cedet/semantic/grammar.el
@@ -1,6 +1,6 @@
 ;;; semantic/grammar.el --- Major mode framework for Semantic grammars  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 
diff --git a/lisp/cedet/semantic/grm-wy-boot.el 
b/lisp/cedet/semantic/grm-wy-boot.el
index 159ac64fc30..7658a26d106 100644
--- a/lisp/cedet/semantic/grm-wy-boot.el
+++ b/lisp/cedet/semantic/grm-wy-boot.el
@@ -1,6 +1,6 @@
 ;;; semantic/grammar-wy.el --- Generated parser support file  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/cedet/semantic/html.el b/lisp/cedet/semantic/html.el
index 7c1181de0d7..120b2108709 100644
--- a/lisp/cedet/semantic/html.el
+++ b/lisp/cedet/semantic/html.el
@@ -1,6 +1,6 @@
 ;;; semantic/html.el --- Semantic details for html files  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2004-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/ia-sb.el b/lisp/cedet/semantic/ia-sb.el
index 47a4ce322ca..76f32345cf7 100644
--- a/lisp/cedet/semantic/ia-sb.el
+++ b/lisp/cedet/semantic/ia-sb.el
@@ -1,6 +1,6 @@
 ;;; semantic/ia-sb.el --- Speedbar analysis display interactor  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/ia.el b/lisp/cedet/semantic/ia.el
index 890c6dac51a..7fec56afaa3 100644
--- a/lisp/cedet/semantic/ia.el
+++ b/lisp/cedet/semantic/ia.el
@@ -1,6 +1,6 @@
 ;;; semantic/ia.el --- Interactive Analysis functions  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/idle.el b/lisp/cedet/semantic/idle.el
index 416dbd340d5..fb8f4449c30 100644
--- a/lisp/cedet/semantic/idle.el
+++ b/lisp/cedet/semantic/idle.el
@@ -1,6 +1,6 @@
 ;;; idle.el --- Schedule parsing tasks in idle time  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2003-2006, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2006, 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/imenu.el b/lisp/cedet/semantic/imenu.el
index 7f27561c3d2..e13eec209ed 100644
--- a/lisp/cedet/semantic/imenu.el
+++ b/lisp/cedet/semantic/imenu.el
@@ -1,6 +1,6 @@
 ;;; semantic/imenu.el --- Use Semantic as an imenu tag generator  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2005, 2007-2008, 2010-2023 Free Software
+;; Copyright (C) 2000-2005, 2007-2008, 2010-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/java.el b/lisp/cedet/semantic/java.el
index e65dcdb2db3..7e6a252e423 100644
--- a/lisp/cedet/semantic/java.el
+++ b/lisp/cedet/semantic/java.el
@@ -1,6 +1,6 @@
 ;;; semantic/java.el --- Semantic functions for Java  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 
diff --git a/lisp/cedet/semantic/lex-spp.el b/lisp/cedet/semantic/lex-spp.el
index 59a52c35e9f..053f583a60e 100644
--- a/lisp/cedet/semantic/lex-spp.el
+++ b/lisp/cedet/semantic/lex-spp.el
@@ -1,6 +1,6 @@
 ;;; semantic/lex-spp.el --- Semantic Lexical Pre-processor  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/lex.el b/lisp/cedet/semantic/lex.el
index e2bcf6417ed..144ebcd64f8 100644
--- a/lisp/cedet/semantic/lex.el
+++ b/lisp/cedet/semantic/lex.el
@@ -1,6 +1,6 @@
 ;;; semantic/lex.el --- Lexical Analyzer builder  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/mru-bookmark.el 
b/lisp/cedet/semantic/mru-bookmark.el
index b8d28eb7b08..4b4b5bd7235 100644
--- a/lisp/cedet/semantic/mru-bookmark.el
+++ b/lisp/cedet/semantic/mru-bookmark.el
@@ -1,6 +1,6 @@
 ;;; semantic/mru-bookmark.el --- Automatic bookmark tracking  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/sb.el b/lisp/cedet/semantic/sb.el
index 17cf00cd3c4..aa472ef681e 100644
--- a/lisp/cedet/semantic/sb.el
+++ b/lisp/cedet/semantic/sb.el
@@ -1,6 +1,6 @@
 ;;; semantic/sb.el --- Semantic tag display for speedbar  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/scope.el b/lisp/cedet/semantic/scope.el
index 956e901d538..a6eeb7b98a8 100644
--- a/lisp/cedet/semantic/scope.el
+++ b/lisp/cedet/semantic/scope.el
@@ -1,6 +1,6 @@
 ;;; semantic/scope.el --- Analyzer Scope Calculations  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/senator.el b/lisp/cedet/semantic/senator.el
index ca4334eaff5..aec251a0dc6 100644
--- a/lisp/cedet/semantic/senator.el
+++ b/lisp/cedet/semantic/senator.el
@@ -1,6 +1,6 @@
 ;;; semantic/senator.el --- SEmantic NAvigaTOR  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/cedet/semantic/sort.el b/lisp/cedet/semantic/sort.el
index aebd50a649b..5e2dca03f64 100644
--- a/lisp/cedet/semantic/sort.el
+++ b/lisp/cedet/semantic/sort.el
@@ -1,6 +1,6 @@
 ;;; semantic/sort.el --- Utilities for sorting and re-arranging tag tables.  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/symref.el b/lisp/cedet/semantic/symref.el
index 1ebd7ea154b..5c487a7f44d 100644
--- a/lisp/cedet/semantic/symref.el
+++ b/lisp/cedet/semantic/symref.el
@@ -1,6 +1,6 @@
 ;;; semantic/symref.el --- Symbol Reference API  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/symref/cscope.el 
b/lisp/cedet/semantic/symref/cscope.el
index 2d2e3e134aa..afe7829302c 100644
--- a/lisp/cedet/semantic/symref/cscope.el
+++ b/lisp/cedet/semantic/symref/cscope.el
@@ -1,6 +1,6 @@
 ;;; semantic/symref/cscope.el --- Semantic-symref support via cscope  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/symref/filter.el 
b/lisp/cedet/semantic/symref/filter.el
index efc4cb06b83..300f165282a 100644
--- a/lisp/cedet/semantic/symref/filter.el
+++ b/lisp/cedet/semantic/symref/filter.el
@@ -1,6 +1,6 @@
 ;;; semantic/symref/filter.el --- Filter symbol reference hits for accuracy  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/symref/global.el 
b/lisp/cedet/semantic/symref/global.el
index d13222855af..bfedbd3b366 100644
--- a/lisp/cedet/semantic/symref/global.el
+++ b/lisp/cedet/semantic/symref/global.el
@@ -1,6 +1,6 @@
 ;;; semantic/symref/global.el --- Use GNU Global for symbol references  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/symref/grep.el 
b/lisp/cedet/semantic/symref/grep.el
index cebeac3adca..83e3bc36073 100644
--- a/lisp/cedet/semantic/symref/grep.el
+++ b/lisp/cedet/semantic/symref/grep.el
@@ -1,6 +1,6 @@
 ;;; semantic/symref/grep.el --- Symref implementation using find/grep  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/symref/idutils.el 
b/lisp/cedet/semantic/symref/idutils.el
index 3052070da75..7af5146bbbb 100644
--- a/lisp/cedet/semantic/symref/idutils.el
+++ b/lisp/cedet/semantic/symref/idutils.el
@@ -1,6 +1,6 @@
 ;;; semantic/symref/idutils.el --- Symref implementation for idutils  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/symref/list.el 
b/lisp/cedet/semantic/symref/list.el
index 4b4c968cf81..5239a8a33be 100644
--- a/lisp/cedet/semantic/symref/list.el
+++ b/lisp/cedet/semantic/symref/list.el
@@ -1,6 +1,6 @@
 ;;; semantic/symref/list.el --- Symref Output List UI  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/tag-file.el b/lisp/cedet/semantic/tag-file.el
index ee32adeb574..ed2db82f9a0 100644
--- a/lisp/cedet/semantic/tag-file.el
+++ b/lisp/cedet/semantic/tag-file.el
@@ -1,6 +1,6 @@
 ;;; semantic/tag-file.el --- Routines that find files based on tags.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/tag-ls.el b/lisp/cedet/semantic/tag-ls.el
index fb01e0365ac..1854acd59a5 100644
--- a/lisp/cedet/semantic/tag-ls.el
+++ b/lisp/cedet/semantic/tag-ls.el
@@ -1,6 +1,6 @@
 ;;; semantic/tag-ls.el --- Language Specific override functions for tags  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/tag-write.el b/lisp/cedet/semantic/tag-write.el
index d32a85d6a00..cee1c53b8b2 100644
--- a/lisp/cedet/semantic/tag-write.el
+++ b/lisp/cedet/semantic/tag-write.el
@@ -1,6 +1,6 @@
 ;;; semantic/tag-write.el --- Write tags to a text stream  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/tag.el b/lisp/cedet/semantic/tag.el
index 4c1694ddd6b..18a0b4caee2 100644
--- a/lisp/cedet/semantic/tag.el
+++ b/lisp/cedet/semantic/tag.el
@@ -1,6 +1,6 @@
 ;;; semantic/tag.el --- Tag creation and access  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/texi.el b/lisp/cedet/semantic/texi.el
index 45e03cb9102..6374d995d0a 100644
--- a/lisp/cedet/semantic/texi.el
+++ b/lisp/cedet/semantic/texi.el
@@ -1,6 +1,6 @@
 ;;; semantic/texi.el --- Semantic details for Texinfo files  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/semantic/util-modes.el 
b/lisp/cedet/semantic/util-modes.el
index 92b9f84ebb3..c785c3d8ee2 100644
--- a/lisp/cedet/semantic/util-modes.el
+++ b/lisp/cedet/semantic/util-modes.el
@@ -1,6 +1,6 @@
 ;;; semantic/util-modes.el --- Semantic minor modes  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2000-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Authors: Eric M. Ludlam <zappo@gnu.org>
 ;;          David Ponce <david@dponce.com>
diff --git a/lisp/cedet/semantic/util.el b/lisp/cedet/semantic/util.el
index 2cd3184d006..f3c33c16ebc 100644
--- a/lisp/cedet/semantic/util.el
+++ b/lisp/cedet/semantic/util.el
@@ -1,6 +1,6 @@
 ;;; semantic/util.el --- Utilities for use with semantic tag tables  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/wisent.el b/lisp/cedet/semantic/wisent.el
index 23da3ac5df5..00ba21c43af 100644
--- a/lisp/cedet/semantic/wisent.el
+++ b/lisp/cedet/semantic/wisent.el
@@ -1,6 +1,6 @@
 ;;; semantic/wisent.el --- Wisent - Semantic gateway  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2001-2007, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2007, 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 ;; Created: 30 Aug 2001
diff --git a/lisp/cedet/semantic/wisent/comp.el 
b/lisp/cedet/semantic/wisent/comp.el
index d13b2cf326d..debf9fc97b2 100644
--- a/lisp/cedet/semantic/wisent/comp.el
+++ b/lisp/cedet/semantic/wisent/comp.el
@@ -1,6 +1,6 @@
 ;;; semantic/wisent/comp.el --- GNU Bison for Emacs - Grammar compiler  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1984, 1986, 1989, 1992, 1995, 2000-2007, 2009-2023 Free
+;; Copyright (C) 1984, 1986, 1989, 1992, 1995, 2000-2007, 2009-2024 Free
 ;; Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
diff --git a/lisp/cedet/semantic/wisent/grammar.el 
b/lisp/cedet/semantic/wisent/grammar.el
index b121b05befe..7911dc04564 100644
--- a/lisp/cedet/semantic/wisent/grammar.el
+++ b/lisp/cedet/semantic/wisent/grammar.el
@@ -1,6 +1,6 @@
 ;;; semantic/wisent/grammar.el --- Wisent's input grammar mode  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: David Ponce <david@dponce.com>
 ;; Created: 26 Aug 2002
diff --git a/lisp/cedet/semantic/wisent/java-tags.el 
b/lisp/cedet/semantic/wisent/java-tags.el
index 3bac18a257c..ed62d2c3a9c 100644
--- a/lisp/cedet/semantic/wisent/java-tags.el
+++ b/lisp/cedet/semantic/wisent/java-tags.el
@@ -1,6 +1,6 @@
 ;;; semantic/wisent/java-tags.el --- Java LALR parser for Emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2006, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2006, 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 ;; Created: 15 Dec 2001
diff --git a/lisp/cedet/semantic/wisent/javascript.el 
b/lisp/cedet/semantic/wisent/javascript.el
index 1750d53d46d..7a1a8637aae 100644
--- a/lisp/cedet/semantic/wisent/javascript.el
+++ b/lisp/cedet/semantic/wisent/javascript.el
@@ -1,6 +1,6 @@
 ;;; semantic/wisent/javascript.el --- javascript parser support  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2005, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax
diff --git a/lisp/cedet/semantic/wisent/python.el 
b/lisp/cedet/semantic/wisent/python.el
index 6b274df614c..73f08beaa28 100644
--- a/lisp/cedet/semantic/wisent/python.el
+++ b/lisp/cedet/semantic/wisent/python.el
@@ -1,6 +1,6 @@
 ;;; wisent-python.el --- Semantic support for Python  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Richard Kim <emacs18@gmail.com>
 ;; Created: June 2002
diff --git a/lisp/cedet/semantic/wisent/wisent.el 
b/lisp/cedet/semantic/wisent/wisent.el
index c2bb429ef76..a6c5ba7c087 100644
--- a/lisp/cedet/semantic/wisent/wisent.el
+++ b/lisp/cedet/semantic/wisent/wisent.el
@@ -1,6 +1,6 @@
 ;;; semantic/wisent/wisent.el --- GNU Bison for Emacs - Runtime  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 ;; Created: 30 January 2002
diff --git a/lisp/cedet/srecode.el b/lisp/cedet/srecode.el
index 7f606a6eb56..1dc7f98f7eb 100644
--- a/lisp/cedet/srecode.el
+++ b/lisp/cedet/srecode.el
@@ -1,6 +1,6 @@
 ;;; srecode.el --- Semantic buffer evaluator.  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: codegeneration
diff --git a/lisp/cedet/srecode/args.el b/lisp/cedet/srecode/args.el
index 78b217d6b7e..f4f79a98ffd 100644
--- a/lisp/cedet/srecode/args.el
+++ b/lisp/cedet/srecode/args.el
@@ -1,6 +1,6 @@
 ;;; srecode/args.el --- Provide some simple template arguments  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/compile.el b/lisp/cedet/srecode/compile.el
index 77d3fee9df7..b960873506d 100644
--- a/lisp/cedet/srecode/compile.el
+++ b/lisp/cedet/srecode/compile.el
@@ -1,6 +1,6 @@
 ;;; srecode/compile --- Compilation of srecode template files.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: codegeneration
diff --git a/lisp/cedet/srecode/cpp.el b/lisp/cedet/srecode/cpp.el
index 0be8db03bbc..9b3f0b85dcb 100644
--- a/lisp/cedet/srecode/cpp.el
+++ b/lisp/cedet/srecode/cpp.el
@@ -1,6 +1,6 @@
 ;;; srecode/cpp.el --- C++ specific handlers for Semantic Recoder  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;;         Jan Moringen <scymtym@users.sourceforge.net>
diff --git a/lisp/cedet/srecode/ctxt.el b/lisp/cedet/srecode/ctxt.el
index ebcab20303f..bad9836bb43 100644
--- a/lisp/cedet/srecode/ctxt.el
+++ b/lisp/cedet/srecode/ctxt.el
@@ -1,6 +1,6 @@
 ;;; srecode/ctxt.el --- Derive a context from the source buffer.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/dictionary.el b/lisp/cedet/srecode/dictionary.el
index 25d595bf3c3..03d25466cfc 100644
--- a/lisp/cedet/srecode/dictionary.el
+++ b/lisp/cedet/srecode/dictionary.el
@@ -1,6 +1,6 @@
 ;;; srecode/dictionary.el --- Dictionary code for the semantic recoder.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/document.el b/lisp/cedet/srecode/document.el
index 40bb7f9e480..f4d192da38c 100644
--- a/lisp/cedet/srecode/document.el
+++ b/lisp/cedet/srecode/document.el
@@ -1,6 +1,6 @@
 ;;; srecode/document.el --- Documentation (comment) generation  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/el.el b/lisp/cedet/srecode/el.el
index bf034691103..ee88a056793 100644
--- a/lisp/cedet/srecode/el.el
+++ b/lisp/cedet/srecode/el.el
@@ -1,6 +1,6 @@
 ;;; srecode/el.el --- Emacs Lisp specific arguments  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/expandproto.el 
b/lisp/cedet/srecode/expandproto.el
index d5c22c0d71a..37b3fe3d78c 100644
--- a/lisp/cedet/srecode/expandproto.el
+++ b/lisp/cedet/srecode/expandproto.el
@@ -1,6 +1,6 @@
 ;;; srecode/expandproto.el --- Expanding prototypes.  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/extract.el b/lisp/cedet/srecode/extract.el
index 4eb7632b721..27a96431062 100644
--- a/lisp/cedet/srecode/extract.el
+++ b/lisp/cedet/srecode/extract.el
@@ -1,6 +1,6 @@
 ;;; srecode/extract.el --- Extract content from previously inserted macro.  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
@@ -33,7 +33,7 @@
 ;; or deep template calls can be extracted.
 ;;
 ;; This code was specifically written for srecode-document, which
-;; wants to extract user written text, and re-use it in a reformatted
+;; wants to extract user written text, and reuse it in a reformatted
 ;; comment.
 
 (require 'srecode)
diff --git a/lisp/cedet/srecode/fields.el b/lisp/cedet/srecode/fields.el
index 804b9937f6d..72ee2e91511 100644
--- a/lisp/cedet/srecode/fields.el
+++ b/lisp/cedet/srecode/fields.el
@@ -1,6 +1,6 @@
 ;;; srecode/fields.el --- Handling type-in fields in a buffer.  -*- 
lexical-binding: t; -*-
 ;;
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/filters.el b/lisp/cedet/srecode/filters.el
index 1bb81b4a951..2b7fee06687 100644
--- a/lisp/cedet/srecode/filters.el
+++ b/lisp/cedet/srecode/filters.el
@@ -1,6 +1,6 @@
 ;;; srecode/filters.el --- Filters for use in template variables.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/find.el b/lisp/cedet/srecode/find.el
index 6d64a26e46c..41030aa6944 100644
--- a/lisp/cedet/srecode/find.el
+++ b/lisp/cedet/srecode/find.el
@@ -1,6 +1,6 @@
 ;;;; srecode/find.el --- Tools for finding templates in the database.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/getset.el b/lisp/cedet/srecode/getset.el
index 9ef85cbf5aa..046cba330af 100644
--- a/lisp/cedet/srecode/getset.el
+++ b/lisp/cedet/srecode/getset.el
@@ -1,6 +1,6 @@
 ;;; srecode/getset.el --- Package for inserting new get/set methods.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/insert.el b/lisp/cedet/srecode/insert.el
index 04f5ef55e05..b08b3583cd4 100644
--- a/lisp/cedet/srecode/insert.el
+++ b/lisp/cedet/srecode/insert.el
@@ -1,6 +1,6 @@
 ;;; srecode/insert.el --- Insert srecode templates to an output stream  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/java.el b/lisp/cedet/srecode/java.el
index 8d43111dd4d..66abd736de4 100644
--- a/lisp/cedet/srecode/java.el
+++ b/lisp/cedet/srecode/java.el
@@ -1,6 +1,6 @@
 ;;; srecode/java.el --- Srecode Java support  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/map.el b/lisp/cedet/srecode/map.el
index 44e465c69b1..30f4c755e17 100644
--- a/lisp/cedet/srecode/map.el
+++ b/lisp/cedet/srecode/map.el
@@ -1,6 +1,6 @@
 ;;; srecode/map.el --- Manage a template file map  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/mode.el b/lisp/cedet/srecode/mode.el
index d45f9a4bcd6..1774a52c0ab 100644
--- a/lisp/cedet/srecode/mode.el
+++ b/lisp/cedet/srecode/mode.el
@@ -1,6 +1,6 @@
 ;;; srecode/mode.el --- Minor mode for managing and using SRecode templates  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/semantic.el b/lisp/cedet/srecode/semantic.el
index 68fedf6fc2c..90a25d543d5 100644
--- a/lisp/cedet/srecode/semantic.el
+++ b/lisp/cedet/srecode/semantic.el
@@ -1,6 +1,6 @@
 ;;; srecode/semantic.el --- Semantic specific extensions to SRecode  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/srt-mode.el b/lisp/cedet/srecode/srt-mode.el
index 6bd416c5690..fbe88bd1fab 100644
--- a/lisp/cedet/srecode/srt-mode.el
+++ b/lisp/cedet/srecode/srt-mode.el
@@ -1,6 +1,6 @@
 ;;; srecode/srt-mode.el --- Major mode for writing screcode macros  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -420,7 +420,7 @@ Moves to the end of one named section."
              (when (string= (car (car subdicts)) name)
                (setq res (cdr (car subdicts))))
              (setq subdicts (cdr subdicts)))
-           ;; Pre-pend our global vars.
+           ;; Prepend our global vars.
            (append global res))
        ;; If we aren't in a subsection, just do the global variables
        global
diff --git a/lisp/cedet/srecode/srt.el b/lisp/cedet/srecode/srt.el
index bd2f62f8fd6..556dff82f97 100644
--- a/lisp/cedet/srecode/srt.el
+++ b/lisp/cedet/srecode/srt.el
@@ -1,6 +1,6 @@
 ;;; srecode/srt.el --- argument handlers for SRT files  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/table.el b/lisp/cedet/srecode/table.el
index e5ab53dd253..8ac26c9bf01 100644
--- a/lisp/cedet/srecode/table.el
+++ b/lisp/cedet/srecode/table.el
@@ -1,6 +1,6 @@
 ;;; srecode/table.el --- Tables of Semantic Recoders  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/cedet/srecode/template.el b/lisp/cedet/srecode/template.el
index 4048e13e602..2417f1f7ef6 100644
--- a/lisp/cedet/srecode/template.el
+++ b/lisp/cedet/srecode/template.el
@@ -1,6 +1,6 @@
 ;;; srecode/template.el --- SRecoder template language parser support.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/cedet/srecode/texi.el b/lisp/cedet/srecode/texi.el
index 65af027fe19..dd54347faef 100644
--- a/lisp/cedet/srecode/texi.el
+++ b/lisp/cedet/srecode/texi.el
@@ -1,6 +1,6 @@
 ;;; srecode/texi.el --- Srecode texinfo support.  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/lisp/char-fold.el b/lisp/char-fold.el
index 6da2dae8471..4d9644216d8 100644
--- a/lisp/char-fold.el
+++ b/lisp/char-fold.el
@@ -1,6 +1,6 @@
 ;;; char-fold.el --- match unicode to similar ASCII -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: matching
@@ -214,7 +214,7 @@
          equiv))
       equiv)))
 
-(defconst char-fold-table
+(defvar char-fold-table
   (eval-when-compile
     (char-fold--make-table))
   "Used for folding characters of the same group during search.
diff --git a/lisp/chistory.el b/lisp/chistory.el
index e53499d9e05..2a2d55f66ae 100644
--- a/lisp/chistory.el
+++ b/lisp/chistory.el
@@ -1,6 +1,6 @@
 ;;; chistory.el --- list command history  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: K. Shane Hartman
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/cmuscheme.el b/lisp/cmuscheme.el
index b3b8ae87ee3..c84a1809322 100644
--- a/lisp/cmuscheme.el
+++ b/lisp/cmuscheme.el
@@ -1,6 +1,6 @@
 ;;; cmuscheme.el --- Scheme process in a buffer. Adapted from tea.el  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1988-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988-2024 Free Software Foundation, Inc.
 
 ;; Author: Olin Shivers <olin.shivers@cs.cmu.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/color.el b/lisp/color.el
index f68cf5e6b17..078c12fbf47 100644
--- a/lisp/color.el
+++ b/lisp/color.el
@@ -1,6 +1,6 @@
 ;;; color.el --- Color manipulation library -*- lexical-binding:t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Authors: Julien Danjou <julien@danjou.info>
 ;;          Drew Adams <drew.adams@oracle.com>
diff --git a/lisp/comint.el b/lisp/comint.el
index de7cc5b0e86..0a9cdb44bef 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -1,6 +1,6 @@
 ;;; comint.el --- general command interpreter in a window stuff -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1988, 1990, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 1990, 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: Olin Shivers <shivers@cs.cmu.edu>
 ;;     Simon Marshall <simon@gnu.org>
diff --git a/lisp/completion-preview.el b/lisp/completion-preview.el
index 1d5f1253702..6fd60f3c416 100644
--- a/lisp/completion-preview.el
+++ b/lisp/completion-preview.el
@@ -1,6 +1,6 @@
 ;;; completion-preview.el --- Preview completion with inline overlay  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: Eshel Yaron <me@eshelyaron.com>
 ;; Maintainer: Eshel Yaron <me@eshelyaron.com>
@@ -52,6 +52,8 @@
 
 ;;; Code:
 
+(require 'mwheel)
+
 (defgroup completion-preview nil
   "In-buffer completion preview."
   :group 'completion)
@@ -133,10 +135,14 @@ If this option is nil, these commands do not display any 
message."
   "<down-mouse-1>" #'completion-preview-insert
   "C-<down-mouse-1>" #'completion-at-point
   "<down-mouse-2>" #'completion-at-point
-  (format "<%s>" mouse-wheel-up-event)             
#'completion-preview-prev-candidate
-  (format "<%s>" mouse-wheel-up-alternate-event)   
#'completion-preview-prev-candidate
-  (format "<%s>" mouse-wheel-down-event)           
#'completion-preview-next-candidate
-  (format "<%s>" mouse-wheel-down-alternate-event) 
#'completion-preview-next-candidate)
+  ;; BEWARE: `mouse-wheel-UP-event' corresponds to `wheel-DOWN' events
+  ;; and vice versa!!
+  "<wheel-up>"     #'completion-preview-prev-candidate
+  "<wheel-down>"   #'completion-preview-next-candidate
+  (key-description (vector mouse-wheel-up-event))
+  #'completion-preview-next-candidate
+  (key-description (vector mouse-wheel-down-event))
+  #'completion-preview-prev-candidate)
 
 (defvar-local completion-preview--overlay nil)
 
@@ -189,10 +195,24 @@ Completion Preview mode avoids updating the preview after 
these commands.")
   "Return property PROP of the completion preview overlay."
   (overlay-get completion-preview--overlay prop))
 
+(defun completion-preview--window-selection-change (window)
+  "Hide completion preview in WINDOW after switching to another window.
+Completion Preview mode adds this function to
+`window-selection-change-functions', which see."
+  (unless (or (eq window (selected-window))
+              (eq window (minibuffer-selected-window)))
+    (with-current-buffer (window-buffer window)
+      (completion-preview-active-mode -1))))
+
 (define-minor-mode completion-preview-active-mode
   "Mode for when the completion preview is shown."
   :interactive nil
-  (unless completion-preview-active-mode (completion-preview-hide)))
+  (if completion-preview-active-mode
+      (add-hook 'window-selection-change-functions
+                #'completion-preview--window-selection-change nil t)
+    (remove-hook 'window-selection-change-functions
+                 #'completion-preview--window-selection-change t)
+    (completion-preview-hide)))
 
 (defun completion-preview--try-table (table beg end props)
   "Check TABLE for a completion matching the text between BEG and END.
diff --git a/lisp/completion.el b/lisp/completion.el
index b0167412b20..ab7f2a7bc52 100644
--- a/lisp/completion.el
+++ b/lisp/completion.el
@@ -1,6 +1,6 @@
 ;;; completion.el --- dynamic word-completion code  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1990-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: abbrev convenience
diff --git a/lisp/composite.el b/lisp/composite.el
index 3ae3e64d5b9..326e8f10aee 100644
--- a/lisp/composite.el
+++ b/lisp/composite.el
@@ -1,6 +1,6 @@
 ;;; composite.el --- support character composition  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
 ;;   2008, 2009, 2010, 2011
diff --git a/lisp/cus-dep.el b/lisp/cus-dep.el
index 00f497d4e90..55965841a76 100644
--- a/lisp/cus-dep.el
+++ b/lisp/cus-dep.el
@@ -1,6 +1,6 @@
 ;;; cus-dep.el --- find customization dependencies  -*- lexical-binding: t; -*-
 ;;
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: internal
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index 6442ffeac24..38b6ec984ab 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -1,6 +1,6 @@
 ;;; cus-edit.el --- tools for customizing Emacs and Lisp packages -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Maintainer: emacs-devel@gnu.org
@@ -177,7 +177,7 @@
 
 (defgroup wp nil
   "Support for editing text files.
-Use group `text' for this instead.  This group is deprecated."
+Use group `text' for this instead.  This group is obsolete."
   :group 'emacs)
 
 (defgroup text nil
@@ -5389,9 +5389,49 @@ The following properties have special meanings for this 
widget:
   :hidden-states '(standard)
   :action #'custom-icon-action
   :custom-set #'custom-icon-set
-  :custom-reset-current #'custom-redraw)
-  ;; Not implemented yet.
-  ;; :custom-reset-saved 'custom-icon-reset-saved)
+  :custom-mark-to-save #'custom-icon-mark-to-save
+  :custom-reset-current #'custom-redraw
+  :custom-reset-saved #'custom-icon-reset-saved
+  :custom-state-set-and-redraw #'custom-icon-state-set-and-redraw
+  :custom-reset-standard #'custom-icon-reset-standard
+  :custom-mark-to-reset-standard #'custom-icon-mark-to-reset-standard)
+
+(defun custom-icon-mark-to-save (widget)
+  "Mark user customization for icon edited by WIDGET to be saved later."
+  (let* ((icon (widget-value widget))
+         (value (custom--icons-widget-value
+                 (car (widget-get widget :children)))))
+    (custom-push-theme 'theme-icon icon 'user 'set value)))
+
+(defun custom-icon-reset-saved (widget)
+  "Restore icon customized by WIDGET to the icon's default attributes.
+
+If there's a theme value for the icon, resets to that.  Otherwise, resets to
+its standard value."
+  (let* ((icon (widget-value widget)))
+    (custom-push-theme 'theme-icon icon 'user 'reset)
+    (custom-icon-state-set widget)
+    (custom-redraw widget)))
+
+(defun custom-icon-state-set-and-redraw (widget)
+  "Set state of icon widget WIDGET and redraw it with up-to-date settings."
+  (custom-icon-state-set widget)
+  (custom-redraw-magic widget))
+
+(defun custom-icon-reset-standard (widget)
+  "Reset icon edited by WIDGET to its standard value."
+  (let* ((icon (widget-value widget))
+         (themes (get icon 'theme-icon)))
+    (dolist (theme themes)
+      (custom-push-theme 'theme-icon icon (car theme) 'reset))
+    (custom-save-all))
+  (widget-put widget :custom-state 'unknown)
+  (custom-redraw widget))
+
+(defun custom-icon-mark-to-reset-standard (widget)
+  "Reset icon edited by WIDGET to its standard value."
+  ;; Don't mark for now, there aren't that many icons.
+  (custom-icon-reset-standard widget))
 
 (defvar custom-icon-extended-menu
   (let ((map (make-sparse-keymap)))
@@ -5410,6 +5450,18 @@ The following properties have special meanings for this 
widget:
                   :enable (memq
                            (widget-get custom-actioned-widget :custom-state)
                            '(modified changed))))
+    (define-key-after map [custom-icon-reset-saved]
+      '(menu-item "Revert This Session's Customization"
+                  custom-icon-reset-saved
+                  :enable (memq
+                           (widget-get custom-actioned-widget :custom-state)
+                           '(modified set changed rogue))))
+    (when (or custom-file init-file-user)
+      (define-key-after map [custom-icon-reset-standard]
+        '(menu-item "Erase Customization" custom-icon-reset-standard
+                    :enable (memq
+                             (widget-get custom-actioned-widget :custom-state)
+                             '(modified set changed saved rogue)))))
     map)
   "A menu for `custom-icon' widgets.
 Used in `custom-icon-action' to show a menu to the user.")
diff --git a/lisp/cus-face.el b/lisp/cus-face.el
index a3a27263a7c..47afa841f5e 100644
--- a/lisp/cus-face.el
+++ b/lisp/cus-face.el
@@ -1,6 +1,6 @@
 ;;; cus-face.el --- customization support for faces  -*- lexical-binding: t; 
-*-
 ;;
-;; Copyright (C) 1996-1997, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 1999-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: help, faces
@@ -32,7 +32,7 @@
 (defun custom-declare-face (face spec doc &rest args)
   "Like `defface', but with FACE evaluated as a normal argument."
   (when (and doc
-             (not (stringp doc)))
+             (not (documentation-stringp doc)))
     (error "Invalid (or missing) doc string %S" doc))
   (unless (get face 'face-defface-spec)
     (face-spec-set face (purecopy spec) 'face-defface-spec)
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index 6d83aaf4d14..7e0b64e9067 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -1,6 +1,6 @@
 ;;; cus-start.el --- define customization properties of builtins  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1997, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: internal
@@ -606,6 +606,8 @@ This should only be chosen under exceptional circumstances,
 since it could result in memory overflow and make Emacs crash."
                                              nil))
                               "27.1")
+             ;; w32fns.c
+             (w32-follow-system-dark-mode display boolean "30.1")
             ;; window.c
             (temp-buffer-show-function windows (choice (const nil) function))
             (next-screen-context-lines windows integer)
diff --git a/lisp/cus-theme.el b/lisp/cus-theme.el
index ccd8ba51c9d..1aa995a1d91 100644
--- a/lisp/cus-theme.el
+++ b/lisp/cus-theme.el
@@ -1,6 +1,6 @@
 ;;; cus-theme.el --- custom theme creation user interface  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <alex@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/custom.el b/lisp/custom.el
index 5c134ff7f13..a19b14aaf8a 100644
--- a/lisp/custom.el
+++ b/lisp/custom.el
@@ -1,6 +1,6 @@
 ;;; custom.el --- tools for declaring and initializing options  -*- 
lexical-binding: t -*-
 ;;
-;; Copyright (C) 1996-1997, 1999, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1996-1997, 1999, 2001-2024 Free Software Foundation,
 ;; Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el
index a4b4d07b688..853c0f4b290 100644
--- a/lisp/dabbrev.el
+++ b/lisp/dabbrev.el
@@ -1,6 +1,6 @@
 ;;; dabbrev.el --- dynamic abbreviation package  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-1986, 1992, 1994, 1996-1997, 2000-2023 Free
+;; Copyright (C) 1985-1986, 1992, 1994, 1996-1997, 2000-2024 Free
 ;; Software Foundation, Inc.
 
 ;; Author: Don Morrison
diff --git a/lisp/delim-col.el b/lisp/delim-col.el
index 1bbcaf736f1..3e744168cd0 100644
--- a/lisp/delim-col.el
+++ b/lisp/delim-col.el
@@ -1,6 +1,6 @@
 ;;; delim-col.el --- prettify all columns in a region or rectangle  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
 ;; Old-Version: 2.1
diff --git a/lisp/delsel.el b/lisp/delsel.el
index 48656bc8ba3..df99a56d7bc 100644
--- a/lisp/delsel.el
+++ b/lisp/delsel.el
@@ -1,6 +1,6 @@
 ;;; delsel.el --- delete selection if you insert  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1992, 1997-1998, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1992, 1997-1998, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Matthieu Devin <devin@lucid.com>
diff --git a/lisp/descr-text.el b/lisp/descr-text.el
index 4834c2eb7ba..eeab995c37d 100644
--- a/lisp/descr-text.el
+++ b/lisp/descr-text.el
@@ -1,6 +1,6 @@
 ;;; descr-text.el --- describe text mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1994-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Boris Goldowsky <boris@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/desktop.el b/lisp/desktop.el
index f096f13ab80..3fa09ce6a41 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -1,6 +1,6 @@
 ;;; desktop.el --- save partial status of Emacs when killed -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1993-1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993-1995, 1997, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Morten Welinder <terra@diku.dk>
@@ -163,13 +163,22 @@ Used at desktop read to provide backward compatibility.")
 (define-minor-mode desktop-save-mode
   "Toggle desktop saving (Desktop Save mode).
 
-When Desktop Save mode is enabled, the state of Emacs is saved from
-one session to another.  In particular, Emacs will save the desktop when
-it exits (this may prompt you; see the option `desktop-save').  The next
-time Emacs starts, if this mode is active it will restore the desktop.
+When Desktop Save mode is enabled, the state of Emacs is saved from one
+session to another.  The saved Emacs \"desktop configuration\" includes the
+buffers, their file names, major modes, buffer positions, window and frame
+configuration, and some important global variables.
 
-To manually save the desktop at any time, use the command `\\[desktop-save]'.
-To load it, use `\\[desktop-read]'.
+To enable this feature for future sessions, customize `desktop-save-mode'
+to t, or add this line in your init file:
+
+    (desktop-save-mode 1)
+
+When this mode is enabled, Emacs will save the desktop when it exits
+(this may prompt you, see the option `desktop-save').  The next time
+Emacs starts, if this mode is active it will restore the desktop.
+
+To manually save the desktop at any time, use the command \\[desktop-save].
+To load it, use \\[desktop-read].
 
 Once a desktop file exists, Emacs will auto-save it according to the
 option `desktop-auto-save-timeout'.
@@ -293,7 +302,7 @@ May be used to show a dired buffer."
   :version "22.1")
 
 (defcustom desktop-not-loaded-hook nil
-  "Normal hook run when the user declines to re-use a desktop file.
+  "Normal hook run when the user declines to reuse a desktop file.
 Run in the directory in which the desktop file was found.
 May be used to deal with accidental multiple Emacs jobs."
   :type 'hook
diff --git a/lisp/dframe.el b/lisp/dframe.el
index 995bb0a25d1..4031e0784c2 100644
--- a/lisp/dframe.el
+++ b/lisp/dframe.el
@@ -1,6 +1,6 @@
 ;;; dframe.el --- dedicate frame support modes  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: file, tags, tools
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 1a17ed749e8..a2ce3083cfe 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -1,6 +1,6 @@
 ;;; dired-aux.el --- less commonly used parts of dired -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>.
 ;; Maintainer: emacs-devel@gnu.org
@@ -1367,7 +1367,8 @@ after adding own commands to the composite list."
   (let* ((xdg-mime (when (executable-find "xdg-mime")
                      (string-trim-right
                       (shell-command-to-string
-                       (concat "xdg-mime query filetype " (car files))))))
+                       (concat "xdg-mime query filetype "
+                               (shell-quote-argument (car files)))))))
          (xdg-mime-apps (unless (string-empty-p xdg-mime)
                           (xdg-mime-apps xdg-mime)))
          (xdg-commands
@@ -1401,6 +1402,42 @@ after adding own commands to the composite list."
   "Populate COMMANDS by the `open' command."
   (append (ensure-list shell-command-guess-open) commands))
 
+(declare-function w32-shell-execute "w32fns.c")
+
+(defun dired-do-open (&optional arg)
+  "Open all marked (or next ARG) files using an external program.
+This \"opens\" the file(s) using the external command that is most
+appropriate for the file(s) according to the system conventions.
+If files are marked, run the command on each marked file.  Otherwise,
+run it on the next ARG files, or on the file at mouse-click, or on the
+file at point.  The appropriate command to \"open\" a file on each
+system is determined by `shell-command-guess-open'."
+  (interactive "P" dired-mode)
+  (let ((files (if (mouse-event-p last-nonmenu-event)
+                   (save-excursion
+                     (mouse-set-point last-nonmenu-event)
+                     (dired-get-marked-files nil arg))
+                 (dired-get-marked-files nil arg)))
+        (command shell-command-guess-open))
+    (when (and (memq system-type '(windows-nt))
+               (equal command "start"))
+      (setq command "open"))
+    (when command
+      (dolist (file files)
+        (cond
+         ((memq system-type '(gnu/linux))
+          (call-process command nil 0 nil file))
+         ((memq system-type '(ms-dos))
+          (shell-command (concat command " " (shell-quote-argument file))))
+         ((memq system-type '(windows-nt))
+          (w32-shell-execute command (convert-standard-filename file)))
+         ((memq system-type '(cygwin))
+          (call-process command nil nil nil file))
+         ((memq system-type '(darwin))
+          (start-process (concat command " " file) nil command file))
+         (t
+          (error "Open not supported on this system")))))))
+
 
 ;;; Commands that delete or redisplay part of the dired buffer
 
@@ -1430,7 +1467,7 @@ With a prefix argument, kill that many lines starting 
with the current line.
 (defun dired-do-kill-lines (&optional arg fmt init-count)
   "Remove all marked lines, or the next ARG lines.
 The files or directories on those lines are _not_ deleted.  Only the
-Dired listing is affected.  To restore the removals, use `\\[revert-buffer]'.
+Dired listing is affected.  To restore the removals, use \\[revert-buffer].
 
 With a numeric prefix arg, remove that many lines going forward,
 starting with the current line.  (A negative prefix arg removes lines
@@ -2834,7 +2871,7 @@ similar to the \"-d\" option for the \"cp\" shell command.
 But if `dired-copy-dereference' is non-nil, the symbolic
 links are dereferenced and then copied, similar to the \"-L\"
 option for the \"cp\" shell command.  If ARG is a cons with
-element 4 (`\\[universal-argument]'), the inverted value of
+element 4 (\\[universal-argument]), the inverted value of
 `dired-copy-dereference' will be used.
 
 Also see `dired-do-revert-buffer'."
diff --git a/lisp/dired-x.el b/lisp/dired-x.el
index 04b3c783084..62fdd916e69 100644
--- a/lisp/dired-x.el
+++ b/lisp/dired-x.el
@@ -1,6 +1,6 @@
 ;;; dired-x.el --- extra Dired functionality  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
 ;;     Lawrence R. Dodd <dodd@roebling.poly.edu>
@@ -613,7 +613,8 @@ you can relist single subdirs using \\[dired-do-redisplay]."
       (insert "  "
              (directory-file-name (file-name-directory default-directory))
              ":\n"))
-  (dired-mode dirname (or switches dired-listing-switches))
+  (dired-mode
+   dirname (or switches (connection-local-value dired-listing-switches)))
   (setq mode-name "Virtual Dired"
         revert-buffer-function 'dired-virtual-revert
         dired-subdir-alist nil)
diff --git a/lisp/dired.el b/lisp/dired.el
index 97645c731c8..cef93ab757c 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -1,6 +1,6 @@
 ;;; dired.el --- directory-browsing commands -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-1986, 1992-1997, 2000-2023 Free Software
+;; Copyright (C) 1985-1986, 1992-1997, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
@@ -75,7 +75,9 @@ each option.
 
 On systems such as MS-DOS and MS-Windows, which use `ls' emulation in Lisp,
 some of the `ls' switches are not supported; see the doc string of
-`insert-directory' in `ls-lisp.el' for more details."
+`insert-directory' in `ls-lisp.el' for more details.
+
+For remote Dired buffers, this option supports connection-local values."
   :type 'string
   :group 'dired)
 
@@ -119,12 +121,11 @@ checks this alist to enable globstar in the shell 
subprocess.")
 (defcustom dired-use-ls-dired 'unspecified
   "Non-nil means Dired should pass the \"--dired\" option to \"ls\".
 If nil, don't pass \"--dired\" to \"ls\".
-The special value of `unspecified' means to check whether \"ls\"
-supports the \"--dired\" option, and save the result in this
-variable.  This is performed the first time `dired-insert-directory'
-is invoked.  (If `ls-lisp' is used by default, the test is performed
-only if `ls-lisp-use-insert-directory-program' is non-nil, i.e., if
-Dired actually uses \"ls\".)
+The special value of `unspecified' means to check whether
+`insert-directory-program' supports the \"--dired\" option, and save
+the result in this variable.
+This is performed the first time `dired-insert-directory'
+invokes `insert-directory-program'.
 
 Note that if you set this option to nil, either through choice or
 because your \"ls\" program does not support \"--dired\", Dired
@@ -1383,7 +1384,8 @@ The return value is the target column for the file names."
                ;; is passed in directory name syntax
                ;; if it was the name of a directory at all.
                (file-name-directory dirname)))
-      (or switches (setq switches dired-listing-switches))
+      (or switches
+          (setq switches (connection-local-value dired-listing-switches)))
       (if mode (funcall mode)
         (dired-mode dir-or-list switches))
       ;; default-directory and dired-actual-switches are set now
@@ -1521,18 +1523,21 @@ wildcards, erases the buffer, and builds the 
subdir-alist anew
       (setq dir dired-directory
            file-list nil))
     (setq dir (expand-file-name dir))
-    (if (and (equal "" (file-name-nondirectory dir))
-            (not file-list))
-       ;; If we are reading a whole single directory...
-       (dired-insert-directory dir dired-actual-switches nil nil t)
-      (if (and (not (insert-directory-wildcard-in-dir-p dir))
-               (not (file-readable-p
-                    (directory-file-name (file-name-directory dir)))))
-         (error "Directory %s inaccessible or nonexistent" dir))
+    (cond
+     ((and (equal "" (file-name-nondirectory dir))
+           (not file-list))
+      ;; If we are reading a whole single directory...
+      (dired-insert-directory dir dired-actual-switches nil
+                              (not (file-directory-p dir)) t))
+     ((not (or (insert-directory-wildcard-in-dir-p dir)
+               (file-readable-p
+                (directory-file-name (file-name-directory dir)))))
+      (error "Directory %s inaccessible or nonexistent" dir))
+     (t
       ;; Else treat it as a wildcard spec
       ;; unless we have an explicit list of files.
       (dired-insert-directory dir dired-actual-switches
-                             file-list (not file-list) t))))
+       file-list (not file-list) t)))))
 
 (defun dired-align-file (beg end)
   "Align the fields of a file to the ones of surrounding lines.
@@ -1541,7 +1546,7 @@ BEG..END is the line where the file info is located."
   ;; hold the largest element ("largest" in the current invocation, of
   ;; course).  So when a single line is output, the size of each field is
   ;; just big enough for that one output.  Thus when dired refreshes one
-  ;; line, the alignment if this line w.r.t the rest is messed up because
+  ;; line, the alignment of this line w.r.t the rest is messed up because
   ;; the fields of that one line will generally be smaller.
   ;;
   ;; To work around this problem, we here add spaces to try and
@@ -1608,14 +1613,21 @@ BEG..END is the line where the file info is located."
                 ;; the beginning or the end of the next field, depending on
                 ;; whether this field is left or right aligned).
                 (align-pt-offset
-                 (save-excursion
-                   (goto-char other)
-                   (move-to-column curcol)
-                   (when (looking-at
-                          (concat
-                           (if (eq (char-before) ?\s) " *" "[^ ]* *")
-                           (if num-align "[0-9][^ ]*")))
-                     (- (match-end 0) (match-beginning 0)))))
+                  ;; It is never TRT to realign the first column of
+                  ;; file's data.  But the code below does attempt to
+                  ;; realign the first column if there's no whitespace
+                  ;; before it, so we force it to let the first column
+                  ;; alone.
+                  (if (zerop curcol)
+                      0
+                   (save-excursion
+                     (goto-char other)
+                     (move-to-column curcol)
+                     (when (looking-at
+                            (concat
+                             (if (eq (char-before) ?\s) " *" "[^ ]* *")
+                             (if num-align "[0-9][^ ]*")))
+                       (- (match-end 0) (match-beginning 0))))))
                 ;; Now, the number of spaces to insert is align-pt-offset
                 ;; minus the distance to the equivalent point on the
                 ;; current line.
@@ -1640,9 +1652,6 @@ BEG..END is the line where the file info is located."
          (skip-chars-forward "^ ") (skip-chars-forward " "))
        (set-marker file nil)))))
 
-
-(defvar ls-lisp-use-insert-directory-program)
-
 (defun dired-check-switches (switches short &optional long)
   "Return non-nil if the string SWITCHES matches LONG or SHORT format."
   (let (case-fold-search)
@@ -1673,11 +1682,8 @@ If HDR is non-nil, insert a header line with the 
directory name."
         (remotep (file-remote-p dir))
        end)
     (if (and
-        ;; Don't try to invoke `ls' if we are on DOS/Windows where
-        ;; ls-lisp emulation is used, except if they want to use `ls'
-        ;; as indicated by `ls-lisp-use-insert-directory-program'.
-        (not (and (featurep 'ls-lisp)
-                  (null ls-lisp-use-insert-directory-program)))
+        ;; Don't try to invoke `ls' if ls-lisp emulation should be used.
+        (files--use-insert-directory-program-p)
          ;; FIXME: Big ugly hack for Eshell's eshell-ls-use-in-dired.
          (not (bound-and-true-p eshell-ls-use-in-dired))
         (or remotep
@@ -1698,8 +1704,9 @@ see `dired-use-ls-dired' for more details.")
         (unless remotep
          (setq switches (concat "--dired -N " switches))))
     ;; Expand directory wildcards and fill file-list.
-    (let ((dir-wildcard (insert-directory-wildcard-in-dir-p dir)))
-      (cond (dir-wildcard
+    (let ((dir-wildcard (and (null file-list) wildcard
+                             (insert-directory-wildcard-in-dir-p dir))))
+      (cond ((and dir-wildcard (files--use-insert-directory-program-p))
              (setq switches (concat "-d " switches))
              (let* ((default-directory (car dir-wildcard))
                     (script (format "%s %s %s"
@@ -1722,78 +1729,81 @@ see `dired-use-ls-dired' for more details.")
                  (user-error
                   "%s: No files matching wildcard" (cdr dir-wildcard)))
                (insert-directory-clean (point) switches)))
-            (t
-             ;; We used to specify the C locale here, to force English
-             ;; month names; but this should not be necessary any
-             ;; more, with the new value of
-             ;; `directory-listing-before-filename-regexp'.
-             (if file-list
-                (dolist (f file-list)
-                  (let ((beg (point)))
-                    (insert-directory f switches nil nil)
-                    ;; Re-align fields, if necessary.
-                    (dired-align-file beg (point))))
-               (insert-directory dir switches wildcard (not wildcard))))))
-    ;; Quote certain characters, unless ls quoted them for us.
-    (if (not (dired-switches-escape-p dired-actual-switches))
+            ;; We used to specify the C locale here, to force English
+            ;; month names; but this should not be necessary any
+            ;; more, with the new value of
+            ;; `directory-listing-before-filename-regexp'.
+            ((or file-list dir-wildcard)
+            (let ((default-directory
+                   (or (car dir-wildcard) default-directory)))
+              (dolist (f (or file-list
+                             (file-expand-wildcards (cdr dir-wildcard))))
+                (let ((beg (point)))
+                  (insert-directory f switches nil nil)
+                  ;; Re-align fields, if necessary.
+                  (dired-align-file beg (point))))))
+           (t
+             (insert-directory dir switches wildcard (not wildcard))))
+      ;; Quote certain characters, unless ls quoted them for us.
+      (if (not (dired-switches-escape-p dired-actual-switches))
+         (save-excursion
+           (setq end (point-marker))
+           (goto-char opoint)
+           (while (search-forward "\\" end t)
+             (replace-match (apply #'propertize
+                                   "\\\\"
+                                   (text-properties-at (match-beginning 0)))
+                            nil t))
+           (goto-char opoint)
+           (while (search-forward "\^m" end t)
+             (replace-match (apply #'propertize
+                                   "\\015"
+                                   (text-properties-at (match-beginning 0)))
+                            nil t))
+           (set-marker end nil))
+       ;; Replace any newlines in DIR with literal "\n"s, for the sake
+       ;; of the header line.  To disambiguate a literal "\n" in the
+       ;; actual dirname, we also replace "\" with "\\".
+       ;; Personally, I think this should always be done, irrespective
+       ;; of the value of dired-actual-switches, because:
+       ;;  i) Dired simply does not work with an unescaped newline in
+       ;;  the directory name used in the header (bug=10469#28), and
+       ;;  ii) "\" is always replaced with "\\" in the listing, so doing
+       ;;  it in the header as well makes things consistent.
+       ;; But at present it is only done if "-b" is in ls-switches,
+       ;; because newlines in dirnames are uncommon, and people may
+       ;; have gotten used to seeing unescaped "\" in the headers.
+       ;; Note: adjust dired-build-subdir-alist if you change this.
+       (setq dir (string-replace "\\" "\\\\" dir)
+              dir (string-replace "\n" "\\n" dir)))
+      ;; If we used --dired and it worked, the lines are already indented.
+      ;; Otherwise, indent them.
+      (unless (save-excursion
+               (goto-char opoint)
+               (looking-at-p "  "))
+       (let ((indent-tabs-mode nil))
+         (indent-rigidly opoint (point) 2)))
+      ;; Insert text at the beginning to standardize things.
+      (let ((content-point opoint))
        (save-excursion
-         (setq end (point-marker))
-         (goto-char opoint)
-         (while (search-forward "\\" end t)
-           (replace-match (apply #'propertize
-                                 "\\\\"
-                                 (text-properties-at (match-beginning 0)))
-                          nil t))
          (goto-char opoint)
-         (while (search-forward "\^m" end t)
-           (replace-match (apply #'propertize
-                                 "\\015"
-                                 (text-properties-at (match-beginning 0)))
-                          nil t))
-         (set-marker end nil))
-      ;; Replace any newlines in DIR with literal "\n"s, for the sake
-      ;; of the header line.  To disambiguate a literal "\n" in the
-      ;; actual dirname, we also replace "\" with "\\".
-      ;; Personally, I think this should always be done, irrespective
-      ;; of the value of dired-actual-switches, because:
-      ;;  i) Dired simply does not work with an unescaped newline in
-      ;;  the directory name used in the header (bug=10469#28), and
-      ;;  ii) "\" is always replaced with "\\" in the listing, so doing
-      ;;  it in the header as well makes things consistent.
-      ;; But at present it is only done if "-b" is in ls-switches,
-      ;; because newlines in dirnames are uncommon, and people may
-      ;; have gotten used to seeing unescaped "\" in the headers.
-      ;; Note: adjust dired-build-subdir-alist if you change this.
-      (setq dir (string-replace "\\" "\\\\" dir)
-            dir (string-replace "\n" "\\n" dir)))
-    ;; If we used --dired and it worked, the lines are already indented.
-    ;; Otherwise, indent them.
-    (unless (save-excursion
-             (goto-char opoint)
-             (looking-at-p "  "))
-      (let ((indent-tabs-mode nil))
-       (indent-rigidly opoint (point) 2)))
-    ;; Insert text at the beginning to standardize things.
-    (let ((content-point opoint))
-      (save-excursion
-       (goto-char opoint)
-       (when (and (or hdr wildcard)
-                  (not (and (looking-at "^  \\(.*\\):$")
-                            (file-name-absolute-p (match-string 1)))))
-         ;; Note that dired-build-subdir-alist will replace the name
-         ;; by its expansion, so it does not matter whether what we insert
-         ;; here is fully expanded, but it should be absolute.
-         (insert "  " (or (car-safe (insert-directory-wildcard-in-dir-p dir))
-                           (directory-file-name (file-name-directory dir)))
-                  ":\n")
-         (setq content-point (point)))
-       (when wildcard
-         ;; Insert "wildcard" line where "total" line would be for a full dir.
-         (insert "  wildcard " (or (cdr-safe 
(insert-directory-wildcard-in-dir-p dir))
-                                    (file-name-nondirectory dir))
-                  "\n"))
-        (setq content-point (dired--insert-disk-space opoint dir)))
-      (dired-insert-set-properties content-point (point)))))
+         (when (and (or hdr wildcard)
+                    (not (and (looking-at "^  \\(.*\\):$")
+                              (file-name-absolute-p (match-string 1)))))
+           ;; Note that dired-build-subdir-alist will replace the name
+           ;; by its expansion, so it does not matter whether what we insert
+           ;; here is fully expanded, but it should be absolute.
+           (insert "  " (or (car-safe dir-wildcard)
+                             (directory-file-name (file-name-directory dir)))
+                    ":\n")
+           (setq content-point (point)))
+         (when wildcard
+           ;; Insert "wildcard" line where "total" line would be for a full 
dir.
+           (insert "  wildcard " (or (cdr-safe 
(insert-directory-wildcard-in-dir-p dir))
+                                      (file-name-nondirectory dir))
+                    "\n"))
+          (setq content-point (dired--insert-disk-space opoint dir)))
+        (dired-insert-set-properties content-point (point))))))
 
 (defun dired--insert-disk-space (beg file)
   ;; Try to insert the amount of free space.
@@ -2007,9 +2017,22 @@ mouse-2: visit this file in other window"
               keymap ,(let* ((current-dir dir)
                              (click (lambda ()
                                       (interactive)
-                                      (if (assoc current-dir 
dired-subdir-alist)
-                                          (dired-goto-subdir current-dir)
-                                        (dired current-dir)))))
+                                      (cond
+                                       ((assoc current-dir dired-subdir-alist)
+                                        (dired-goto-subdir current-dir))
+                                       ;; If there is a wildcard chars
+                                       ;; in the directory name, don't
+                                       ;; use the alternate file machinery
+                                       ;; which tries to keep only one
+                                       ;; dired buffer open at once.
+                                       ;;
+                                       ;; FIXME: Is this code path reachable?
+                                       ((insert-directory-wildcard-in-dir-p
+                                         current-dir)
+                                        (dired current-dir))
+                                       (t
+                                        (dired--find-possibly-alternative-file
+                                         current-dir))))))
                         (define-keymap
                           "<mouse-2>" click
                           "<follow-link>" 'mouse-face
@@ -2591,6 +2614,9 @@ Do so according to the former subdir alist 
OLD-SUBDIR-ALIST."
     ["Delete Image Tag..." image-dired-delete-tag
      :help "Delete image tag from current or marked files"]))
 
+(declare-function shell-command-guess "dired-aux" (files))
+(defvar shell-command-guess-open)
+
 (defun dired-context-menu (menu click)
   "Populate MENU with Dired mode commands at CLICK."
   (when (mouse-posn-property (event-start click) 'dired-filename)
@@ -2606,6 +2632,9 @@ Do so according to the former subdir alist 
OLD-SUBDIR-ALIST."
            :help "Edit file at mouse click"]
           ["Find in Other Window" dired-mouse-find-file-other-window
            :help "Edit file at mouse click in other window"]
+          ,@(when shell-command-guess-open
+              '(["Open" dired-do-open
+                 :help "Open externally"]))
           ,@(when commands
               (list (cons "Open With"
                           (append
@@ -2708,7 +2737,8 @@ Keybindings:
        (expand-file-name (if (listp dired-directory)
                              (car dired-directory)
                            dired-directory)))
-  (setq-local dired-actual-switches (or switches dired-listing-switches))
+  (setq-local dired-actual-switches
+              (or switches (connection-local-value dired-listing-switches)))
   (setq-local font-lock-defaults
               '(dired-font-lock-keywords t nil nil beginning-of-line))
   (setq-local desktop-save-buffer 'dired-desktop-buffer-misc-data)
@@ -2787,7 +2817,9 @@ is controlled by `dired-movement-style'."
     (dired--trivial-next-line arg)))
 
 (defun dired--move-to-next-line (arg jumpfun)
-  (let ((old-position (progn
+  (let ((wrapped nil)
+        (old-arg arg)
+        (old-position (progn
                         ;; It's always true that we should move
                         ;; to the filename when possible.
                         (dired-move-to-filename)
@@ -2802,16 +2834,27 @@ is controlled by `dired-movement-style'."
       (when (= old-position (point))
         ;; Now point is at beginning/end of movable area,
         ;; but it still wants to move farther.
-        (if (eq dired-movement-style 'cycle)
-            ;; `cycle': go to the other end.
+        (cond
+         ;; `cycle': go to the other end.
+         ((eq dired-movement-style 'cycle)
+          ;; Argument not changing on the second wrap
+          ;; means infinite loop with no files found.
+          (if (and wrapped (eq old-arg arg))
+              (setq arg 0)
             (goto-char (if (cl-plusp moving-down)
                            (point-min)
-                         (point-max)))
-          ;; `bounded': go back to the last non-empty line.
-          (while (dired-between-files)
-            (funcall jumpfun (- moving-down)))
+                         (point-max))))
+          (setq wrapped t))
+         ;; `bounded': go back to the last non-empty line.
+         ((eq dired-movement-style 'bounded)
+          (while (and (dired-between-files) (not (zerop arg)))
+            (funcall jumpfun (- moving-down))
+            ;; Point not moving means infinite loop.
+            (if (= old-position (point))
+                (setq arg 0)
+              (setq old-position (point))))
           ;; Encountered a boundary, so let's stop movement.
-          (setq arg moving-down)))
+          (setq arg (if (dired-between-files) 0 moving-down)))))
       (unless (dired-between-files)
         ;; Has moved to a non-empty line.  This movement does
         ;; make sense.
@@ -4983,14 +5026,15 @@ Ask means pop up a menu for the user to select one of 
copy, move or link."
 
 (defun dired-desktop-save-p ()
   "Should `dired-directory' be desktop saved?"
-  (if (consp dired-directory)
-      (not (string-match-p desktop-files-not-to-save (car dired-directory)))
-    (not (string-match-p desktop-files-not-to-save dired-directory))))
+  (or (null desktop-files-not-to-save)
+      (and (stringp desktop-files-not-to-save)
+           (if (consp dired-directory)
+               (not (string-match-p desktop-files-not-to-save (car 
dired-directory)))
+             (not (string-match-p desktop-files-not-to-save 
dired-directory))))))
 
 (defun dired-desktop-buffer-misc-data (dirname)
   "Auxiliary information to be saved in desktop file."
-  (when (and (stringp desktop-files-not-to-save)
-             (dired-desktop-save-p))
+  (when (dired-desktop-save-p)
     (cons
      ;; Value of `dired-directory'.
      (if (consp dired-directory)
diff --git a/lisp/dirtrack.el b/lisp/dirtrack.el
index b171caa1333..07e176b8eea 100644
--- a/lisp/dirtrack.el
+++ b/lisp/dirtrack.el
@@ -1,6 +1,6 @@
 ;;; dirtrack.el --- Directory Tracking by watching the prompt  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Peter Breton <pbreton@cs.umb.edu>
 ;; Created: Sun Nov 17 1996
diff --git a/lisp/disp-table.el b/lisp/disp-table.el
index e8eef0010ec..50428d911a3 100644
--- a/lisp/disp-table.el
+++ b/lisp/disp-table.el
@@ -1,6 +1,6 @@
 ;;; disp-table.el --- functions for dealing with char tables  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1987, 1994-1995, 1999, 2001-2023 Free Software
+;; Copyright (C) 1987, 1994-1995, 1999, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Erik Naggum <erik@naggum.no>
diff --git a/lisp/display-fill-column-indicator.el 
b/lisp/display-fill-column-indicator.el
index 45bdca2f5a5..ef0f2d4981c 100644
--- a/lisp/display-fill-column-indicator.el
+++ b/lisp/display-fill-column-indicator.el
@@ -1,6 +1,6 @@
 ;;; display-fill-column-indicator.el --- interface for 
display-fill-column-indicator -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: convenience
diff --git a/lisp/display-line-numbers.el b/lisp/display-line-numbers.el
index 4f87ffd0e22..c6ee588484c 100644
--- a/lisp/display-line-numbers.el
+++ b/lisp/display-line-numbers.el
@@ -1,6 +1,6 @@
 ;;; display-line-numbers.el --- interface for display-line-numbers -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: convenience
diff --git a/lisp/dnd.el b/lisp/dnd.el
index 936534fa32c..22cb18359a3 100644
--- a/lisp/dnd.el
+++ b/lisp/dnd.el
@@ -1,6 +1,6 @@
 ;;; dnd.el --- drag and drop support  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Jan Djärv <jan.h.d@swipnet.se>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index 2fdb49f3e42..c4b384c35c6 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -1,6 +1,6 @@
 ;;; doc-view.el --- Document viewer for Emacs -*- lexical-binding: t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Tassilo Horn <tsdh@gnu.org>
 ;; Keywords: files, pdf, ps, dvi, djvu, epub, cbz, fb2, xps, openxps
@@ -698,12 +698,12 @@ Typically \"page-%s.png\".")
     (tool-bar-local-item-from-menu 'doc-view-previous-page "last-page"
                                    map doc-view-mode-map :vert-only t
                                    :enable '(> (doc-view-current-page) 1)
-                                   :help "Move to the next page.")
+                                   :help "Move to the previous page.")
     (tool-bar-local-item-from-menu 'doc-view-next-page "next-page"
                                    map doc-view-mode-map :vert-only t
                                    :enable '(< (doc-view-current-page)
                                                (doc-view-last-page-number))
-                                   :help "Move to the last page.")
+                                   :help "Move to the next page.")
     map)
   "Like the default `tool-bar-map', but with additions for DocView.")
 
diff --git a/lisp/dom.el b/lisp/dom.el
index 3066673954a..b329379fdc3 100644
--- a/lisp/dom.el
+++ b/lisp/dom.el
@@ -1,6 +1,6 @@
 ;;; dom.el --- XML/HTML (etc.) DOM manipulation and searching functions -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: xml, html
@@ -288,7 +288,7 @@ If XML, generate XML instead of HTML."
        (insert ">")
         (dolist (child children)
          (if (stringp child)
-             (insert child)
+             (insert (url-insert-entities-in-string child))
            (setq non-text t)
            (when pretty
               (insert "\n" (make-string (+ column 2) ?\s)))
diff --git a/lisp/dos-fns.el b/lisp/dos-fns.el
index 42ba646a4fb..987706920c4 100644
--- a/lisp/dos-fns.el
+++ b/lisp/dos-fns.el
@@ -1,6 +1,6 @@
 ;;; dos-fns.el --- MS-Dos specific functions  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1991, 1993, 1995-1996, 2001-2023 Free Software
+;; Copyright (C) 1991, 1993, 1995-1996, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/dos-vars.el b/lisp/dos-vars.el
index f2493ac573f..1e06911836a 100644
--- a/lisp/dos-vars.el
+++ b/lisp/dos-vars.el
@@ -1,6 +1,6 @@
 ;;; dos-vars.el --- MS-Dos specific user options  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
diff --git a/lisp/dos-w32.el b/lisp/dos-w32.el
index 1db5419fc40..4302b66c4a0 100644
--- a/lisp/dos-w32.el
+++ b/lisp/dos-w32.el
@@ -1,6 +1,6 @@
 ;;; dos-w32.el --- Functions shared among MS-DOS and W32 (NT/95) platforms  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: Geoff Voelker <voelker@cs.washington.edu>
 ;; Keywords: internal
diff --git a/lisp/double.el b/lisp/double.el
index 197bfd4df6f..abc7b654259 100644
--- a/lisp/double.el
+++ b/lisp/double.el
@@ -1,6 +1,6 @@
 ;;; double.el --- support for keyboard remapping with double clicking  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1994, 1997-1998, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1994, 1997-1998, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
diff --git a/lisp/dynamic-setting.el b/lisp/dynamic-setting.el
index ebe25ab9c75..e54dce11541 100644
--- a/lisp/dynamic-setting.el
+++ b/lisp/dynamic-setting.el
@@ -1,6 +1,6 @@
 ;;; dynamic-setting.el --- Support dynamic changes  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Jan Djärv <jan.h.d@swipnet.se>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/ebuff-menu.el b/lisp/ebuff-menu.el
index 3038886034c..743b92578eb 100644
--- a/lisp/ebuff-menu.el
+++ b/lisp/ebuff-menu.el
@@ -1,6 +1,6 @@
 ;;; ebuff-menu.el --- electric-buffer-list mode  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-1986, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985-1986, 1994, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Richard Mlynarik <mly@ai.mit.edu>
diff --git a/lisp/echistory.el b/lisp/echistory.el
index 31af6eb6039..dfc1295e7ab 100644
--- a/lisp/echistory.el
+++ b/lisp/echistory.el
@@ -1,6 +1,6 @@
 ;;; echistory.el --- Electric Command History Mode  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: K. Shane Hartman
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/ecomplete.el b/lisp/ecomplete.el
index c48c3c0650f..ee79dd5fa47 100644
--- a/lisp/ecomplete.el
+++ b/lisp/ecomplete.el
@@ -1,6 +1,6 @@
 ;;; ecomplete.el --- electric completion of addresses and the like  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: mail
diff --git a/lisp/edmacro.el b/lisp/edmacro.el
index 28d210f7780..abfc380d154 100644
--- a/lisp/edmacro.el
+++ b/lisp/edmacro.el
@@ -1,6 +1,6 @@
 ;;; edmacro.el --- keyboard macro editor  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Gillespie <daveg@synaptics.com>
 ;; Keywords: abbrev
@@ -124,9 +124,9 @@ from `kmacro-edit-lossage'."
 (defun edit-kbd-macro (keys &optional prefix finish-hook store-hook)
   "Edit a keyboard macro.
 At the prompt, type any key sequence which is bound to a keyboard macro.
-Or, type `\\[kmacro-end-and-call-macro]' or \\`RET' to edit the last
-keyboard macro, `\\[view-lossage]' to edit the last 300
-keystrokes as a keyboard macro, or `\\[execute-extended-command]'
+Or, type \\[kmacro-end-and-call-macro] or \\`RET' to edit the last
+keyboard macro, \\[view-lossage] to edit the last 300
+keystrokes as a keyboard macro, or \\[execute-extended-command]
 to edit a macro by its command name.
 With a prefix argument, format the macro in a more concise way."
   (interactive
@@ -720,17 +720,15 @@ This function assumes that the events can be stored in a 
string."
            (setf (aref seq i) (logand (aref seq i) 127)))
   seq)
 
-;; These are needed in a --without-x build.
-(defvar mouse-wheel-down-event)
-(defvar mouse-wheel-up-event)
-(defvar mouse-wheel-right-event)
-(defvar mouse-wheel-left-event)
-
 (defun edmacro-fix-menu-commands (macro &optional noerror)
   (if (vectorp macro)
       (let (result)
         ;; Not preloaded in a --without-x build.
         (require 'mwheel)
+        (defvar mouse-wheel-down-event)
+        (defvar mouse-wheel-up-event)
+        (defvar mouse-wheel-right-event)
+        (defvar mouse-wheel-left-event)
        ;; Make a list of the elements.
        (setq macro (append macro nil))
        (dolist (ev macro)
@@ -746,9 +744,9 @@ This function assumes that the events can be stored in a 
string."
                ;; info is recorded in macros to make this possible.
                ((or (mouse-event-p ev) (mouse-movement-p ev)
                     (memq (event-basic-type ev)
-                          (list mouse-wheel-down-event mouse-wheel-up-event
-                                mouse-wheel-right-event
-                                mouse-wheel-left-event)))
+                          `( ,mouse-wheel-down-event ,mouse-wheel-up-event
+                             ,mouse-wheel-right-event ,mouse-wheel-left-event
+                             wheel-down wheel-up wheel-left wheel-right)))
                 nil)
                (noerror nil)
                (t
diff --git a/lisp/ehelp.el b/lisp/ehelp.el
index c0885340975..aeb5a7b4bb7 100644
--- a/lisp/ehelp.el
+++ b/lisp/ehelp.el
@@ -1,6 +1,6 @@
 ;;; ehelp.el --- bindings for electric-help mode -*- lexical-binding: t -*-
 
-;; Copyright (C) 1986, 1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 1995, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Richard Mlynarik
 ;; (according to ack.texi and authors.el)
diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el
index 223c7d89773..40618e9ef38 100644
--- a/lisp/elec-pair.el
+++ b/lisp/elec-pair.el
@@ -1,6 +1,6 @@
 ;;; elec-pair.el --- Automatic parenthesis pairing  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: João Távora <joaotavora@gmail.com>
 
diff --git a/lisp/electric.el b/lisp/electric.el
index cef5326852c..fee0bf36d7f 100644
--- a/lisp/electric.el
+++ b/lisp/electric.el
@@ -1,6 +1,6 @@
 ;;; electric.el --- window maker and Command loop for `electric' modes  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1985-1986, 1995, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985-1986, 1995, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: K. Shane Hartman
diff --git a/lisp/elide-head.el b/lisp/elide-head.el
index f74c85fdfee..808bf55a05f 100644
--- a/lisp/elide-head.el
+++ b/lisp/elide-head.el
@@ -1,6 +1,6 @@
 ;;; elide-head.el --- hide headers in files  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: outlines tools
diff --git a/lisp/emacs-lisp/advice.el b/lisp/emacs-lisp/advice.el
index 78e0151542f..32a397f0d5e 100644
--- a/lisp/emacs-lisp/advice.el
+++ b/lisp/emacs-lisp/advice.el
@@ -1,6 +1,6 @@
 ;;; advice.el --- An overloading mechanism for Emacs Lisp functions  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
 ;; Author: Hans Chalupsky <hans@cs.buffalo.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/avl-tree.el b/lisp/emacs-lisp/avl-tree.el
index b42017d28fb..2b46a518cf5 100644
--- a/lisp/emacs-lisp/avl-tree.el
+++ b/lisp/emacs-lisp/avl-tree.el
@@ -1,6 +1,6 @@
 ;;; avl-tree.el --- balanced binary trees, AVL-trees  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1995, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Per Cederqvist <ceder@lysator.liu.se>
 ;;         Inge Wallin <inge@lysator.liu.se>
diff --git a/lisp/emacs-lisp/backquote.el b/lisp/emacs-lisp/backquote.el
index 0be984f1492..0d4681bc979 100644
--- a/lisp/emacs-lisp/backquote.el
+++ b/lisp/emacs-lisp/backquote.el
@@ -1,6 +1,6 @@
 ;;; backquote.el --- implement the ` Lisp construct  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1990, 1992, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1990, 1992, 1994, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Rick Sladkey <jrs@world.std.com>
diff --git a/lisp/emacs-lisp/backtrace.el b/lisp/emacs-lisp/backtrace.el
index 74462899efc..4ae7de5790d 100644
--- a/lisp/emacs-lisp/backtrace.el
+++ b/lisp/emacs-lisp/backtrace.el
@@ -1,6 +1,6 @@
 ;;; backtrace.el --- generic major mode for Elisp backtraces -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Gemini Lasswell
 ;; Keywords: lisp, tools, maint
diff --git a/lisp/emacs-lisp/benchmark.el b/lisp/emacs-lisp/benchmark.el
index e50b8524f29..58e51d7565b 100644
--- a/lisp/emacs-lisp/benchmark.el
+++ b/lisp/emacs-lisp/benchmark.el
@@ -1,6 +1,6 @@
 ;;; benchmark.el --- support for benchmarking code  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: lisp, extensions
diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el
index 98a3bcbb360..69a8d02531e 100644
--- a/lisp/emacs-lisp/bindat.el
+++ b/lisp/emacs-lisp/bindat.el
@@ -1,6 +1,6 @@
 ;;; bindat.el --- binary data structure packing and unpacking.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Kim F. Storm <storm@cua.dk>
 ;; Assignment name: struct.el
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index ea818328000..80ca8fc177e 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1,6 +1,6 @@
 ;;; byte-opt.el --- the optimization passes of the emacs-lisp byte compiler 
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1991, 1994, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 1994, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Jamie Zawinski <jwz@lucid.com>
 ;;     Hallvard Furuseth <hbf@ulrik.uio.no>
@@ -440,7 +440,7 @@ There can be multiple entries for the same NAME if it has 
several aliases.")
 
       (`(unwind-protect ,protected-expr :fun-body ,unwind-fun)
        ;; FIXME: The return value of UNWIND-FUN is never used so we
-       ;; could potentially optimise it for-effect, but we don't do
+       ;; could potentially optimize it for-effect, but we don't do
        ;; that right no.
        `(,fn ,(byte-optimize-form protected-expr for-effect)
              :fun-body ,(byte-optimize-form unwind-fun)))
@@ -812,8 +812,29 @@ There can be multiple entries for the same NAME if it has 
several aliases.")
   (or (not form)   ; assume (quote nil) always being normalized to nil
       (and (consp form)
            (let ((head (car form)))
-             ;; FIXME: There are many other expressions that are statically 
nil.
-             (cond ((memq head '(while ignore)) t)
+             (cond ((memq head
+                          ;; Some forms that are statically nil.
+                          ;; FIXME: Replace with a function property?
+                          '( while ignore
+                             insert insert-and-inherit insert-before-markers
+                             insert-before-markers-and-inherit
+                             insert-char insert-byte insert-buffer-substring
+                             delete-region delete-char
+                             widen narrow-to-region transpose-regions
+                             forward-char backward-char
+                             beginning-of-line end-of-line
+                             erase-buffer buffer-swap-text
+                             delete-overlay delete-all-overlays
+                             remhash
+                             maphash
+                             map-charset-chars map-char-table
+                             mapbacktrace
+                             mapatoms
+                             ding beep sleep-for
+                             json-insert
+                             set-match-data
+                             ))
+                    t)
                    ((eq head 'if)
                     (and (byte-compile-nilconstp (nth 2 form))
                          (byte-compile-nilconstp (car (last (cdddr form))))))
@@ -975,7 +996,7 @@ There can be multiple entries for the same NAME if it has 
several aliases.")
     (list (car form) (nth 2 form) (nth 1 form)))))
 
 (defun byte-opt--nary-comparison (form)
-  "Optimise n-ary comparisons such as `=', `<' etc."
+  "Optimize n-ary comparisons such as `=', `<' etc."
   (let ((nargs (length (cdr form))))
     (cond
      ((= nargs 1)
@@ -990,7 +1011,7 @@ There can be multiple entries for the same NAME if it has 
several aliases.")
         (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.
+            ;; The optimizer will eliminate trivial bindings later.
             (let ((i 1))
               (dolist (arg (cdr form))
                 (let ((var (make-symbol (format "arg%d" i))))
@@ -1460,7 +1481,7 @@ See Info node `(elisp) Integer Basics'."
 (put 'let* 'byte-optimizer #'byte-optimize-letX)
 (defun byte-optimize-letX (form)
   (pcase form
-    ;; No bindings.
+    ;; Bindings list is empty.
     (`(,_ () . ,body)
      `(progn . ,body))
 
@@ -1470,7 +1491,7 @@ See Info node `(elisp) Integer Basics'."
          `(progn ,@(mapcar #'cadr bindings) ,const)
        `(,head ,(butlast bindings) ,(cadar (last bindings)) ,const)))
 
-    ;; Body is last variable.
+    ;; Body does nothing but return the last variable in bindings.
     (`(,head ,(and bindings
                    (let last-var (caar (last bindings))))
              ,(and last-var             ; non-linear pattern
diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el
index 24fbddb9d71..846c383094a 100644
--- a/lisp/emacs-lisp/byte-run.el
+++ b/lisp/emacs-lisp/byte-run.el
@@ -1,6 +1,6 @@
 ;;; byte-run.el --- byte-compiler support for inlining  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Jamie Zawinski <jwz@lucid.com>
 ;;     Hallvard Furuseth <hbf@ulrik.uio.no>
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 82811a52a0a..8c1d4814cbf 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -1,6 +1,6 @@
 ;;; bytecomp.el --- compilation of Lisp code into byte code -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985-1987, 1992, 1994, 1998, 2000-2023 Free Software
+;; Copyright (C) 1985-1987, 1992, 1994, 1998, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Jamie Zawinski <jwz@lucid.com>
@@ -231,17 +231,8 @@ This includes variable references and calls to functions 
such as `car'."
   :type 'boolean)
 
 (defvar byte-compile-dynamic nil
-  "If non-nil, compile function bodies so they load lazily.
-They are hidden in comments in the compiled file,
-and each one is brought into core when the
-function is called.
-
-To enable this option, make it a file-local variable
-in the source file you want it to apply to.
-For example, add  -*-byte-compile-dynamic: t;-*- on the first line.
-
-When this option is true, if you load the compiled file and then move it,
-the functions you loaded will not be able to run.")
+  "Formerly used to compile function bodies so they load lazily.
+This variable no longer has any effect.")
 (make-obsolete-variable 'byte-compile-dynamic "not worthwhile any more." 
"27.1")
 ;;;###autoload(put 'byte-compile-dynamic 'safe-local-variable 'booleanp)
 
@@ -262,7 +253,7 @@ This option is enabled by default because it reduces Emacs 
memory usage."
   :type 'boolean)
 ;;;###autoload(put 'byte-compile-dynamic-docstrings 'safe-local-variable 
'booleanp)
 
-(defconst byte-compile-log-buffer "*Compile-Log*"
+(defvar byte-compile-log-buffer "*Compile-Log*"
   "Name of the byte-compiler's log buffer.")
 
 (defvar byte-compile--known-dynamic-vars nil
@@ -354,7 +345,7 @@ A value of `all' really means all."
   '(docstrings-non-ascii-quotes)
   "List of warning types that are only enabled during Emacs builds.
 This is typically either warning types that are being phased in
-(but shouldn't be enabled for packages yet), or that are only relevant
+\(but shouldn't be enabled for packages yet), or that are only relevant
 for the Emacs build itself.")
 
 (defvar byte-compile--suppressed-warnings nil
@@ -1753,69 +1744,114 @@ Also ignore URLs."
 The byte-compiler will emit a warning for documentation strings
 containing lines wider than this.  If `fill-column' has a larger
 value, it will override this variable."
-  :group 'bytecomp
   :type 'natnum
   :safe #'natnump
   :version "28.1")
 
-(define-obsolete-function-alias 'byte-compile-docstring-length-warn
-  'byte-compile-docstring-style-warn "29.1")
-
-(defun byte-compile-docstring-style-warn (form)
-  "Warn if there are stylistic problems with the docstring in FORM.
-Warn if documentation string of FORM is too wide.
+(defun byte-compile--list-with-n (list n elem)
+  "Return LIST with its Nth element replaced by ELEM."
+  (if (eq elem (nth n list))
+      list
+    (nconc (take n list)
+           (list elem)
+           (nthcdr (1+ n) list))))
+
+(defun byte-compile--docstring-style-warn (docs kind name)
+  "Warn if there are stylistic problems in the docstring DOCS.
+Warn if documentation string is too wide.
 It is too wide if it has any lines longer than the largest of
 `fill-column' and `byte-compile-docstring-max-column'."
   (when (byte-compile-warning-enabled-p 'docstrings)
-    (let* ((kind nil) (name nil) (docs nil)
+    (let* ((name (if (eq (car-safe name) 'quote) (cadr name) name))
            (prefix (lambda ()
                      (format "%s%s"
                              kind
-                             (if name (format-message " `%s' " name) "")))))
-      (pcase (car form)
-        ((or 'autoload 'custom-declare-variable 'defalias
-             'defconst 'define-abbrev-table
-             'defvar 'defvaralias
-             'custom-declare-face)
-         (setq kind (nth 0 form))
-         (setq name (nth 1 form))
-         (when (and (consp name) (eq (car name) 'quote))
-           (setq name (cadr name)))
-         (setq docs (nth 3 form)))
-        ('lambda
-          (setq kind "")          ; can't be "function", unfortunately
-          (setq docs (nth 2 form))))
-      (when (and kind docs (stringp docs)
-                 (setq docs (help-strip-pos-info docs)))
-        (let ((col (max byte-compile-docstring-max-column fill-column)))
-          (when (and (byte-compile-warning-enabled-p 'docstrings-wide)
-                     (byte-compile--wide-docstring-p docs col))
-            (byte-compile-warn-x
-             name
-             "%sdocstring wider than %s characters" (funcall prefix) col)))
-        ;; There's a "naked" ' character before a symbol/list, so it
-        ;; should probably be quoted with \=.
-        (when (string-match-p (rx (| (in " \t") bol)
-                                  (? (in "\"#"))
-                                  "'"
-                                  (in "A-Za-z" "("))
+;;;; Merge STOUGH, 2024-03-03
+;; <<<<<<< HEAD
+;;                              (if name (format-message " `%s' " name) "")))))
+;;       (pcase (car form)
+;;         ((or 'autoload 'custom-declare-variable 'defalias
+;;              'defconst 'define-abbrev-table
+;;              'defvar 'defvaralias
+;;              'custom-declare-face)
+;;          (setq kind (nth 0 form))
+;;          (setq name (nth 1 form))
+;;          (when (and (consp name) (eq (car name) 'quote))
+;;            (setq name (cadr name)))
+;;          (setq docs (nth 3 form)))
+;;         ('lambda
+;;           (setq kind "")          ; can't be "function", unfortunately
+;;           (setq docs (nth 2 form))))
+;;       (when (and kind docs (stringp docs)
+;;                  (setq docs (help-strip-pos-info docs)))
+;;         (let ((col (max byte-compile-docstring-max-column fill-column)))
+;;           (when (and (byte-compile-warning-enabled-p 'docstrings-wide)
+;;                      (byte-compile--wide-docstring-p docs col))
+;;             (byte-compile-warn-x
+;;              name
+;;              "%sdocstring wider than %s characters" (funcall prefix) col)))
+;;         ;; There's a "naked" ' character before a symbol/list, so it
+;;         ;; should probably be quoted with \=.
+;;         (when (string-match-p (rx (| (in " \t") bol)
+;;                                   (? (in "\"#"))
+;;                                   "'"
+;;                                   (in "A-Za-z" "("))
+;; =======
+                             (if name (format-message " `%S' " name) "")))))
+      (let ((col (max byte-compile-docstring-max-column fill-column)))
+        (when (and (byte-compile-warning-enabled-p 'docstrings-wide)
+                   (byte-compile--wide-docstring-p docs col))
+          (byte-compile-warn-x
+           name
+           "%sdocstring wider than %s characters" (funcall prefix) col)))
+      ;; There's a "naked" ' character before a symbol/list, so it
+      ;; should probably be quoted with \=.
+      (when (string-match-p (rx (| (in " \t") bol)
+                                (? (in "\"#"))
+                                "'"
+                                (in "A-Za-z" "("))
+                            docs)
+        (byte-compile-warn-x
+         name
+         (concat "%sdocstring has wrong usage of unescaped single quotes"
+                 " (use \\=%c or different quoting such as %c...%c)")
+         (funcall prefix) ?' ?` ?'))
+      ;; There's a "Unicode quote" in the string -- it should probably
+      ;; be an ASCII one instead.
+      (when (byte-compile-warning-enabled-p 'docstrings-non-ascii-quotes)
+        (when (string-match-p (rx (| " \"" (in " \t") bol)
+                                  (in "‘’"))
+;; >>>>>>> master
                               docs)
           (byte-compile-warn-x
            name
-           (concat "%sdocstring has wrong usage of unescaped single quotes"
-                   " (use \\=%c or different quoting such as %c...%c)")
-           (funcall prefix) ?' ?` ?'))
-        ;; There's a "Unicode quote" in the string -- it should probably
-        ;; be an ASCII one instead.
-        (when (byte-compile-warning-enabled-p 'docstrings-non-ascii-quotes)
-          (when (string-match-p (rx (| " \"" (in " \t") bol)
-                                    (in "‘’"))
-                                docs)
-            (byte-compile-warn-x
-             name
-             "%sdocstring uses curved single quotes; use %s instead of ‘...’"
-             (funcall prefix) "`...'"))))))
-  form)
+           "%sdocstring uses curved single quotes; use %s instead of ‘...’"
+           (funcall prefix) "`...'"))))))
+
+(defvar byte-compile--\#$) ; Special value that will print as `#$'.
+(defvar byte-compile--docstrings nil "Table of already compiled docstrings.")
+
+(defun byte-compile--docstring (doc kind name &optional is-a-value)
+  (byte-compile--docstring-style-warn doc kind name)
+  ;; Make docstrings dynamic, when applicable.
+  (cond
+   ((and byte-compile-dynamic-docstrings
+         ;; The native compiler doesn't use those dynamic docstrings.
+         (not byte-native-compiling)
+         ;; Docstrings can only be dynamic when compiling a file.
+         byte-compile--\#$)
+    (let* ((byte-pos (with-memoization
+                         ;; Reuse a previously written identical docstring.
+                         ;; This is not done out of thriftiness but to try and
+                         ;; make sure that "equal" functions remain `equal'.
+                         ;; (Often those identical docstrings come from
+                         ;; `help-add-fundoc-usage').
+                         ;; Needed e.g. for `advice-tests-nadvice'.
+                         (gethash doc byte-compile--docstrings)
+                       (byte-compile-output-as-comment doc nil)))
+           (newdoc (cons byte-compile--\#$ byte-pos)))
+      (if is-a-value newdoc (macroexp-quote newdoc))))
+   (t doc)))
 
 ;; If we have compiled any calls to functions which are not known to be
 ;; defined, issue a warning enumerating them.
@@ -1850,6 +1886,8 @@ It is too wide if it has any lines longer than the 
largest of
           ;; macroenvironment.
           (copy-alist byte-compile-initial-macro-environment))
          (byte-compile--outbuffer nil)
+         (byte-compile--\#$ nil)
+         (byte-compile--docstrings (make-hash-table :test 'equal))
          (overriding-plist-environment nil)
          (byte-compile-function-environment nil)
          (byte-compile-bound-variables nil)
@@ -1863,7 +1901,6 @@ It is too wide if it has any lines longer than the 
largest of
          ;;
          (byte-compile-verbose byte-compile-verbose)
          (byte-optimize byte-optimize)
-         (byte-compile-dynamic byte-compile-dynamic)
          (byte-compile-dynamic-docstrings
           byte-compile-dynamic-docstrings)
          (byte-compile-warnings byte-compile-warnings)
@@ -1879,39 +1916,46 @@ It is too wide if it has any lines longer than the 
largest of
          (setq byte-to-native-plist-environment
                overriding-plist-environment)))))
 
-(defmacro displaying-byte-compile-warnings (&rest body)
+(defmacro displaying-byte-compile-warnings (&rest body) ;FIXME: namespace!
   (declare (debug (def-body)))
-  `(let* ((--displaying-byte-compile-warnings-fn (lambda () ,@body))
-         (warning-series-started
-          (and (markerp warning-series)
-               (eq (marker-buffer warning-series)
-                   (get-buffer byte-compile-log-buffer))))
-          (byte-compile-form-stack byte-compile-form-stack))
-     (if (or (eq warning-series 'byte-compile-warning-series)
-            warning-series-started)
-        ;; warning-series does come from compilation,
-        ;; so don't bind it, but maybe do set it.
-        (let (tem)
-          ;; Log the file name.  Record position of that text.
-          (setq tem (byte-compile-log-file))
-          (unless warning-series-started
-            (setq warning-series (or tem 'byte-compile-warning-series)))
-          ;; (if byte-compile-debug STOUGH, 2024-02-13
-              (funcall --displaying-byte-compile-warnings-fn)
-            ;; (condition-case error-info STOUGH, 2024-02-13
-            ;;     (funcall --displaying-byte-compile-warnings-fn)
-            ;;   (error (byte-compile-report-error error-info))))
-              )
-       ;; warning-series does not come from compilation, so bind it.
-       (let ((warning-series
-             ;; Log the file name.  Record position of that text.
-             (or (byte-compile-log-file) 'byte-compile-warning-series)))
-        ;; (if byte-compile-debug STOUGH, 2024-02-13
-            (funcall --displaying-byte-compile-warnings-fn)
-          ;; (condition-case error-info STOUGH, 2024-02-13
-          ;;     (funcall --displaying-byte-compile-warnings-fn)
-          ;;   (error (byte-compile-report-error error-info))))
-       ))))
+  `(bytecomp--displaying-warnings (lambda () ,@body)))
+
+(defun bytecomp--displaying-warnings (body-fn)
+  (let* ((wrapped-body
+         (lambda ()
+           (if byte-compile-debug
+               (funcall body-fn)
+             ;; Use a `handler-bind' to remember the `byte-compile-form-stack'
+             ;; active at the time the error is signaled, so as to
+             ;; get more precise error locations.
+             (let ((form-stack nil))
+               ;; (condition-case error-info
+                   ;; (handler-bind
+                   ;;     ((error (lambda (_err)
+                   ;;               (setq form-stack 
byte-compile-form-stack))))
+                     (funcall body-fn);; )
+                 ;; (error (let ((byte-compile-form-stack form-stack))
+                 ;;          (byte-compile-report-error error-info)))
+                  ;; )
+              ))))
+        (warning-series-started
+         (and (markerp warning-series)
+              (eq (marker-buffer warning-series)
+                  (get-buffer byte-compile-log-buffer))))
+         (byte-compile-form-stack byte-compile-form-stack))
+    (if (or (eq warning-series #'byte-compile-warning-series)
+           warning-series-started)
+       ;; warning-series does come from compilation,
+       ;; so don't bind it, but maybe do set it.
+       (let ((tem (byte-compile-log-file))) ;; Log the file name.
+         (unless warning-series-started
+           (setq warning-series (or tem #'byte-compile-warning-series)))
+         (funcall wrapped-body))
+      ;; warning-series does not come from compilation, so bind it.
+      (let ((warning-series
+            ;; Log the file name.  Record position of that text.
+            (or (byte-compile-log-file) #'byte-compile-warning-series)))
+       (funcall wrapped-body)))))
 
 ;;;###autoload
 (defun byte-force-recompile (directory)
@@ -2208,9 +2252,10 @@ See also `emacs-lisp-byte-compile-and-load'."
       ;; Don't inherit lexical-binding from caller (bug#12938).
       (unless (local-variable-p 'lexical-binding)
         (let ((byte-compile-current-buffer (current-buffer)))
-          (byte-compile-warn-x
-           (position-symbol 'a (point-min))
-           "file has no `lexical-binding' directive on its first line"))
+          (displaying-byte-compile-warnings
+           (byte-compile-warn-x
+            (position-symbol 'a (point-min))
+            "file has no `lexical-binding' directive on its first line")))
         (setq-local lexical-binding nil))
       ;; Set the default directory, in case an eval-when-compile uses it.
       (setq default-directory (file-name-directory filename)))
@@ -2374,7 +2419,12 @@ With argument ARG, insert value in current buffer after 
the form."
        (setq case-fold-search nil))
      (displaying-byte-compile-warnings
       (with-current-buffer inbuffer
-       (when byte-compile-current-file
+       (when byte-compile-dest-file
+          (setq byte-compile--\#$
+                (copy-sequence ;It needs to be a fresh new object.
+                 ;; Also it stands for the `load-file-name' when the `.elc' 
will
+                 ;; be loaded, so make it look like it.
+                 byte-compile-dest-file))
          (byte-compile-insert-header byte-compile-current-file
                                       byte-compile--outbuffer)
           ;; Instruct native-comp to ignore this file.
@@ -2430,8 +2480,7 @@ With argument ARG, insert value in current buffer after 
the form."
 (defun byte-compile-insert-header (_filename outbuffer)
   "Insert a header at the start of OUTBUFFER.
 Call from the source buffer."
-  (let ((dynamic byte-compile-dynamic)
-       (optimize byte-optimize))
+  (let ((optimize byte-optimize))
     (with-current-buffer outbuffer
       (goto-char (point-min))
       ;; The magic number of .elc files is ";ELC", or 0x3B454C43.  After
@@ -2465,18 +2514,11 @@ Call from the source buffer."
        ((eq optimize 'byte) " byte-level optimization only")
        (optimize " all optimizations")
        (t "out optimization"))
-       ".\n"
-       (if dynamic ";;; Function definitions are lazy-loaded.\n"
-        "")
-       "\n\n"))))
+       ".\n\n\n"))))
 
 (defun byte-compile-output-file-form (form)
   ;; Write the given form to the output buffer, being careful of docstrings
-  ;; (for `byte-compile-dynamic-docstrings') in defvar, defvaralias,
-  ;; defconst, autoload, and custom-declare-variable.
-  ;; defalias calls are output directly by byte-compile-file-form-defmumble;
-  ;; it does not pay to first build the defalias in defmumble and then parse
-  ;; it here.
+  ;; (for `byte-compile-dynamic-docstrings').
   (when byte-native-compiling
     ;; Spill output for the native compiler here
     (push (make-byte-to-native-top-level :form form :lexical lexical-binding)
@@ -2486,152 +2528,17 @@ Call from the source buffer."
         (print-level nil)
         (print-quoted t)
         (print-gensym t)
-        (print-circle t))               ; Handle circular data structures.
-    (if (memq (car-safe form) '(defvar defvaralias defconst
-                                 autoload custom-declare-variable))
-        (byte-compile-output-docform nil nil nil '("\n(" ")") form nil 3 nil
-                                     (memq (car form)
-                                           '(defvaralias autoload
-                                              custom-declare-variable)))
-      (princ "\n" byte-compile--outbuffer)
-      (prin1 form byte-compile--outbuffer)
-      nil)))
+        (print-circle t)
+        (print-continuous-numbering t)
+        (print-number-table (make-hash-table :test #'eq)))
+    (when byte-compile--\#$
+      (puthash byte-compile--\#$ "#$" print-number-table))
+    (princ "\n" byte-compile--outbuffer)
+    (prin1 form byte-compile--outbuffer)
+    nil))
 
 (defvar byte-compile--for-effect)
 
-(defun byte-compile--output-docform-recurse
-    (info position form cvecindex docindex specindex quoted)
-  "Print a form with a doc string.  INFO is (prefix postfix).
-POSITION is where the next doc string is to be inserted.
-CVECINDEX is the index in the FORM of the constant vector, or nil.
-DOCINDEX is the index of the doc string (or nil) in the FORM.
-If SPECINDEX is non-nil, it is the index in FORM
-of the function bytecode string.  In that case,
-we output that argument and the following argument
-\(the constants vector) together, for lazy loading.
-QUOTED says that we have to put a quote before the
-list that represents a doc string reference.
-`defvaralias', `autoload' and `custom-declare-variable' need that.
-
-Return the position after any inserted docstrings as comments."
-  (let ((index 0)
-        doc-string-position)
-    ;; Insert the doc string, and make it a comment with #@LENGTH.
-    (when (and byte-compile-dynamic-docstrings
-               (stringp (nth docindex form)))
-      (goto-char position)
-      (setq doc-string-position
-            (byte-compile-output-as-comment
-             (nth docindex form) nil)
-            position (point))
-      (goto-char (point-max)))
-
-    (insert (car info))
-    (prin1 (car form) byte-compile--outbuffer)
-    (while (setq form (cdr form))
-      (setq index (1+ index))
-      (insert " ")
-      (cond ((and (numberp specindex) (= index specindex)
-                  ;; Don't handle the definition dynamically
-                  ;; if it refers (or might refer)
-                  ;; to objects already output
-                  ;; (for instance, gensyms in the arg list).
-                  (let (non-nil)
-                    (when (hash-table-p print-number-table)
-                      (maphash (lambda (_k v) (if v (setq non-nil t)))
-                               print-number-table))
-                    (not non-nil)))
-             ;; Output the byte code and constants specially
-             ;; for lazy dynamic loading.
-             (goto-char position)
-             (let ((lazy-position (byte-compile-output-as-comment
-                                   (cons (car form) (nth 1 form))
-                                   t)))
-               (setq position (point))
-               (goto-char (point-max))
-               (princ (format "(#$ . %d) nil" lazy-position)
-                      byte-compile--outbuffer)
-               (setq form (cdr form))
-               (setq index (1+ index))))
-            ((eq index cvecindex)
-             (let* ((cvec (car form))
-                    (len (length cvec))
-                    (index2 0)
-                    elt)
-               (insert "[")
-               (while (< index2 len)
-                 (setq elt (aref cvec index2))
-                 (if (byte-code-function-p elt)
-                     (setq position
-                           (byte-compile--output-docform-recurse
-                            '("#[" "]") position
-                            (append elt nil) ; Convert the vector to a list.
-                            2 4 specindex nil))
-                   (prin1 elt byte-compile--outbuffer))
-                 (setq index2 (1+ index2))
-                 (unless (eq index2 len)
-                   (insert " ")))
-               (insert "]")))
-            ((= index docindex)
-             (cond
-              (doc-string-position
-               (princ (format (if quoted "'(#$ . %d)"  "(#$ . %d)")
-                              doc-string-position)
-                      byte-compile--outbuffer))
-              ((stringp (car form))
-               (let ((print-escape-newlines nil))
-                 (goto-char (prog1 (1+ (point))
-                              (prin1 (car form)
-                                     byte-compile--outbuffer)))
-                 (insert "\\\n")
-                 (goto-char (point-max))))
-              (t (prin1 (car form) byte-compile--outbuffer))))
-            (t (prin1 (car form) byte-compile--outbuffer))))
-    (insert (cadr info))
-    position))
-
-(defun byte-compile-output-docform (preface tailpiece name info form
-                                            cvecindex docindex
-                                            specindex quoted)
-  "Print a form with a doc string.  INFO is (prefix postfix).
-If PREFACE, NAME, and TAILPIECE are non-nil, print them too,
-before/after INFO and the FORM but after the doc string itself.
-CVECINDEX is the index in the FORM of the constant vector, or nil.
-DOCINDEX is the index of the doc string (or nil) in the FORM.
-If SPECINDEX is non-nil, it is the index in FORM
-of the function bytecode string.  In that case,
-we output that argument and the following argument
-\(the constants vector) together, for lazy loading.
-QUOTED says that we have to put a quote before the
-list that represents a doc string reference.
-`defvaralias', `autoload' and `custom-declare-variable' need that."
-  ;; We need to examine byte-compile-dynamic-docstrings
-  ;; in the input buffer (now current), not in the output buffer.
-  (let ((byte-compile-dynamic-docstrings byte-compile-dynamic-docstrings))
-    (with-current-buffer byte-compile--outbuffer
-      (let ((position (point))
-            (print-continuous-numbering t)
-            print-number-table
-            ;; FIXME: The bindings below are only needed for when we're
-            ;; called from ...-defmumble.
-            (print-escape-newlines t)
-            (print-length nil)
-            (print-level nil)
-            (print-quoted t)
-            (print-gensym t)
-            (print-circle t))       ; Handle circular data structures.
-        (when preface
-          ;; FIXME: We don't handle uninterned names correctly.
-          ;; E.g. if cl-define-compiler-macro uses uninterned name we get:
-          ;;    (defalias '#1=#:foo--cmacro #[514 ...])
-          ;;    (put 'foo 'compiler-macro '#:foo--cmacro)
-          (insert preface)
-          (prin1 name byte-compile--outbuffer))
-        (byte-compile--output-docform-recurse
-         info position form cvecindex docindex specindex quoted)
-        (when tailpiece
-          (insert tailpiece))))))
-
 (defun byte-compile-keep-pending (form &optional handler)
   (if (memq byte-optimize '(t source))
       (setq form (byte-optimize-one-form form t)))
@@ -2651,7 +2558,7 @@ list that represents a doc string reference.
   (if byte-compile-output
       (let ((form (byte-compile-out-toplevel t 'file)))
        (cond ((eq (car-safe form) 'progn)
-              (mapc 'byte-compile-output-file-form (cdr form)))
+              (mapc #'byte-compile-output-file-form (cdr form)))
              (form
               (byte-compile-output-file-form form)))
        (setq byte-compile-constants nil
@@ -2673,16 +2580,12 @@ list that represents a doc string reference.
 
 ;; byte-hunk-handlers cannot call this!
 (defun byte-compile-toplevel-file-form (top-level-form)
-  ;; (let ((byte-compile-form-stack
-  ;;        (cons top-level-form byte-compile-form-stack)))
-  (push top-level-form byte-compile-form-stack)
-  (prog1
-      (byte-compile-recurse-toplevel
-       top-level-form
-       (lambda (form)
-         (let ((byte-compile-current-form nil)) ; close over this for warnings.
-           (byte-compile-file-form (byte-compile-preprocess form t)))))
-    (pop byte-compile-form-stack)))
+  (macroexp--with-extended-form-stack top-level-form
+    (byte-compile-recurse-toplevel
+     top-level-form
+     (lambda (form)
+       (let ((byte-compile-current-form nil)) ; close over this for warnings.
+         (byte-compile-file-form (byte-compile-preprocess form t)))))))
 
 ;; byte-hunk-handlers can call this.
 (defun byte-compile-file-form (form)
@@ -2730,12 +2633,12 @@ list that represents a doc string reference.
        (setq byte-compile-unresolved-functions
              (delq (assq funsym byte-compile-unresolved-functions)
                    byte-compile-unresolved-functions)))))
-  (if (stringp (nth 3 form))
-      (prog1
-          form
-        (byte-compile-docstring-style-warn form))
-    ;; No doc string, so we can compile this as a normal form.
-    (byte-compile-keep-pending form 'byte-compile-normal-call)))
+  (let* ((doc (nth 3 form))
+         (newdoc (if (not (stringp doc)) doc
+                   (byte-compile--docstring
+                    doc 'autoload (nth 1 form)))))
+    (byte-compile-keep-pending (byte-compile--list-with-n form 3 newdoc)
+                               #'byte-compile-normal-call)))
 
 (put 'defvar   'byte-hunk-handler 'byte-compile-file-form-defvar)
 (put 'defconst 'byte-hunk-handler 'byte-compile-file-form-defvar)
@@ -2747,9 +2650,10 @@ list that represents a doc string reference.
     (byte-compile-warn-x
      sym "global/dynamic var `%s' lacks a prefix" sym)))
 
-(defun byte-compile--declare-var (sym)
+(defun byte-compile--declare-var (sym &optional not-toplevel)
   (byte-compile--check-prefixed-var sym)
-  (when (memq sym byte-compile-lexical-variables)
+  (when (and (not not-toplevel)
+             (memq sym byte-compile-lexical-variables))
     (setq byte-compile-lexical-variables
           (delq sym byte-compile-lexical-variables))
     (when (byte-compile-warning-enabled-p 'lexical sym)
@@ -2758,26 +2662,31 @@ list that represents a doc string reference.
   (push sym byte-compile--seen-defvars))
 
 (defun byte-compile-file-form-defvar (form)
-  (let* ((sym (nth 1 form))
-         (defining-symbol sym))
-    (byte-compile--declare-var sym)
-    (if (eq (car form) 'defconst)
-        (push sym byte-compile-const-variables))
-    (if (and (null (cddr form))                ;No `value' provided.
-           (eq (car form) 'defvar))     ;Just a declaration.
-      nil
-    (byte-compile-docstring-style-warn form)
-    (setq form (copy-sequence form))
-    (when (consp (nth 2 form))
-      (setcar (cdr (cdr form))
-              (byte-compile-top-level (nth 2 form) nil 'file)))
-    (let ((posified-doc-string
-           (byte-run-posify-doc-string
-            (and (nth 3 form) (stringp (nth 3 form)) (nth 3 form)))))
-      (if (nthcdr 3 form)
-          (setcar (nthcdr 3 form) posified-doc-string)
-        (nconc form (list posified-doc-string))))
-    form)))
+;;;; MERGED AWAY STOUGH, 2024-03-03
+;; <<<<<<< HEAD
+;;   (let* ((sym (nth 1 form))
+;;          (defining-symbol sym))
+;;     (byte-compile--declare-var sym)
+;;     (if (eq (car form) 'defconst)
+;;         (push sym byte-compile-const-variables))
+;;     (if (and (null (cddr form))             ;No `value' provided.
+;;            (eq (car form) 'defvar))     ;Just a declaration.
+;;       nil
+;;     (byte-compile-docstring-style-warn form)
+;;     (setq form (copy-sequence form))
+;;     (when (consp (nth 2 form))
+;;       (setcar (cdr (cdr form))
+;;               (byte-compile-top-level (nth 2 form) nil 'file)))
+;;     (let ((posified-doc-string
+;;            (byte-run-posify-doc-string
+;;             (and (nth 3 form) (stringp (nth 3 form)) (nth 3 form)))))
+;;       (if (nthcdr 3 form)
+;;           (setcar (nthcdr 3 form) posified-doc-string)
+;;         (nconc form (list posified-doc-string))))
+;;     form)))
+;; =======
+  (byte-compile-defvar form 'toplevel))
+;; >>>>>>> master
 
 (put 'define-abbrev-table 'byte-hunk-handler
      'byte-compile-file-form-defvar-function)
@@ -2785,26 +2694,37 @@ list that represents a doc string reference.
 
 (defun byte-compile-file-form-defvar-function (form)
   (pcase-let (((or `',name (let name nil)) (nth 1 form)))
-    (if name (byte-compile--declare-var name)))
-  ;; Variable aliases are better declared before the corresponding variable,
-  ;; since it makes it more likely that only one of the two vars has a value
-  ;; before the `defvaralias' gets executed, which avoids the need to
-  ;; merge values.
-  (pcase form
-    (`(defvaralias ,_ ',newname . ,_)
-     (when (memq newname byte-compile-bound-variables)
-       (if (byte-compile-warning-enabled-p 'suspicious)
-           (byte-compile-warn-x
-            newname
-            "Alias for `%S' should be declared before its referent" 
newname)))))
-  (byte-compile-docstring-style-warn form)
-  (byte-compile-keep-pending form))
+    (if name (byte-compile--declare-var name))
+    ;; Variable aliases are better declared before the corresponding variable,
+    ;; since it makes it more likely that only one of the two vars has a value
+    ;; before the `defvaralias' gets executed, which avoids the need to
+    ;; merge values.
+    (pcase form
+      (`(defvaralias ,_ ',newname . ,_)
+       (when (memq newname byte-compile-bound-variables)
+         (if (byte-compile-warning-enabled-p 'suspicious)
+             (byte-compile-warn-x
+              newname
+              "Alias for `%S' should be declared before its referent"
+              newname)))))
+    (let ((doc (nth 3 form)))
+      (when (stringp doc)
+        (setcar (nthcdr 3 form)
+                (byte-compile--docstring doc (nth 0 form) name))))
+    (byte-compile-keep-pending form)))
 
 (put 'custom-declare-variable 'byte-hunk-handler
      'byte-compile-file-form-defvar-function)
 
 (put 'custom-declare-face 'byte-hunk-handler
-     'byte-compile-docstring-style-warn)
+     #'byte-compile--custom-declare-face)
+(defun byte-compile--custom-declare-face (form)
+  (let ((kind (nth 0 form)) (name (nth 1 form)) (docs (nth 3 form)))
+    (when (stringp docs)
+      (let ((newdocs (byte-compile--docstring docs kind name)))
+        (unless (eq docs newdocs)
+          (setq form (byte-compile--list-with-n form 3 newdocs)))))
+    form))
 
 (put 'require 'byte-hunk-handler 'byte-compile-file-form-require)
 (defun byte-compile-file-form-require (form)
@@ -2958,34 +2878,39 @@ not to take responsibility for the actual compilation 
of the code."
                (cons (cons bare-name code)
                      (symbol-value this-kind))))
 
-        (if rest
-            ;; There are additional args to `defalias' (like maybe a docstring)
-            ;; that the code below can't handle: punt!
-            nil
-          ;; Otherwise, we have a bona-fide defun/defmacro definition, and use
-          ;; special code to allow dynamic docstrings and byte-code.
-          (byte-compile-flush-pending)
+        (byte-compile-flush-pending)
+        (let ((newform `(defalias ',bare-name
+                         ,(if macro `'(macro . ,code) code) ,@rest)))
           (when byte-native-compiling
-            ;; Spill output for the native compiler here.
+            ;; Don't let `byte-compile-output-file-form' push the form to
+            ;; `byte-to-native-top-level-forms' because we want to use
+            ;; `make-byte-to-native-func-def' when possible.
             (push
-             (if macro
+             (if (or macro rest)
                  (make-byte-to-native-top-level
-                  :form `(defalias ',name '(macro . ,code) nil)
+                  :form newform
                   :lexical lexical-binding)
                (make-byte-to-native-func-def :name name
                                              :byte-func code))
              byte-to-native-top-level-forms))
-          ;; Output the form by hand, that's much simpler than having
-          ;; b-c-output-file-form analyze the defalias.
-          (byte-compile-output-docform
-           "\n(defalias '" ")"
-           bare-name
-           (if macro '(" '(macro . #[" "])") '(" #[" "]"))
-           (append code nil)    ; Turn byte-code-function-p into list.
-           2 4
-           (and (atom code) byte-compile-dynamic 1)
-           nil)
-          t)))))
+;;;; OLD STOUGH, 2024-03-03
+;; <<<<<<< HEAD
+;;           ;; Output the form by hand, that's much simpler than having
+;;           ;; b-c-output-file-form analyze the defalias.
+;;           (byte-compile-output-docform
+;;            "\n(defalias '" ")"
+;;            bare-name
+;;            (if macro '(" '(macro . #[" "])") '(" #[" "]"))
+;;            (append code nil)    ; Turn byte-code-function-p into list.
+;;            2 4
+;;            (and (atom code) byte-compile-dynamic 1)
+;;            nil)
+;;           t)))))
+;;=======
+          (let ((byte-native-compiling nil))
+           (byte-compile-output-file-form newform)))
+        t))))
+;; >>>>>>> master
 
 (defun byte-compile-output-as-comment (exp quoted)
   "Print Lisp object EXP in the output file at point, inside a comment.
@@ -3030,18 +2955,10 @@ otherwise, print without quoting."
 
 (defun byte-compile--reify-function (fun)
   "Return an expression which will evaluate to a function value FUN.
-FUN should be either a `lambda' value or a `closure' value."
-  (pcase-let* (((or (and `(lambda ,args . ,body) (let env nil))
-                    `(closure ,env ,args . ,body))
-                fun)
-               (preamble nil)
+FUN should be an interpreted closure."
+  (pcase-let* ((`(closure ,env ,args . ,body) fun)
+               (`(,preamble . ,body) (macroexp-parse-body body))
                (renv ()))
-    ;; Split docstring and `interactive' form from body.
-    (when (stringp (car body))
-      (push (pop body) preamble))
-    (when (eq (car-safe (car body)) 'interactive)
-      (push (pop body) preamble))
-    (setq preamble (nreverse preamble))
     ;; Turn the function's closed vars (if any) into local let bindings.
     (dolist (binding env)
       (cond
@@ -3063,41 +2980,78 @@ If FORM is a lambda or a macro, byte-compile it as a 
function."
            (fun (if (symbolp form)
                    (symbol-function form)
                  form))
-          (macro (eq (car-safe fun) 'macro)))
-      (if macro
-         (setq fun (cdr fun)))
-      (prog1
-          (cond
-           ;; Up until Emacs-24.1, byte-compile silently did nothing
-           ;; when asked to compile something invalid.  So let's tone
-           ;; down the complaint from an error to a simple message for
-           ;; the known case where signaling an error causes problems.
-           ((compiled-function-p fun)
-            (message "Function %s is already compiled"
-                     (if (symbolp form) form "provided"))
-            fun)
-           (t
-            (let (final-eval defining-symbol)
-              (when (or (symbolp form) (eq (car-safe fun) 'closure))
-                ;; `fun' is a function *value*, so try to recover its 
corresponding
-                ;; source code.
-                (setq lexical-binding (eq (car fun) 'closure))
-                (setq fun (byte-compile--reify-function fun))
-                (setq final-eval t))
-              ;; Expand macros.
-              (setq fun (byte-compile-preprocess fun))
-              (setq fun (byte-compile-top-level fun nil 'eval))
-              (if (symbolp form)
-                  ;; byte-compile-top-level returns an *expression* equivalent 
to the
-                  ;; `fun' expression, so we need to evaluate it, tho normally
-                  ;; this is not needed because the expression is just a 
constant
-                  ;; byte-code object, which is self-evaluating.
-                  (setq fun (eval fun t)))
-              (if final-eval
-                  (setq fun (eval fun t)))
-              (if macro (push 'macro fun))
-              (if (symbolp form) (fset form fun))
-              fun))))))))
+;;;; MERGE STOUGH, 2024-03-03
+;; <<<<<<< HEAD
+;;        (macro (eq (car-safe fun) 'macro)))
+;;       (if macro
+;;       (setq fun (cdr fun)))
+;;       (prog1
+;;           (cond
+;;            ;; Up until Emacs-24.1, byte-compile silently did nothing
+;;            ;; when asked to compile something invalid.  So let's tone
+;;            ;; down the complaint from an error to a simple message for
+;;            ;; the known case where signaling an error causes problems.
+;;            ((compiled-function-p fun)
+;;             (message "Function %s is already compiled"
+;;                      (if (symbolp form) form "provided"))
+;;             fun)
+;;            (t
+;;             (let (final-eval defining-symbol)
+;;               (when (or (symbolp form) (eq (car-safe fun) 'closure))
+;;                 ;; `fun' is a function *value*, so try to recover its 
corresponding
+;;                 ;; source code.
+;;                 (setq lexical-binding (eq (car fun) 'closure))
+;;                 (setq fun (byte-compile--reify-function fun))
+;;                 (setq final-eval t))
+;;               ;; Expand macros.
+;;               (setq fun (byte-compile-preprocess fun))
+;;               (setq fun (byte-compile-top-level fun nil 'eval))
+;;               (if (symbolp form)
+;;                   ;; byte-compile-top-level returns an *expression* 
equivalent to the
+;;                   ;; `fun' expression, so we need to evaluate it, tho 
normally
+;;                   ;; this is not needed because the expression is just a 
constant
+;;                   ;; byte-code object, which is self-evaluating.
+;;                   (setq fun (eval fun t)))
+;;               (if final-eval
+;;                   (setq fun (eval fun t)))
+;;               (if macro (push 'macro fun))
+;;               (if (symbolp form) (fset form fun))
+;;               fun))))))))
+;; =======
+          (macro (eq (car-safe fun) 'macro))
+           (need-a-value nil))
+      (when macro
+       (setq need-a-value t)
+       (setq fun (cdr fun)))
+      (cond
+       ;; Up until Emacs-24.1, byte-compile silently did nothing
+       ;; when asked to compile something invalid.  So let's tone
+       ;; down the complaint from an error to a simple message for
+       ;; the known case where signaling an error causes problems.
+       ((compiled-function-p fun)
+        (message "Function %s is already compiled"
+                 (if (symbolp form) form "provided"))
+        fun)
+       (t
+        (when (or (symbolp form) (eq (car-safe fun) 'closure))
+          ;; `fun' is a function *value*, so try to recover its
+          ;; corresponding source code.
+          (when (setq lexical-binding (eq (car-safe fun) 'closure))
+            (setq fun (byte-compile--reify-function fun)))
+          (setq need-a-value t))
+        ;; Expand macros.
+        (setq fun (byte-compile-preprocess fun))
+        (setq fun (byte-compile-top-level fun nil 'eval))
+        (when need-a-value
+          ;; `byte-compile-top-level' returns an *expression* equivalent to
+          ;; the `fun' expression, so we need to evaluate it, tho normally
+          ;; this is not needed because the expression is just a constant
+          ;; byte-code object, which is self-evaluating.
+          (setq fun (eval fun lexical-binding)))
+        (if macro (push 'macro fun))
+        (if (symbolp form) (fset form fun))
+        fun))))))
+;; >>>>>>> master
 
 (defun byte-compile-sexp (sexp)
   "Compile and return SEXP."
@@ -3196,9 +3150,9 @@ lambda-expression."
       (setq fun (cons 'lambda fun))
     (unless (eq 'lambda (car-safe fun))
       (error "Not a lambda list: %S" fun)))
-  (byte-compile-docstring-style-warn fun)
   (byte-compile-check-lambda-list (nth 1 fun))
   (let* ((arglist (nth 1 fun))
+         (bare-arglist (byte-run-strip-symbol-positions arglist)) ; for 
compile-defun.
          (arglistvars (byte-run-strip-symbol-positions
                        (byte-compile-arglist-vars arglist)))
         (byte-compile-bound-variables
@@ -3207,16 +3161,22 @@ lambda-expression."
         (body (cdr (cdr fun)))
         (doc (if (stringp (car body))
                   (prog1 (car body)
-                    ;; Discard the doc string
+                    ;; Discard the doc string from the body
                     ;; unless it is the last element of the body.
                     (if (cdr body)
                         (setq body (cdr body))))))
         (int (assq 'interactive body))
          command-modes)
     (when lexical-binding
+      (when arglist
+        ;; byte-compile-make-args-desc lost the args's names,
+        ;; so preserve them in the docstring.
+       (setq doc (help-add-fundoc-usage doc bare-arglist)))
       (dolist (var arglistvars)
         (when (assq var byte-compile--known-dynamic-vars)
           (byte-compile--warn-lexical-dynamic var 'lambda))))
+    (when (stringp doc)
+      (setq doc (byte-compile--docstring doc "" nil 'is-a-value)))
     ;; Process the interactive spec.
     (when int
       ;; Skip (interactive) if it is in front (the most usual location).
@@ -3260,8 +3220,7 @@ lambda-expression."
                                    (and lexical-binding
                                         (byte-compile-make-lambda-lexenv
                                          arglistvars))
-                                   reserved-csts))
-          (bare-arglist (byte-run-strip-symbol-positions arglist))) ; for 
compile-defun.
+                                   reserved-csts)))
       ;; Build the actual byte-coded function.
       (cl-assert (eq 'byte-code (car-safe compiled)))
       (let ((out
@@ -3273,12 +3232,7 @@ lambda-expression."
                     ;; byte-string, constants-vector, stack depth
                     (cdr compiled)
                     ;; optionally, the doc string.
-                    (cond ((and lexical-binding arglist)
-                           ;; byte-compile-make-args-desc lost the args's 
names,
-                           ;; so preserve them in the docstring.
-                           (list (help-add-fundoc-usage doc bare-arglist)))
-                          ((or doc int)
-                           (list doc)))
+                    (when (or doc int) (list doc))
                     ;; optionally, the interactive spec (and the modes the
                     ;; command applies to).
                     (cond
@@ -3500,127 +3454,126 @@ lambda-expression."
 ;;
 (defun byte-compile-form (form &optional for-effect)
   (let ((byte-compile--for-effect for-effect))
-    (push form byte-compile-form-stack)
-    (cond
-     ((not (consp form))
-      (cond ((or (not (symbolp form)) (macroexp--const-symbol-p form))
-             (byte-compile-constant form))
-            ((and byte-compile--for-effect byte-compile-delete-errors)
-             (setq byte-compile--for-effect nil))
-            (t (byte-compile-variable-ref form))))
-     ((symbolp (car form))
-      (let* ((fn (car form))
-             (handler (get fn 'byte-compile))
-            (interactive-only
-             (or (function-get fn 'interactive-only)
-                 (memq fn byte-compile-interactive-only-functions))))
-        (when (memq fn '(set symbol-value run-hooks ;; add-to-list
-                             add-hook remove-hook run-hook-with-args
-                             run-hook-with-args-until-success
-                             run-hook-with-args-until-failure))
-          (pcase (cdr form)
-            (`(',var . ,_)
-             (when (and (memq var byte-compile-lexical-variables)
-                        (byte-compile-warning-enabled-p 'lexical var))
-               (byte-compile-warn
-                (format-message "%s cannot use lexical var `%s'" fn var))))))
-        ;; Warn about using obsolete hooks.
-        (if (memq fn '(add-hook remove-hook))
-            (let ((hook (car-safe (cdr form))))
-              (if (eq (car-safe hook) 'quote)
-                  (byte-compile-check-variable (cadr hook) nil))))
-        (when (and (byte-compile-warning-enabled-p 'suspicious)
-                   (macroexp--const-symbol-p fn))
-          (byte-compile-warn-x fn "`%s' called as a function" fn))
-       (when (and (byte-compile-warning-enabled-p 'interactive-only fn)
-                  interactive-only)
-         (byte-compile-warn-x fn "`%s' is for interactive use only%s"
-                              fn
-                              (cond ((stringp interactive-only)
-                                     (format "; %s"
-                                             (substitute-command-keys
-                                              interactive-only)))
-                                    ((and (symbolp interactive-only)
-                                          (not (eq interactive-only t)))
-                                     (format-message "; use `%s' instead."
-                                                      interactive-only))
-                                    (t "."))))
-        (let ((mutargs (function-get (car form) 'mutates-arguments)))
-          (when mutargs
-            (dolist (idx (if (eq mutargs 'all-but-last)
-                             (number-sequence 1 (- (length form) 2))
-                           mutargs))
-              (let ((arg (nth idx form)))
-                (when (and (or (and (eq (car-safe arg) 'quote)
-                                    (consp (nth 1 arg)))
-                               (arrayp arg))
-                           (byte-compile-warning-enabled-p
-                            'mutate-constant (car form)))
-                  (byte-compile-warn-x form "`%s' on constant %s (arg %d)"
-                                       (car form)
-                                       (if (consp arg) "list" (type-of arg))
-                                       idx))))))
-
-        (let ((funargs (function-get (car form) 'funarg-positions)))
-          (dolist (funarg funargs)
-            (let ((arg (if (numberp funarg)
-                           (nth funarg form)
-                         (cadr (memq funarg form)))))
-              (when (and (eq 'quote (car-safe arg))
-                         (eq 'lambda (car-safe (cadr arg))))
+    (macroexp--with-extended-form-stack form
+      (cond
+       ((not (consp form))
+        (cond ((or (not (symbolp form)) (macroexp--const-symbol-p form))
+               (byte-compile-constant form))
+              ((and byte-compile--for-effect byte-compile-delete-errors)
+               (setq byte-compile--for-effect nil))
+              (t (byte-compile-variable-ref form))))
+       ((symbolp (car form))
+        (let* ((fn (car form))
+               (handler (get fn 'byte-compile))
+              (interactive-only
+               (or (function-get fn 'interactive-only)
+                   (memq fn byte-compile-interactive-only-functions))))
+          (when (memq fn '(set symbol-value run-hooks ;; add-to-list
+                               add-hook remove-hook run-hook-with-args
+                               run-hook-with-args-until-success
+                               run-hook-with-args-until-failure))
+            (pcase (cdr form)
+              (`(',var . ,_)
+               (when (and (memq var byte-compile-lexical-variables)
+                          (byte-compile-warning-enabled-p 'lexical var))
+                 (byte-compile-warn
+                  (format-message "%s cannot use lexical var `%s'" fn var))))))
+          ;; Warn about using obsolete hooks.
+          (if (memq fn '(add-hook remove-hook))
+              (let ((hook (car-safe (cdr form))))
+                (if (eq (car-safe hook) 'quote)
+                    (byte-compile-check-variable (cadr hook) nil))))
+          (when (and (byte-compile-warning-enabled-p 'suspicious)
+                     (macroexp--const-symbol-p fn))
+            (byte-compile-warn-x fn "`%s' called as a function" fn))
+         (when (and (byte-compile-warning-enabled-p 'interactive-only fn)
+                    interactive-only)
+           (byte-compile-warn-x fn "`%s' is for interactive use only%s"
+                                fn
+                                (cond ((stringp interactive-only)
+                                       (format "; %s"
+                                               (substitute-command-keys
+                                                interactive-only)))
+                                      ((and (symbolp interactive-only)
+                                            (not (eq interactive-only t)))
+                                       (format-message "; use `%s' instead."
+                                                        interactive-only))
+                                      (t "."))))
+          (let ((mutargs (function-get (car form) 'mutates-arguments)))
+            (when mutargs
+              (dolist (idx (if (eq mutargs 'all-but-last)
+                               (number-sequence 1 (- (length form) 2))
+                             mutargs))
+                (let ((arg (nth idx form)))
+                  (when (and (or (and (eq (car-safe arg) 'quote)
+                                      (consp (nth 1 arg)))
+                                 (arrayp arg))
+                             (byte-compile-warning-enabled-p
+                              'mutate-constant (car form)))
+                    (byte-compile-warn-x form "`%s' on constant %s (arg %d)"
+                                         (car form)
+                                         (if (consp arg) "list" (type-of arg))
+                                         idx))))))
+
+          (let ((funargs (function-get (car form) 'funarg-positions)))
+            (dolist (funarg funargs)
+              (let ((arg (if (numberp funarg)
+                             (nth funarg form)
+                           (cadr (memq funarg form)))))
+                (when (and (eq 'quote (car-safe arg))
+                           (eq 'lambda (car-safe (cadr arg))))
+                  (byte-compile-warn-x
+                   arg "(lambda %s ...) quoted with %s rather than with #%s"
+                   (or (nth 1 (cadr arg)) "()")
+                   "'" "'")))))           ; avoid styled quotes
+
+          (if (eq (car-safe (symbol-function (car form))) 'macro)
+              (byte-compile-report-error
+               (format-message "`%s' defined after use in %S (missing 
`require' of a library file?)"
+                               (car form) form)))
+
+          (when byte-compile--for-effect
+            (let ((sef (function-get (car form) 'side-effect-free)))
+              (cond
+               ((and sef (or (eq sef 'error-free)
+                             byte-compile-delete-errors))
+                ;; This transform is normally done in the Lisp optimizer,
+                ;; so maybe we don't need to bother about it here?
+                (setq form (cons 'progn (cdr form)))
+                (setq handler #'byte-compile-progn))
+               ((and (or sef (function-get (car form) 'important-return-value))
+                     ;; Don't warn for arguments to `ignore'.
+                     (not (eq byte-compile--for-effect 'for-effect-no-warn))
+                     (byte-compile-warning-enabled-p
+                      'ignored-return-value (car form)))
                 (byte-compile-warn-x
-                 arg "(lambda %s ...) quoted with %s rather than with #%s"
-                 (or (nth 1 (cadr arg)) "()")
-                 "'" "'")))))           ; avoid styled quotes
-
-        (if (eq (car-safe (symbol-function (car form))) 'macro)
-            (byte-compile-report-error
-             (format-message "`%s' defined after use in %S (missing `require' 
of a library file?)"
-                     (car form) form)))
-
-        (when byte-compile--for-effect
-          (let ((sef (function-get (car form) 'side-effect-free)))
-            (cond
-             ((and sef (or (eq sef 'error-free)
-                           byte-compile-delete-errors))
-              ;; This transform is normally done in the Lisp optimiser,
-              ;; so maybe we don't need to bother about it here?
-              (setq form (cons 'progn (cdr form)))
-              (setq handler #'byte-compile-progn))
-             ((and (or sef (function-get (car form) 'important-return-value))
-                   ;; Don't warn for arguments to `ignore'.
-                   (not (eq byte-compile--for-effect 'for-effect-no-warn))
-                   (byte-compile-warning-enabled-p
-                    'ignored-return-value (car form)))
-              (byte-compile-warn-x
-               (car form)
-               "value from call to `%s' is unused%s"
-               (car form)
-               (cond ((eq (car form) 'mapcar)
-                      "; use `mapc' or `dolist' instead")
-                     (t "")))))))
-
-        (if (and handler
-                 ;; Make sure that function exists.
-                 (and (functionp handler)
-                      ;; Ignore obsolete byte-compile function used by former
-                      ;; CL code to handle compiler macros (we do it
-                      ;; differently now).
-                      (not (eq handler 'cl-byte-compile-compiler-macro))))
-            (funcall handler form)
-          (byte-compile-normal-call form))))
-     ((and (byte-code-function-p (car form))
-           (memq byte-optimize '(t lap)))
-      (byte-compile-unfold-bcf form))
-     ((byte-compile-normal-call form)))
-    (if byte-compile--for-effect
-        (byte-compile-discard))
-    (pop byte-compile-form-stack)))
+                 (car form)
+                 "value from call to `%s' is unused%s"
+                 (car form)
+                 (cond ((eq (car form) 'mapcar)
+                        "; use `mapc' or `dolist' instead")
+                       (t "")))))))
+
+          (if (and handler
+                   ;; Make sure that function exists.
+                   (and (functionp handler)
+                        ;; Ignore obsolete byte-compile function used by former
+                        ;; CL code to handle compiler macros (we do it
+                        ;; differently now).
+                        (not (eq handler 'cl-byte-compile-compiler-macro))))
+              (funcall handler form)
+            (byte-compile-normal-call form))))
+       ((and (byte-code-function-p (car form))
+             (memq byte-optimize '(t lap)))
+        (byte-compile-unfold-bcf form))
+       ((byte-compile-normal-call form)))
+      (if byte-compile--for-effect
+          (byte-compile-discard)))))
 
 (let ((important-return-value-fns
        '(
          ;; These functions are side-effect-free except for the
-         ;; behaviour of functions passed as argument.
+         ;; behavior of functions passed as argument.
          mapcar mapcan mapconcat
          assoc plist-get plist-member
 
@@ -3833,7 +3786,6 @@ lambda-expression."
          (alen (length (cdr form)))
          (dynbinds ())
          lap)
-    (fetch-bytecode fun)
     (setq lap (byte-decompile-bytecode-1 (aref fun 1) (aref fun 2) t))
     ;; optimized switch bytecode makes it impossible to guess the correct
     ;; `byte-compile-depth', which can result in incorrect inlined code.
@@ -4165,7 +4117,7 @@ If it is nil, then the handler is 
\"byte-compile-SYMBOL.\""
     (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.
+         ;; is last, which may allow more lapcode optimizations.
          (let* ((op (car form))
                 (flipped-op (cdr (assq op '((< . >) (<= . >=)
                                             (> . <) (>= . <=) (= . =))))))
@@ -4333,7 +4285,7 @@ This function is never called when `lexical-binding' is 
nil."
            (arg2 (nth 2 form)))
        (when (and (memq (car form) '(+ *))
                   (macroexp-const-p arg1))
-         ;; Put constant argument last for better LAP optimisation.
+         ;; Put constant argument last for better LAP optimization.
          (cl-rotatef arg1 arg2))
        (byte-compile-form arg1)
        (byte-compile-form arg2)
@@ -5164,49 +5116,52 @@ binding slots have been popped."
     (push (nth 1 (nth 1 form)) byte-compile-global-not-obsolete-vars))
   (byte-compile-normal-call form))
 
-(defun byte-compile-defvar (form)
-  ;; This is not used for file-level defvar/consts.
-  (when (and (symbolp (nth 1 form))
-             (not (string-match "[-*/:$]" (symbol-name (nth 1 form))))
-             (byte-compile-warning-enabled-p 'lexical (nth 1 form)))
-    (byte-compile-warn-x
-     (nth 1 form)
-     "global/dynamic var `%s' lacks a prefix"
-     (nth 1 form)))
-  (byte-compile-docstring-style-warn form)
-  (let ((fun (nth 0 form))
-       (var (nth 1 form))
-       (value (nth 2 form))
-       (string (nth 3 form)))
-    (when (or (> (length form) 4)
-             (and (eq fun 'defconst) (null (cddr form))))
-      (let ((ncall (length (cdr form))))
-       (byte-compile-warn-x
-         fun
-        "`%s' called with %d argument%s, but %s %s"
-        fun ncall
-        (if (= 1 ncall) "" "s")
-        (if (< ncall 2) "requires" "accepts only")
-        "2-3")))
-    (push var byte-compile-bound-variables)
+(defun byte-compile-defvar (form &optional toplevel)
+  (let* ((fun (nth 0 form))
+        (var (nth 1 form))
+        (value (nth 2 form))
+        (string (nth 3 form)))
+    (byte-compile--declare-var var (not toplevel))
     (if (eq fun 'defconst)
        (push var byte-compile-const-variables))
-    (when (and string (not (stringp string)))
+    (cond
+     ((stringp string)
+      (setq string (byte-compile--docstring string fun var 'is-a-value)))
+     (string
       (byte-compile-warn-x
        string
        "third arg to `%s %s' is not a string: %s"
-       fun var string))
-    ;; Delegate the actual work to the function version of the
-    ;; special form, named with a "-1" suffix.
-    (byte-compile-form-do-effect
-     (cond
-      ((eq fun 'defconst) `(defconst-1 ',var ,@(nthcdr 2 form)))
-      ((not (cddr form)) `',var) ; A simple (defvar foo) just returns foo.
-      (t `(defvar-1 ',var
-                    ;; Don't eval `value' if `defvar' wouldn't eval it either.
-                    ,(if (macroexp-const-p value) value
-                       `(if (boundp ',var) nil ,value))
-                    ,@(nthcdr 3 form)))))))
+       fun var string)))
+;;;; NEW STOUGH FROM MERGE, 2024-02-24
+    (setq string (byte-run-posify-doc-string (and (stringp string) string)))
+;;;; END OF NEW STOUGH
+    (if toplevel
+        ;; At top-level we emit calls to defvar/defconst.
+        (if (and (null (cddr form))       ;No `value' provided.
+                 (eq (car form) 'defvar)) ;Just a declaration.
+            nil
+          (let ((tail (nthcdr 4 form)))
+            (when (or tail string) (push string tail))
+            (when (cddr form)
+              (push (if (not (consp value)) value
+                        (byte-compile-top-level value nil 'file))
+                    tail))
+            `(,fun ,var ,@tail)))
+      ;; At non-top-level, since there is no byte code for
+      ;; defvar/defconst, we delegate the actual work to the function
+      ;; version of the special form, named with a "-1" suffix.
+      (byte-compile-form-do-effect
+       (cond
+        ((eq fun 'defconst)
+         `(defconst-1 ',var ,@(byte-compile--list-with-n
+                               (nthcdr 2 form) 1 (macroexp-quote string))))
+        ((not (cddr form)) `',var) ; A simple (defvar foo) just returns foo.
+        (t `(defvar-1 ',var
+                      ;; Don't eval `value' if `defvar' wouldn't eval it 
either.
+                      ,(if (macroexp-const-p value) value
+                         `(if (boundp ',var) nil ,value))
+                      ,@(byte-compile--list-with-n
+                         (nthcdr 3 form) 0 (macroexp-quote string)))))))))
 
 (defun byte-compile-autoload (form)
   (and (macroexp-const-p (nth 1 form))
@@ -5232,14 +5187,6 @@ binding slots have been popped."
   ;; For the compilation itself, we could largely get rid of this hunk-handler,
   ;; if it weren't for the fact that we need to figure out when a defalias
   ;; defines a macro, so as to add it to byte-compile-macro-environment.
-  ;;
-  ;; FIXME: we also use this hunk-handler to implement the function's
-  ;; dynamic docstring feature (via byte-compile-file-form-defmumble).
-  ;; We should probably actually implement it (more elegantly) in
-  ;; byte-compile-lambda so it applies to all lambdas.  We did it here
-  ;; so the resulting .elc format was recognizable by make-docfile,
-  ;; but since then we stopped using DOC for the docstrings of
-  ;; preloaded elc files so that obstacle is gone.
   (let ((byte-compile-free-references nil)
         (byte-compile-free-assignments nil))
     (pcase form
@@ -5248,7 +5195,11 @@ binding slots have been popped."
       ;; - `arg' is the expression to which it is defined.
       ;; - `rest' is the rest of the arguments.
       (`(,_ ',name ,arg . ,rest)
-       (byte-compile-docstring-style-warn form)
+       (let ((doc (car rest)))
+         (when (stringp doc)
+           (setq rest (byte-compile--list-with-n
+                       rest 0
+                       (byte-compile--docstring doc (nth 0 form) name)))))
        (pcase-let*
            ;; `macro' is non-nil if it defines a macro.
            ;; `fun' is the function part of `arg' (defaults to `arg').
@@ -5347,7 +5298,7 @@ FORM is used to provide location, 
`bytecomp--cus-function' and
   "Warn about common mistakes in the `defcustom' type TYPE."
   (let ((invalid-types
          '(
-           ;; Lisp type predicates, often confused with customisation types:
+           ;; Lisp type predicates, often confused with customization types:
            functionp numberp integerp fixnump natnump floatp booleanp
            characterp listp stringp consp vectorp symbolp keywordp
            hash-table-p facep
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index 12847c1d46a..f6573b6f71e 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -1,6 +1,6 @@
 ;;; cconv.el --- Closure conversion for statically scoped Emacs Lisp. -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Igor Kuzmin <kzuminig@iro.umontreal.ca>
 ;; Maintainer: emacs-devel@gnu.org
@@ -332,171 +332,177 @@ places where they originally did not directly appear."
   ;; to find the number of a specific variable in the environment vector,
   ;; so we never touch it(unless we enter to the other closure).
   ;;(if (listp form) (print (car form)) form)
-  (pcase form
-    (`(,(and letsym (or 'let* 'let)) ,binders . ,body)
+  (macroexp--with-extended-form-stack form
+    (pcase form
+      (`(,(and letsym (or 'let* 'let)) ,binders . ,body)
 
                                        ; let and let* special forms
-     (let ((binders-new '())
-           (new-env env)
-           (new-extend extend))
-
-       (dolist (binder binders)
-         (let* ((value nil)
-               (var (if (not (consp binder))
-                        (prog1 binder (setq binder (list binder)))
-                       (when (cddr binder)
-                         (byte-compile-warn-x
-                          binder
-                          "Malformed `%S' binding: %S"
-                          letsym binder))
-                      (setq value (cadr binder))
-                      (car binder))))
-           (cond
-            ;; Ignore bindings without a valid name.
-            ((not (symbolp var))
-             (byte-compile-warn-x var "attempt to let-bind nonvariable `%S'" 
var))
-            ((or (booleanp var) (keywordp var))
-             (byte-compile-warn-x var "attempt to let-bind constant `%S'" var))
-            (t
-             (let ((new-val
-                   (pcase (cconv--var-classification binder form)
-                      ;; Check if var is a candidate for lambda lifting.
-                      ((and :lambda-candidate
-                            (guard
-                             (progn
-                               (cl-assert (and (eq (car value) 'function)
-                                               (eq (car (cadr value)) 
'lambda)))
-                               (cl-assert (equal (cddr (cadr value))
-                                                 (caar cconv-freevars-alist)))
-                               ;; Peek at the freevars to decide whether
-                               ;; to λ-lift.
-                               (let* ((fvs (cdr (car cconv-freevars-alist)))
-                                      (fun (cadr value))
-                                      (funargs (cadr fun))
-                                      (funcvars (append fvs funargs)))
+       (let ((binders-new '())
+             (new-env env)
+             (new-extend extend))
+
+         (dolist (binder binders)
+           (let* ((value nil)
+                 (var (if (not (consp binder))
+                          (prog1 binder (setq binder (list binder)))
+                         (when (cddr binder)
+                           (byte-compile-warn-x
+                            binder
+                            "Malformed `%S' binding: %S"
+                            letsym binder))
+                        (setq value (cadr binder))
+                        (car binder))))
+             (cond
+              ;; Ignore bindings without a valid name.
+              ((not (symbolp var))
+               (byte-compile-warn-x
+                var "attempt to let-bind nonvariable `%S'" var))
+              ((or (booleanp var) (keywordp var))
+               (byte-compile-warn-x
+                var "attempt to let-bind constant `%S'" var))
+              (t
+               (let ((new-val
+                     (pcase (cconv--var-classification binder form)
+                        ;; Check if var is a candidate for lambda lifting.
+                        ((and :lambda-candidate
+                              (guard
+                               (progn
+                                 (cl-assert
+                                  (and (eq (car value) 'function)
+                                       (eq (car (cadr value)) 'lambda)))
+                                 (cl-assert (equal (cddr (cadr value))
+                                                   (caar 
cconv-freevars-alist)))
+                                 ;; Peek at the freevars to decide whether
+                                 ;; to λ-lift.
+                                 (let* ((fvs (cdr (car cconv-freevars-alist)))
+                                        (fun (cadr value))
+                                        (funargs (cadr fun))
+                                        (funcvars (append fvs funargs)))
                                        ; lambda lifting condition
-                                 (and fvs (>= cconv-liftwhen
-                                             (length funcvars)))))))
+                                   (and fvs (>= cconv-liftwhen
+                                               (length funcvars)))))))
                                        ; Lift.
-                       (let* ((fvs (cdr (pop cconv-freevars-alist)))
-                              (fun (cadr value))
-                              (funargs (cadr fun))
-                              (funcvars (append fvs funargs))
-                              (funcbody (cddr fun))
-                              (funcbody-env ()))
-                         (push `(,var . (apply-partially ,var . ,fvs)) new-env)
-                         (dolist (fv fvs)
-                           (cl-pushnew fv new-extend)
-                           (if (and (eq 'car-safe (car-safe
-                                                   (cdr (assq fv env))))
-                                    (not (memq fv funargs)))
-                               (push `(,fv . (car-safe ,fv)) funcbody-env)))
-                         `(function (lambda ,funcvars .
-                                      ,(cconv--convert-funcbody
-                                        funargs funcbody funcbody-env 
value)))))
-
-                      ;; Check if it needs to be turned into a "ref-cell".
-                      (:captured+mutated
-                       ;; Declared variable is mutated and captured.
-                       (push `(,var . (car-safe ,var)) new-env)
-                       `(list ,(cconv-convert value env extend)))
-
-                      ;; Check if it needs to be turned into a "ref-cell".
-                      (:unused
-                       ;; Declared variable is unused.
-                       (if (assq var new-env)
-                           (push `(,var) new-env)) ;FIXME:Needed?
-                       (let* ((Ignore (if (symbol-with-pos-p var)
-                                          (position-symbol 'ignore var)
-                                        'ignore))
-                              (newval `(,Ignore
-                                        ,(cconv-convert value env extend)))
-                              (msg (cconv--warn-unused-msg var "variable")))
-                         (if (null msg) newval
-                           (macroexp--warn-wrap var msg newval 'lexical))))
-
-                      ;; Normal default case.
-                      (_
-                       (if (assq var new-env) (push `(,var) new-env))
-                       (cconv-convert value env extend)))))
-
-               (when (and (eq letsym 'let*) (memq var new-extend))
-                 ;; One of the lambda-lifted vars is shadowed, so add
-                 ;; a reference to the outside binding and arrange to use
-                 ;; that reference.
-                 (let ((var-def (cconv--lifted-arg var env))
-                       (closedsym (make-symbol (format "closed-%s" var))))
-                   (setq new-env (cconv--remap-llv new-env var closedsym))
-                   ;; FIXME: `closedsym' doesn't need to be added to `extend'
-                   ;; but adding it makes it easier to write the assertion at
-                   ;; the beginning of this function.
-                   (setq new-extend (cons closedsym (remq var new-extend)))
-                   (push `(,closedsym ,var-def) binders-new)))
-
-               ;; We push the element after redefined free variables are
-               ;; processed.  This is important to avoid the bug when free
-               ;; variable and the function have the same name.
-               (push (list var new-val) binders-new)
-
-               (when (eq letsym 'let*)
-                 (setq env new-env)
-                 (setq extend new-extend))))))
-         )                           ; end of dolist over binders
-
-       (when (not (eq letsym 'let*))
-         ;; We can't do the cconv--remap-llv at the same place for let and
-         ;; let* because in the case of `let', the shadowing may occur
-         ;; before we know that the var will be in `new-extend' (bug#24171).
-         (dolist (binder binders-new)
-           (when (memq (car-safe binder) new-extend)
-             ;; One of the lambda-lifted vars is shadowed.
-             (let* ((var (car-safe binder))
-                    (var-def (cconv--lifted-arg var env))
-                    (closedsym (make-symbol (format "closed-%s" var))))
-               (setq new-env (cconv--remap-llv new-env var closedsym))
-               (setq new-extend (cons closedsym (remq var new-extend)))
-               (push `(,closedsym ,var-def) binders-new)))))
-
-       `(,letsym ,(nreverse binders-new)
-                 . ,(mapcar (lambda (form)
-                              (cconv-convert
-                               form new-env new-extend))
-                            body))))
+                         (let* ((fvs (cdr (pop cconv-freevars-alist)))
+                                (fun (cadr value))
+                                (funargs (cadr fun))
+                                (funcvars (append fvs funargs))
+                                (funcbody (cddr fun))
+                                (funcbody-env ()))
+                           (push `(,var . (apply-partially ,var . ,fvs))
+                                 new-env)
+                           (dolist (fv fvs)
+                             (cl-pushnew fv new-extend)
+                             (if (and (eq 'car-safe (car-safe
+                                                     (cdr (assq fv env))))
+                                      (not (memq fv funargs)))
+                                 (push `(,fv . (car-safe ,fv)) funcbody-env)))
+                           `(function
+                             (lambda ,funcvars
+                               . ,(cconv--convert-funcbody
+                                   funargs funcbody funcbody-env value)))))
+
+                        ;; Check if it needs to be turned into a "ref-cell".
+                        (:captured+mutated
+                         ;; Declared variable is mutated and captured.
+                         (push `(,var . (car-safe ,var)) new-env)
+                         `(list ,(cconv-convert value env extend)))
+
+                        ;; Check if it needs to be turned into a "ref-cell".
+                        (:unused
+                         ;; Declared variable is unused.
+                         (if (assq var new-env)
+                             (push `(,var) new-env)) ;FIXME:Needed?
+                         (let* ((Ignore (if (symbol-with-pos-p var)
+                                            (position-symbol 'ignore var)
+                                          'ignore))
+                                (newval `(,Ignore
+                                          ,(cconv-convert value env extend)))
+                                (msg (cconv--warn-unused-msg var "variable")))
+                           (if (null msg) newval
+                             (macroexp--warn-wrap var msg newval 'lexical))))
+
+                        ;; Normal default case.
+                        (_
+                         (if (assq var new-env) (push `(,var) new-env))
+                         (cconv-convert value env extend)))))
+
+                 (when (and (eq letsym 'let*) (memq var new-extend))
+                   ;; One of the lambda-lifted vars is shadowed, so add
+                   ;; a reference to the outside binding and arrange to use
+                   ;; that reference.
+                   (let ((var-def (cconv--lifted-arg var env))
+                         (closedsym (make-symbol (format "closed-%s" var))))
+                     (setq new-env (cconv--remap-llv new-env var closedsym))
+                     ;; FIXME: `closedsym' doesn't need to be added to `extend'
+                     ;; but adding it makes it easier to write the assertion at
+                     ;; the beginning of this function.
+                     (setq new-extend (cons closedsym (remq var new-extend)))
+                     (push `(,closedsym ,var-def) binders-new)))
+
+                 ;; We push the element after redefined free variables are
+                 ;; processed.  This is important to avoid the bug when free
+                 ;; variable and the function have the same name.
+                 (push (list var new-val) binders-new)
+
+                 (when (eq letsym 'let*)
+                   (setq env new-env)
+                   (setq extend new-extend))))))
+           )                           ; end of dolist over binders
+
+         (when (not (eq letsym 'let*))
+           ;; We can't do the cconv--remap-llv at the same place for let and
+           ;; let* because in the case of `let', the shadowing may occur
+           ;; before we know that the var will be in `new-extend' (bug#24171).
+           (dolist (binder binders-new)
+             (when (memq (car-safe binder) new-extend)
+               ;; One of the lambda-lifted vars is shadowed.
+               (let* ((var (car-safe binder))
+                      (var-def (cconv--lifted-arg var env))
+                      (closedsym (make-symbol (format "closed-%s" var))))
+                 (setq new-env (cconv--remap-llv new-env var closedsym))
+                 (setq new-extend (cons closedsym (remq var new-extend)))
+                 (push `(,closedsym ,var-def) binders-new)))))
+
+         `(,letsym ,(nreverse binders-new)
+                   . ,(mapcar (lambda (form)
+                                (cconv-convert
+                                 form new-env new-extend))
+                              body))))
                                        ;end of let let* forms
 
-                                  ; first element is lambda expression
-    (`(,(and `(lambda . ,_) fun) . ,args)
-     ;; FIXME: it's silly to create a closure just to call it.
-     ;; Running byte-optimize-form earlier would resolve this.
-     `(funcall
-       ,(cconv-convert `(function ,fun) env extend)
-       ,@(mapcar (lambda (form)
-                   (cconv-convert form env extend))
-                 args)))
-
-    (`(cond . ,cond-forms)              ; cond special form
-     `(,(car form) . ,(mapcar (lambda (branch)
-                                (mapcar (lambda (form)
-                                          (cconv-convert form env extend))
-                                        branch))
-                              cond-forms)))
-
-    (`(function (,(and 'lambda lambda-token) ,args . ,body) . ,rest)
-     (let* ((docstring (if (eq :documentation (car-safe (car body)))
-                           (cconv-convert (cadr (pop body)) env extend)))
-            (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 (&rest _cconv--dummy) .,_) t) (_ 
nil)))
-            (cif (when if (cconv-convert if env extend)))
-            (cf nil))
-       ;; TODO: Because we need to non-destructively modify body, this code
-       ;; is particularly ugly.  This should ideally be moved to
-       ;; cconv--convert-function.
-       (pcase cif
-         ('nil (setq bf nil))
-         (`#',f
-          (pcase-let ((`((,f1 . (,_ . ,f2)) . ,f3) bf))
+                                        ; first element is lambda expression
+      (`(,(and `(lambda . ,_) fun) . ,args)
+       ;; FIXME: it's silly to create a closure just to call it.
+       ;; Running byte-optimize-form earlier would resolve this.
+       `(funcall
+         ,(cconv-convert `(function ,fun) env extend)
+         ,@(mapcar (lambda (form)
+                     (cconv-convert form env extend))
+                   args)))
+
+      (`(cond . ,cond-forms)              ; cond special form
+       `(,(car form) . ,(mapcar (lambda (branch)
+                                  (mapcar (lambda (form)
+                                            (cconv-convert form env extend))
+                                          branch))
+                                cond-forms)))
+
+      (`(function (lambda ,args . ,body) . ,rest)
+       (let* ((docstring (if (eq :documentation (car-safe (car body)))
+                             (cconv-convert (cadr (pop body)) env extend)))
+              (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 (&rest _cconv--dummy) .,_) t)))
+              (cif (when if (cconv-convert if env extend)))
+              (cf nil))
+         ;; TODO: Because we need to non-destructively modify body, this code
+         ;; is particularly ugly.  This should ideally be moved to
+         ;; cconv--convert-function.
+         (pcase cif
+           ('nil (setq bf nil))
+           (`#',f
+            (pcase-let ((`((,f1 . (,_ . ,f2)) . ,f3) bf))
             (setq bf `((,f1 . (,(if wrapped
                                     (if (stringp (nth 2 f))
                                         (nth 3 f)
@@ -504,139 +510,137 @@ places where they originally did not directly appear."
                                   cif)
                                . ,f2))
                        . ,f3)))
-          (setq cif nil))
-         ;; The interactive form needs special treatment, so the form
-         ;; inside the `interactive' won't be used any further.
-         (_ (pcase-let ((`((,f1 . (,_ . ,f2)) . ,f3) bf))
-              (setq bf `((,f1 . (nil . ,f2)) . ,f3)))))
-       (when bf
-         ;; If we modified bf, re-build body and form as
-         ;; copies with the modified bits.
-         (setq body (if (stringp (car body))
-                        (cons (car body) bf)
-                      bf)
-               form `(function (,lambda-token ,args . ,body) . ,rest))
-         ;; Also, remove the current old entry on the alist, replacing
-         ;; it with the new one.
-         (let ((entry (pop cconv-freevars-alist)))
-           (push (cons body (cdr entry)) cconv-freevars-alist)))
-       (setq cf (cconv--convert-function args body env form
-                                         lambda-token docstring))
-       (if (not cif)
-           ;; Normal case, the interactive form needs no special treatment.
-           cf
-         `(cconv--interactive-helper
-           ,cf ,(if wrapped cif `(list 'quote ,cif))))))
-
-    (`(internal-make-closure . ,_)
-     (byte-compile-report-error
-      "Internal error in compiler: cconv called twice?"))
-
-    (`(quote . ,_) form)
-    (`(function . ,_) form)
+            (setq cif nil))
+           ;; The interactive form needs special treatment, so the form
+           ;; inside the `interactive' won't be used any further.
+           (_ (pcase-let ((`((,f1 . (,_ . ,f2)) . ,f3) bf))
+                (setq bf `((,f1 . (nil . ,f2)) . ,f3)))))
+         (when bf
+           ;; If we modified bf, re-build body and form as
+           ;; copies with the modified bits.
+           (setq body (if (stringp (car body))
+                          (cons (car body) bf)
+                        bf)
+                 form `(function (lambda ,args . ,body) . ,rest))
+           ;; Also, remove the current old entry on the alist, replacing
+           ;; it with the new one.
+           (let ((entry (pop cconv-freevars-alist)))
+             (push (cons body (cdr entry)) cconv-freevars-alist)))
+         (setq cf (cconv--convert-function args body env form docstring))
+         (if (not cif)
+             ;; Normal case, the interactive form needs no special treatment.
+             cf
+           `(cconv--interactive-helper
+             ,cf ,(if wrapped cif `(list 'quote ,cif))))))
+
+      (`(internal-make-closure . ,_)
+       (byte-compile-report-error
+        "Internal error in compiler: cconv called twice?"))
+
+      (`(quote . ,_) form)
+      (`(function . ,_) form)
 
                                        ;defconst, defvar
-    (`(,(and sym (or 'defconst 'defvar)) ,definedsymbol . ,forms)
-     `(,sym ,definedsymbol
-            . ,(when (consp forms)
-                 (cons (cconv-convert (car forms) env extend)
-                       ;; The rest (i.e. docstring, of any) is not evaluated,
-                       ;; and may be an invalid expression (e.g. ($# . 678)).
-                       (cdr forms)))))
+      (`(,(and sym (or 'defconst 'defvar)) ,definedsymbol . ,forms)
+       `(,sym ,definedsymbol
+              . ,(when (consp forms)
+                   (cons (cconv-convert (car forms) env extend)
+                         ;; The rest (i.e. docstring, of any) is not evaluated,
+                         ;; and may be an invalid expression (e.g. ($# . 678)).
+                         (cdr forms)))))
 
                                         ; condition-case
-    (`(condition-case ,var ,protected-form . ,handlers)
-     (let* ((class (and var (cconv--var-classification (list var) form)))
-            (newenv
-             (cond ((eq class :captured+mutated)
-                    (cons `(,var . (car-safe ,var)) env))
-                   ((assq var env) (cons `(,var) env))
-                   (t env)))
-            (msg (when (eq class :unused)
-                   (cconv--warn-unused-msg var "variable")))
-            (newprotform (cconv-convert protected-form env extend)))
-       `(,(car form) ,var
-            ,(if msg
-                 (macroexp--warn-wrap var msg newprotform 'lexical)
-               newprotform)
-          ,@(mapcar
-             (lambda (handler)
-               `(,(car handler)
-                 ,@(let ((body
-                          (mapcar (lambda (form)
-                                    (cconv-convert form newenv extend))
-                                  (cdr handler))))
-                     (if (not (eq class :captured+mutated))
-                         body
-                       `((let ((,var (list ,var))) ,@body))))))
-             handlers))))
-
-    (`(unwind-protect ,form1 . ,body)
-     `(,(car form) ,(cconv-convert form1 env extend)
-        :fun-body ,(cconv--convert-function () body env form1)))
-
-    (`(setq ,var ,expr)
-     (let ((var-new (or (cdr (assq var env)) var))
-           (value (cconv-convert expr env extend)))
-       (pcase var-new
-         ((pred symbolp) `(,(car form) ,var-new ,value))
-         (`(car-safe ,iexp) `(setcar ,iexp ,value))
-         ;; This "should never happen", but for variables which are
-         ;; mutated+captured+unused, we may end up trying to `setq'
-         ;; on a closed-over variable, so just drop the setq.
-         (_ ;; (byte-compile-report-error
-          ;;  (format "Internal error in cconv of (setq %s ..)"
-          ;;          sym-new))
-          value))))
-
-    (`(,(and (or 'funcall 'apply) callsym) ,fun . ,args)
-     ;; These are not special forms but we treat them separately for the needs
-     ;; of lambda lifting.
-     (let ((mapping (cdr (assq fun env))))
-       (pcase mapping
-         (`(apply-partially ,_ . ,(and fvs `(,_ . ,_)))
-          (cl-assert (eq (cadr mapping) fun))
-          `(,callsym ,fun
-                     ,@(mapcar (lambda (fv)
-                                 (let ((exp (or (cdr (assq fv env)) fv)))
-                                   (pcase exp
-                                     (`(car-safe ,iexp . ,_) iexp)
-                                     (_ exp))))
-                               fvs)
-                     ,@(mapcar (lambda (arg)
-                                 (cconv-convert arg env extend))
-                               args)))
-         (_ `(,callsym ,@(mapcar (lambda (arg)
+      (`(condition-case ,var ,protected-form . ,handlers)
+       (let* ((class (and var (cconv--var-classification (list var) form)))
+              (newenv
+               (cond ((eq class :captured+mutated)
+                      (cons `(,var . (car-safe ,var)) env))
+                     ((assq var env) (cons `(,var) env))
+                     (t env)))
+              (msg (when (eq class :unused)
+                     (cconv--warn-unused-msg var "variable")))
+              (newprotform (cconv-convert protected-form env extend)))
+         `(,(car form) ,var
+           ,(if msg
+                (macroexp--warn-wrap var msg newprotform 'lexical)
+              newprotform)
+           ,@(mapcar
+              (lambda (handler)
+                `(,(car handler)
+                  ,@(let ((body
+                           (mapcar (lambda (form)
+                                     (cconv-convert form newenv extend))
+                                   (cdr handler))))
+                      (if (not (eq class :captured+mutated))
+                          body
+                        `((let ((,var (list ,var))) ,@body))))))
+              handlers))))
+
+      (`(unwind-protect ,form1 . ,body)
+       `(,(car form) ,(cconv-convert form1 env extend)
+         :fun-body ,(cconv--convert-function () body env form1)))
+
+      (`(setq ,var ,expr)
+       (let ((var-new (or (cdr (assq var env)) var))
+             (value (cconv-convert expr env extend)))
+         (pcase var-new
+           ((pred symbolp) `(,(car form) ,var-new ,value))
+           (`(car-safe ,iexp) `(setcar ,iexp ,value))
+           ;; This "should never happen", but for variables which are
+           ;; mutated+captured+unused, we may end up trying to `setq'
+           ;; on a closed-over variable, so just drop the setq.
+           (_ ;; (byte-compile-report-error
+            ;;  (format "Internal error in cconv of (setq %s ..)"
+            ;;          sym-new))
+            value))))
+
+      (`(,(and (or 'funcall 'apply) callsym) ,fun . ,args)
+       ;; These are not special forms but we treat them separately for the 
needs
+       ;; of lambda lifting.
+       (let ((mapping (cdr (assq fun env))))
+         (pcase mapping
+           (`(apply-partially ,_ . ,(and fvs `(,_ . ,_)))
+            (cl-assert (eq (cadr mapping) fun))
+            `(,callsym ,fun
+                       ,@(mapcar (lambda (fv)
+                                   (let ((exp (or (cdr (assq fv env)) fv)))
+                                     (pcase exp
+                                       (`(car-safe ,iexp . ,_) iexp)
+                                       (_ exp))))
+                                 fvs)
+                       ,@(mapcar (lambda (arg)
                                    (cconv-convert arg env extend))
-                                 (cons fun args)))))))
-
-    ;; The form (if any) is converted beforehand as part of the `lambda' case.
-    (`(interactive . ,_) form)
-
-    ;; `declare' should now be macro-expanded away (and if they're not, we're
-    ;; in trouble because they *can* contain code nowadays).
-    ;; (`(declare . ,_) form)              ;The args don't contain code.
-
-    (`(oclosure--fix-type (ignore . ,vars) ,exp)
-     (dolist (var vars)
-       (let ((x (assq var env)))
-         (pcase (cdr x)
-           (`(car-safe . ,_) (error "Slot %S should not be mutated" var))
-           (_ (cl-assert (null (cdr x)))))))
-     (cconv-convert exp env extend))
-
-    (`(,func . ,forms)
-     (if (symbolp func)
-         ;; First element is function or whatever function-like forms are:
-         ;; or, and, if, catch, progn, prog1, while, until
-         `(,func . ,(mapcar (lambda (form)
-                              (cconv-convert form env extend))
-                            forms))
-       (macroexp--warn-wrap form (format-message "Malformed function `%S'"
-                                                 (car form))
-                            nil nil)))
-
-    (_ (or (cdr (assq form env)) form))))
+                                 args)))
+           (_ `(,callsym ,@(mapcar (lambda (arg)
+                                     (cconv-convert arg env extend))
+                                   (cons fun args)))))))
+
+      ;; The form (if any) is converted beforehand as part of the `lambda' 
case.
+      (`(interactive . ,_) form)
+
+      ;; `declare' should now be macro-expanded away (and if they're not, we're
+      ;; in trouble because they *can* contain code nowadays).
+      ;; (`(declare . ,_) form)              ;The args don't contain code.
+
+      (`(oclosure--fix-type (ignore . ,vars) ,exp)
+       (dolist (var vars)
+         (let ((x (assq var env)))
+           (pcase (cdr x)
+             (`(car-safe . ,_) (error "Slot %S should not be mutated" var))
+             (_ (cl-assert (null (cdr x)))))))
+       (cconv-convert exp env extend))
+
+      (`(,func . ,forms)
+       (if (symbolp func)
+           ;; First element is function or whatever function-like forms are:
+           ;; or, and, if, catch, progn, prog1, while, until
+           `(,func . ,(mapcar (lambda (form)
+                                (cconv-convert form env extend))
+                              forms))
+         (byte-compile-warn-x form "Malformed function `%S'" func)
+         nil))
+
+      (_ (or (cdr (assq form env)) form)))))
 
 (defvar byte-compile-lexical-variables)
 
diff --git a/lisp/emacs-lisp/chart.el b/lisp/emacs-lisp/chart.el
index 2d4f10123d1..da61e45213d 100644
--- a/lisp/emacs-lisp/chart.el
+++ b/lisp/emacs-lisp/chart.el
@@ -1,6 +1,6 @@
 ;;; chart.el --- Draw charts (bar charts, etc)  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Old-Version: 0.2
diff --git a/lisp/emacs-lisp/check-declare.el b/lisp/emacs-lisp/check-declare.el
index c887d95210c..8e40b227b65 100644
--- a/lisp/emacs-lisp/check-declare.el
+++ b/lisp/emacs-lisp/check-declare.el
@@ -1,6 +1,6 @@
 ;;; check-declare.el --- Check declare-function statements  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Glenn Morris <rgm@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
@@ -40,7 +40,7 @@
 
 ;;; Code:
 
-(defconst check-declare-warning-buffer "*Check Declarations Warnings*"
+(defvar check-declare-warning-buffer "*Check Declarations Warnings*"
   "Name of buffer used to display any `check-declare' warnings.")
 
 (defun check-declare-locate (file basefile)
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index 471a2fbdf48..82c6c03a592 100644
--- a/lisp/emacs-lisp/checkdoc.el
+++ b/lisp/emacs-lisp/checkdoc.el
@@ -1,6 +1,6 @@
 ;;; checkdoc.el --- check documentation strings for style requirements  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Old-Version: 0.6.2
@@ -556,7 +556,8 @@ the users will view as each check is completed."
   "Display and update the status buffer for the current checkdoc mode.
 CHECK is a list of four strings stating the current status of each
 test; the nth string describes the status of the nth test."
-  (let (temp-buffer-setup-hook)
+  (let (temp-buffer-setup-hook
+        (temp-buffer-show-hook #'special-mode))
     (with-output-to-temp-buffer "*Checkdoc Status*"
       (mapc #'princ
             (list "Buffer comments and tags:  " (nth 0 check)
@@ -1611,8 +1612,11 @@ may require more formatting")
        (let ((f nil) (m nil) (start (point))
              ;; Ignore the "A-" modifier: it is uncommon in practice,
              ;; and leads to false positives in regexp ranges.
-             (re "[^`‘A-Za-z0-9_]\\([CMs]-[a-zA-Z]\\|\\(\\([CMs]-\\)?\
-mouse-[0-3]\\)\\)\\>"))
+             (re (rx (not (any "0-9A-Za-z_`‘-"))
+                     (group (or (seq (any "CMs") "-" (any "A-Za-z"))
+                                (group (opt (group (any "CMs") "-"))
+                                       "mouse-" (any "0-3"))))
+                     eow)))
         ;; Find the first key sequence not in a sample
         (while (and (not f) (setq m (re-search-forward re e t)))
           (setq f (not (checkdoc-in-sample-code-p start e))))
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el
index 454076eb3f0..9281cd9821e 100644
--- a/lisp/emacs-lisp/cl-extra.el
+++ b/lisp/emacs-lisp/cl-extra.el
@@ -1,6 +1,6 @@
 ;;; cl-extra.el --- Common Lisp features, part 2  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1993, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Gillespie <daveg@synaptics.com>
 ;; Keywords: extensions
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 3d1be7daf3c..63a1347d7e2 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -1,6 +1,6 @@
 ;;; cl-generic.el --- CLOS-style generic functions for Elisp  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Version: 1.0
@@ -684,7 +684,7 @@ The set of acceptable TYPEs (also called \"specializers\") 
is defined
   ;; compiled.  Otherwise the byte-compiler and all the code on
   ;; which it depends needs to be usable before cl-generic is loaded,
   ;; which imposes a significant burden on the bootstrap.
-  (if (consp (lambda (x) (+ x 1)))
+  (if (not (compiled-function-p (lambda (x) (+ x 1))))
       (lambda (exp) (eval exp t))
     ;; But do byte-compile the dispatchers once bootstrap is passed:
     ;; the performance difference is substantial (like a 5x speedup on
diff --git a/lisp/emacs-lisp/cl-indent.el b/lisp/emacs-lisp/cl-indent.el
index ee50f572157..f3d076772e3 100644
--- a/lisp/emacs-lisp/cl-indent.el
+++ b/lisp/emacs-lisp/cl-indent.el
@@ -1,6 +1,6 @@
 ;;; cl-indent.el --- Enhanced lisp-indent mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1987, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Richard Mlynarik <mly@eddie.mit.edu>
 ;; Created: July 1987
diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el
index 779f25df572..108dcd31f48 100644
--- a/lisp/emacs-lisp/cl-lib.el
+++ b/lisp/emacs-lisp/cl-lib.el
@@ -1,6 +1,6 @@
 ;;; cl-lib.el --- Common Lisp extensions for Emacs  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Gillespie <daveg@synaptics.com>
 ;; Version: 1.0
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 9618dd0578d..ed86daad828 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -1,6 +1,6 @@
 ;;; cl-macs.el --- Common Lisp macros  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Gillespie <daveg@synaptics.com>
 ;; Old-Version: 2.02
@@ -3745,7 +3745,7 @@ macro that returns its `&whole' argument."
 (mapc (lambda (x) (function-put x 'important-return-value t))
        '(
          ;; Functions that are side-effect-free except for the
-         ;; behaviour of functions passed as argument.
+         ;; behavior of functions passed as argument.
          cl-mapcar cl-mapcan cl-maplist cl-map cl-mapcon
          cl-reduce
          cl-assoc cl-assoc-if cl-assoc-if-not
diff --git a/lisp/emacs-lisp/cl-preloaded.el b/lisp/emacs-lisp/cl-preloaded.el
index 3d0c2b54785..20e68555578 100644
--- a/lisp/emacs-lisp/cl-preloaded.el
+++ b/lisp/emacs-lisp/cl-preloaded.el
@@ -1,6 +1,6 @@
 ;;; cl-preloaded.el --- Preloaded part of the CL library  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2015-2023  Free Software Foundation, Inc
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Package: emacs
diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el
index 56e35078d39..c35353ec3d0 100644
--- a/lisp/emacs-lisp/cl-print.el
+++ b/lisp/emacs-lisp/cl-print.el
@@ -1,6 +1,6 @@
 ;;; cl-print.el --- CL-style generic printing  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords:
diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el
index ec481121ae6..e46955fd968 100644
--- a/lisp/emacs-lisp/cl-seq.el
+++ b/lisp/emacs-lisp/cl-seq.el
@@ -1,6 +1,6 @@
 ;;; cl-seq.el --- Common Lisp features, part 3  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Gillespie <daveg@synaptics.com>
 ;; Old-Version: 2.02
diff --git a/lisp/emacs-lisp/comp-common.el b/lisp/emacs-lisp/comp-common.el
index 6d94d1bd82e..6ba9664ea5c 100644
--- a/lisp/emacs-lisp/comp-common.el
+++ b/lisp/emacs-lisp/comp-common.el
@@ -1,6 +1,6 @@
 ;;; comp-common.el --- common code -*- lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrea Corallo <acorallo@gnu.org>
 ;; Keywords: lisp
@@ -49,11 +49,10 @@ This is intended for debugging the compiler itself.
   :version "28.1")
 
 (defcustom native-comp-never-optimize-functions
-  '(eval
-    ;; The following two are mandatory for Emacs to be working
-    ;; correctly (see comment in `advice--add-function'). DO NOT
-    ;; REMOVE.
-    macroexpand rename-buffer)
+  ;; We used to list those functions here that were advised during
+  ;; preload, but we now prefer to disallow preload advices in
+  ;; loadup.el (bug#67005).
+  '(eval)
   "Primitive functions to exclude from trampoline optimization.
 
 Primitive functions included in this list will not be called
diff --git a/lisp/emacs-lisp/comp-cstr.el b/lisp/emacs-lisp/comp-cstr.el
index e47e93cda18..2984bedb1dd 100644
--- a/lisp/emacs-lisp/comp-cstr.el
+++ b/lisp/emacs-lisp/comp-cstr.el
@@ -1,6 +1,6 @@
 ;;; comp-cstr.el --- native compiler constraint library -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrea Corallo <acorallo@gnu.org>
 ;; Keywords: lisp
@@ -130,7 +130,7 @@ Integer values are handled in the `range' slot.")
   ;; TODO we should be able to just cons hash this.
   (common-supertype-mem (make-hash-table :test #'equal) :type hash-table
                         :documentation "Serve memoization for
-`comp-common-supertype'.")
+`comp-ctxt-common-supertype-mem'.")
   (subtype-p-mem (make-hash-table :test #'equal) :type hash-table
                  :documentation "Serve memoization for
 `comp-cstr-ctxt-subtype-p-mem'.")
@@ -797,7 +797,7 @@ DST is returned."
             (cl-loop
              for val in (valset src)
              ;; If (member value) is subtypep of all other sources then
-             ;; is good to be colleted.
+             ;; is good to be collected.
              when (cl-every (lambda (s)
                               (or (memql val (valset s))
                                   (cl-some (lambda (type)
diff --git a/lisp/emacs-lisp/comp-run.el b/lisp/emacs-lisp/comp-run.el
index 4b1d2451a4e..5d1a193269d 100644
--- a/lisp/emacs-lisp/comp-run.el
+++ b/lisp/emacs-lisp/comp-run.el
@@ -1,6 +1,6 @@
 ;;; comp-runtime.el --- runtime Lisp native compiler code  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrea Corallo <acorallo@gnu.org>
 ;; Keywords: lisp
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index acd9615aaee..431d2aaf918 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -1,6 +1,6 @@
 ;;; comp.el --- compilation of Lisp code into native code -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrea Corallo <acorallo@gnu.org>
 ;; Keywords: lisp
@@ -224,13 +224,13 @@ Useful to hook into pass checkers.")
    finally return h)
   "Hash table function -> `comp-constraint'.")
 
-(defun comp-known-predicate-p (predicate)
+(defun comp--known-predicate-p (predicate)
   "Return t if PREDICATE is known."
   (when (or (gethash predicate comp-known-predicates-h)
             (gethash predicate (comp-cstr-ctxt-pred-type-h comp-ctxt)))
     t))
 
-(defun comp-pred-to-cstr (predicate)
+(defun comp--pred-to-cstr (predicate)
   "Given PREDICATE, return the corresponding constraint."
   (or (gethash predicate comp-known-predicates-h)
       (gethash predicate (comp-cstr-ctxt-pred-type-h comp-ctxt))))
@@ -430,7 +430,7 @@ non local exit (ends with an `unreachable' insn)."))
                                (:include comp-block))
   "A basic block holding only constraints.")
 
-(cl-defstruct (comp-edge (:copier nil) (:constructor make--comp-edge))
+(cl-defstruct (comp-edge (:copier nil) (:constructor comp--edge-make0))
   "An edge connecting two basic blocks."
   (src nil :type (or null comp-block))
   (dst nil :type (or null comp-block))
@@ -438,19 +438,19 @@ non local exit (ends with an `unreachable' insn)."))
           :documentation "The index number corresponding to this edge in the
  edge hash."))
 
-(defun make-comp-edge (&rest args)
+(defun comp--edge-make (&rest args)
   "Create a `comp-edge' with basic blocks SRC and DST."
   (let ((n (funcall (comp-func-edge-cnt-gen comp-func))))
     (puthash
      n
-     (apply #'make--comp-edge :number n args)
+     (apply #'comp--edge-make0 :number n args)
      (comp-func-edges-h comp-func))))
 
-(defun comp-block-preds (basic-block)
+(defun comp--block-preds (basic-block)
   "Return the list of predecessors of BASIC-BLOCK."
   (mapcar #'comp-edge-src (comp-block-in-edges basic-block)))
 
-(defun comp-gen-counter ()
+(defun comp--gen-counter ()
   "Return a sequential number generator."
   (let ((n -1))
     (lambda ()
@@ -484,9 +484,9 @@ CFG is mutated by a pass.")
              :documentation "LAP label -> LIMPLE basic block name.")
   (edges-h (make-hash-table) :type hash-table
          :documentation "Hash edge-num -> edge connecting basic two blocks.")
-  (block-cnt-gen (funcall #'comp-gen-counter) :type function
+  (block-cnt-gen (funcall #'comp--gen-counter) :type function
                  :documentation "Generates block numbers.")
-  (edge-cnt-gen (funcall #'comp-gen-counter) :type function
+  (edge-cnt-gen (funcall #'comp--gen-counter) :type function
                 :documentation "Generates edges numbers.")
   (has-non-local nil :type boolean
                  :documentation "t if non local jumps are present.")
@@ -525,39 +525,39 @@ In use by the back-end."
 
 
 
-(defun comp-equality-fun-p (function)
+(defun comp--equality-fun-p (function)
   "Equality functions predicate for FUNCTION."
   (when (memq function '(eq eql equal)) t))
 
-(defun comp-arithm-cmp-fun-p (function)
+(defun comp--arithm-cmp-fun-p (function)
   "Predicate for arithmetic comparison functions."
   (when (memq function '(= > < >= <=)) t))
 
-(defun comp-set-op-p (op)
+(defun comp--set-op-p (op)
   "Assignment predicate for OP."
   (when (memq op comp-limple-sets) t))
 
-(defun comp-assign-op-p (op)
+(defun comp--assign-op-p (op)
   "Assignment predicate for OP."
   (when (memq op comp-limple-assignments) t))
 
-(defun comp-call-op-p (op)
+(defun comp--call-op-p (op)
   "Call predicate for OP."
   (when (memq op comp-limple-calls) t))
 
-(defun comp-branch-op-p (op)
+(defun comp--branch-op-p (op)
   "Branch predicate for OP."
   (when (memq op comp-limple-branches) t))
 
-(defsubst comp-limple-insn-call-p (insn)
+(defsubst comp--limple-insn-call-p (insn)
   "Limple INSN call predicate."
-  (comp-call-op-p (car-safe insn)))
+  (comp--call-op-p (car-safe insn)))
 
-(defun comp-type-hint-p (func)
+(defun comp--type-hint-p (func)
   "Type-hint predicate for function name FUNC."
   (when (memq func comp-type-hints) t))
 
-(defun comp-func-unique-in-cu-p (func)
+(defun comp--func-unique-in-cu-p (func)
   "Return t if FUNC is known to be unique in the current compilation unit."
   (if (symbolp func)
       (cl-loop with h = (make-hash-table :test #'eq)
@@ -569,46 +569,45 @@ In use by the back-end."
                finally return t)
     t))
 
-(defsubst comp-symbol-func-to-fun (symbol-funcion)
-  "Given a function called SYMBOL-FUNCION return its `comp-func'."
-  (gethash (gethash symbol-funcion (comp-ctxt-sym-to-c-name-h
-                                    comp-ctxt))
+(defsubst comp--symbol-func-to-fun (symbol-func)
+  "Given a function called SYMBOL-FUNC return its `comp-func'."
+  (gethash (gethash symbol-func (comp-ctxt-sym-to-c-name-h comp-ctxt))
            (comp-ctxt-funcs-h comp-ctxt)))
 
-(defun comp-function-pure-p (f)
+(defun comp--function-pure-p (f)
   "Return t if F is pure."
   (or (get f 'pure)
-      (when-let ((func (comp-symbol-func-to-fun f)))
+      (when-let ((func (comp--symbol-func-to-fun f)))
         (comp-func-pure func))))
 
-(defun comp-alloc-class-to-container (alloc-class)
+(defun comp--alloc-class-to-container (alloc-class)
   "Given ALLOC-CLASS, return the data container for the current context.
 Assume allocation class `d-default' as default."
   (cl-struct-slot-value 'comp-ctxt (or alloc-class 'd-default) comp-ctxt))
 
-(defsubst comp-add-const-to-relocs (obj)
+(defsubst comp--add-const-to-relocs (obj)
   "Keep track of OBJ into the ctxt relocations."
-  (puthash obj t (comp-data-container-idx (comp-alloc-class-to-container
+  (puthash obj t (comp-data-container-idx (comp--alloc-class-to-container
                                            comp-curr-allocation-class))))
 
 
 ;;; Log routines.
 
-(defun comp-prettyformat-mvar (mvar)
+(defun comp--prettyformat-mvar (mvar)
   (format "#(mvar %s %s %S)"
           (comp-mvar-id mvar)
           (comp-mvar-slot mvar)
           (comp-cstr-to-type-spec mvar)))
 
-(defun comp-prettyformat-insn (insn)
+(defun comp--prettyformat-insn (insn)
   (cond
    ((comp-mvar-p insn)
-    (comp-prettyformat-mvar insn))
+    (comp--prettyformat-mvar insn))
    ((proper-list-p insn)
-    (concat "(" (mapconcat #'comp-prettyformat-insn insn " ") ")"))
+    (concat "(" (mapconcat #'comp--prettyformat-insn insn " ") ")"))
    (t (prin1-to-string insn))))
 
-(defun comp-log-func (func verbosity)
+(defun comp--log-func (func verbosity)
   "Log function FUNC at VERBOSITY.
 VERBOSITY is a number between 0 and 3."
   (when (>= native-comp-verbose verbosity)
@@ -619,9 +618,9 @@ VERBOSITY is a number between 0 and 3."
      do (comp-log (concat "<" (symbol-name block-name) ">") verbosity)
         (cl-loop
          for insn in (comp-block-insns bb)
-         do (comp-log (comp-prettyformat-insn insn) verbosity)))))
+         do (comp-log (comp--prettyformat-insn insn) verbosity)))))
 
-(defun comp-log-edges (func)
+(defun comp--log-edges (func)
   "Log edges in FUNC."
   (let ((edges (comp-func-edges-h func)))
     (comp-log (format "\nEdges in function: %s\n"
@@ -963,7 +962,7 @@ STACK-OFF is the index of the first slot frame involved."
   "`comp-mvar' initializer."
   (let ((mvar (make--comp-mvar :slot slot)))
     (when const-vld
-      (comp-add-const-to-relocs constant)
+      (comp--add-const-to-relocs constant)
       (setf (comp-cstr-imm mvar) constant))
     (when type
       (setf (comp-mvar-typeset mvar) (list type)))
@@ -1008,7 +1007,7 @@ If DST-N is specified, use it; otherwise assume it to be 
the current slot."
 
 (defsubst comp-emit-setimm (val)
   "Set constant VAL to current slot."
-  (comp-add-const-to-relocs val)
+  (comp--add-const-to-relocs val)
   ;; Leave relocation index nil on purpose, will be fixed-up in final
   ;; by `comp-finalize-relocs'.
   (comp-emit `(setimm ,(comp-slot) ,val)))
@@ -1134,7 +1133,7 @@ Return value is the fall-through block name."
 (defun comp-jump-table-optimizable (jmp-table)
   "Return t if JMP-TABLE can be optimized out."
   ;; Identify LAP sequences like:
-  ;; (byte-constant #s(hash-table size 3 test eq rehash-size 1.5 
rehash-threshold 0.8125 purecopy t data (created 126 deleted 126 changed 126)) 
. 24)
+  ;; (byte-constant #s(hash-table test eq purecopy t data (created 126 deleted 
126 changed 126)) . 24)
   ;; (byte-switch)
   ;; (TAG 126 . 10)
   (let ((targets (hash-table-values jmp-table)))
@@ -1496,7 +1495,7 @@ and the annotation emission."
   (cl-loop for bb being the hash-value in (comp-func-blocks func)
            do (setf (comp-block-insns bb)
                     (nreverse (comp-block-insns bb))))
-  (comp-log-func func 2)
+  (comp--log-func func 2)
   func)
 
 (cl-defgeneric comp-prepare-args-for-top-level (function)
@@ -1570,7 +1569,7 @@ and the annotation emission."
 These are stored in the reloc data array."
   (let ((args (comp-prepare-args-for-top-level func)))
     (let ((comp-curr-allocation-class 'd-impure))
-      (comp-add-const-to-relocs (comp-func-byte-func func)))
+      (comp--add-const-to-relocs (comp-func-byte-func func)))
     (comp-emit
      (comp-call 'comp--register-lambda
                 ;; mvar to be fixed-up when containers are
@@ -1773,7 +1772,7 @@ into the C code forwarding the compilation unit."
    do (cl-loop
        for insn in (comp-block-insns b)
        for (op . args) = insn
-       if (comp-assign-op-p op)
+       if (comp--assign-op-p op)
          do (comp-collect-mvars (cdr args))
        else
          do (comp-collect-mvars args))))
@@ -1822,7 +1821,7 @@ The assume is emitted at the beginning of the block BB."
                                        (comp-cstr-negation-make rhs)
                                      rhs)))
               (comp-block-insns bb))))
-      ((pred comp-arithm-cmp-fun-p)
+      ((pred comp--arithm-cmp-fun-p)
        (when-let ((kind (if negated
                             (comp-negate-arithm-cmp-fun kind)
                           kind)))
@@ -1855,7 +1854,7 @@ Return OP otherwise."
   (cl-loop
    with new-bb = (make-comp-block-cstr :name bb-symbol
                                        :insns `((jump ,(comp-block-name 
bb-b))))
-   with new-edge = (make-comp-edge :src bb-a :dst new-bb)
+   with new-edge = (comp--edge-make :src bb-a :dst new-bb)
    for ed in (comp-block-in-edges bb-b)
    when (eq (comp-edge-src ed) bb-a)
    do
@@ -1886,7 +1885,7 @@ Keep on searching till EXIT-INSN is encountered."
      when (eq insn exit-insn)
      do (cl-return (and (comp-mvar-p res) res))
      do (pcase insn
-          (`(,(pred comp-assign-op-p) ,(pred targetp) ,rhs)
+          (`(,(pred comp--assign-op-p) ,(pred targetp) ,rhs)
            (setf res rhs)))
      finally (cl-assert nil))))
 
@@ -1967,14 +1966,18 @@ TARGET-BB-SYM is the symbol name of the target block."
          (set ,(and (pred comp-mvar-p) mvar-3)
               (call memq ,(and (pred comp-mvar-p) mvar-1) ,(and (pred 
comp-mvar-p) mvar-2)))
          (cond-jump ,(and (pred comp-mvar-p) mvar-3) ,(pred comp-mvar-p) ,bb1 
,bb2))
-       (push  `(assume ,mvar-tested ,(make-comp-mvar :type (comp-cstr-cl-tag 
mvar-tag)))
-              (comp-block-insns (comp-add-cond-cstrs-target-block b bb2)))
-       (push  `(assume ,mvar-tested ,(make-comp-mvar :type (comp-cstr-cl-tag 
mvar-tag) :neg t))
-              (comp-block-insns (comp-add-cond-cstrs-target-block b bb1))))
+       (comp-emit-assume 'and mvar-tested
+                         (make-comp-mvar :type (comp-cstr-cl-tag mvar-tag))
+                         (comp-add-cond-cstrs-target-block b bb2)
+                         nil)
+       (comp-emit-assume 'and mvar-tested
+                         (make-comp-mvar :type (comp-cstr-cl-tag mvar-tag))
+                         (comp-add-cond-cstrs-target-block b bb1)
+                         t))
       (`((set ,(and (pred comp-mvar-p) cmp-res)
-              (,(pred comp-call-op-p)
-               ,(and (or (pred comp-equality-fun-p)
-                         (pred comp-arithm-cmp-fun-p))
+              (,(pred comp--call-op-p)
+               ,(and (or (pred comp--equality-fun-p)
+                         (pred comp--arithm-cmp-fun-p))
                      fun)
                ,op1 ,op2))
         ;; (comment ,_comment-str)
@@ -2006,14 +2009,14 @@ TARGET-BB-SYM is the symbol name of the target block."
                               block-target negated)))
         finally (cl-return-from in-the-basic-block)))
       (`((set ,(and (pred comp-mvar-p) cmp-res)
-              (,(pred comp-call-op-p)
-               ,(and (pred comp-known-predicate-p) fun)
+              (,(pred comp--call-op-p)
+               ,(and (pred comp--known-predicate-p) fun)
                ,op))
         ;; (comment ,_comment-str)
         (cond-jump ,cmp-res ,(pred comp-mvar-p) . ,blocks))
        (cl-loop
         with target-mvar = (comp-cond-cstrs-target-mvar op (car insns-seq) b)
-        with cstr = (comp-pred-to-cstr fun)
+        with cstr = (comp--pred-to-cstr fun)
         for branch-target-cell on blocks
         for branch-target = (car branch-target-cell)
         for negated in '(t nil)
@@ -2025,14 +2028,14 @@ TARGET-BB-SYM is the symbol name of the target block."
         finally (cl-return-from in-the-basic-block)))
       ;; Match predicate on the negated branch (unless).
       (`((set ,(and (pred comp-mvar-p) cmp-res)
-              (,(pred comp-call-op-p)
-               ,(and (pred comp-known-predicate-p) fun)
+              (,(pred comp--call-op-p)
+               ,(and (pred comp--known-predicate-p) fun)
                ,op))
          (set ,neg-cmp-res (call eq ,cmp-res ,(pred comp-cstr-null-p)))
         (cond-jump ,neg-cmp-res ,(pred comp-mvar-p) . ,blocks))
        (cl-loop
         with target-mvar = (comp-cond-cstrs-target-mvar op (car insns-seq) b)
-        with cstr = (comp-pred-to-cstr fun)
+        with cstr = (comp--pred-to-cstr fun)
         for branch-target-cell on blocks
         for branch-target = (car branch-target-cell)
         for negated in '(nil t)
@@ -2084,10 +2087,10 @@ TARGET-BB-SYM is the symbol name of the target block."
    (comp-loop-insn-in-block bb
      (when-let ((match
                  (pcase insn
-                   (`(set ,lhs (,(pred comp-call-op-p) ,f . ,args))
+                   (`(set ,lhs (,(pred comp--call-op-p) ,f . ,args))
                     (when-let ((cstr-f (gethash f comp-known-func-cstr-h)))
                       (cl-values f cstr-f lhs args)))
-                   (`(,(pred comp-call-op-p) ,f . ,args)
+                   (`(,(pred comp--call-op-p) ,f . ,args)
                     (when-let ((cstr-f (gethash f comp-known-func-cstr-h)))
                       (cl-values f cstr-f nil args))))))
        (cl-multiple-value-bind (f cstr-f lhs args) match
@@ -2126,7 +2129,7 @@ blocks."
                 (comp-add-cond-cstrs-simple)
                  (comp-add-cond-cstrs)
                  (comp-add-call-cstr)
-                 (comp-log-func comp-func 3))))
+                 (comp--log-func comp-func 3))))
            (comp-ctxt-funcs-h comp-ctxt)))
 
 
@@ -2145,9 +2148,9 @@ blocks."
    do (cl-loop
        for insn in (comp-block-insns b)
        do (pcase insn
-            (`(set ,_lval (,(pred comp-call-op-p) ,f . ,_rest))
+            (`(set ,_lval (,(pred comp--call-op-p) ,f . ,_rest))
              (puthash f t h))
-            (`(,(pred comp-call-op-p) ,f . ,_rest)
+            (`(,(pred comp--call-op-p) ,f . ,_rest)
              (puthash f t h))))
    finally return (cl-loop
                    for f being each hash-key of h
@@ -2160,7 +2163,7 @@ blocks."
 (defun comp-pure-infer-func (f)
   "If all functions called by F are pure then F is pure too."
   (when (and (cl-every (lambda (x)
-                         (or (comp-function-pure-p x)
+                         (or (comp--function-pure-p x)
                              (eq x (comp-func-name f))))
                        (comp-collect-calls f))
              (not (eq (comp-func-pure f) t)))
@@ -2224,16 +2227,16 @@ blocks."
            for (op first second third forth) = last-insn
            do (cl-case op
                 (jump
-                 (make-comp-edge :src bb :dst (gethash first blocks)))
+                 (comp--edge-make :src bb :dst (gethash first blocks)))
                 (cond-jump
-                 (make-comp-edge :src bb :dst (gethash third blocks))
-                 (make-comp-edge :src bb :dst (gethash forth blocks)))
+                 (comp--edge-make :src bb :dst (gethash third blocks))
+                 (comp--edge-make :src bb :dst (gethash forth blocks)))
                 (cond-jump-narg-leq
-                 (make-comp-edge :src bb :dst (gethash second blocks))
-                 (make-comp-edge :src bb :dst (gethash third blocks)))
+                 (comp--edge-make :src bb :dst (gethash second blocks))
+                 (comp--edge-make :src bb :dst (gethash third blocks)))
                 (push-handler
-                 (make-comp-edge :src bb :dst (gethash third blocks))
-                 (make-comp-edge :src bb :dst (gethash forth blocks)))
+                 (comp--edge-make :src bb :dst (gethash third blocks))
+                 (comp--edge-make :src bb :dst (gethash forth blocks)))
                 (return)
                 (unreachable)
                 (otherwise
@@ -2250,7 +2253,7 @@ blocks."
                   (comp-block-out-edges (comp-edge-src edge)))
             (push edge
                   (comp-block-in-edges (comp-edge-dst edge))))
-           (comp-log-edges comp-func)))
+           (comp--log-edges comp-func)))
 
 (defun comp-collect-rev-post-order (basic-block)
   "Walk BASIC-BLOCK children and return their name in reversed post-order."
@@ -2306,7 +2309,7 @@ blocks."
        do (cl-loop
            for name in (cdr rev-bb-list)
            for b = (gethash name blocks)
-           for preds = (comp-block-preds b)
+           for preds = (comp--block-preds b)
            for new-idom = (first-processed preds)
            initially (setf changed nil)
            do (cl-loop for p in (delq new-idom preds)
@@ -2326,7 +2329,7 @@ blocks."
   (cl-loop with blocks = (comp-func-blocks comp-func)
            for b-name being each hash-keys of blocks
            using (hash-value b)
-           for preds = (comp-block-preds b)
+           for preds = (comp--block-preds b)
            when (length> preds 1) ; All joins
            do (cl-loop for p in preds
                        for runner = p
@@ -2358,7 +2361,7 @@ blocks."
              ;; Return t if a SLOT-N was assigned within BB.
              (cl-loop for insn in (comp-block-insns bb)
                       for op = (car insn)
-                      when (or (and (comp-assign-op-p op)
+                      when (or (and (comp--assign-op-p op)
                                     (eql slot-n (comp-mvar-slot (cadr insn))))
                                ;; fetch-handler is after a non local
                                ;; therefore clobbers all frame!!!
@@ -2424,7 +2427,7 @@ PRE-LAMBDA and POST-LAMBDA are called in pre or 
post-order if non-nil."
                  (setf (comp-vec-aref frame slot-n) mvar
                        (cadr insn) mvar))))
      (pcase insn
-       (`(,(pred comp-assign-op-p) ,(pred targetp) . ,_)
+       (`(,(pred comp--assign-op-p) ,(pred targetp) . ,_)
         (let ((mvar (comp-vec-aref frame slot-n)))
           (setf (cddr insn) (cl-nsubst-if mvar #'targetp (cddr insn))))
         (new-lvalue))
@@ -2511,7 +2514,7 @@ Return t when one or more block was removed, nil 
otherwise."
                  (comp-place-phis)
                  (comp-ssa-rename)
                  (comp-finalize-phis)
-                 (comp-log-func comp-func 3)
+                 (comp--log-func comp-func 3)
                  (setf (comp-func-ssa-status f) t))))
            (comp-ctxt-funcs-h comp-ctxt)))
 
@@ -2574,7 +2577,7 @@ Forward propagate immediate involed in assignments." ; 
FIXME: Typo.  Involved or
 
 (defun comp-function-foldable-p (f args)
   "Given function F called with ARGS, return non-nil when optimizable."
-  (and (comp-function-pure-p f)
+  (and (comp--function-pure-p f)
        (cl-every #'comp-cstr-imm-vld-p args)))
 
 (defun comp-function-call-maybe-fold (insn f args)
@@ -2582,7 +2585,7 @@ Forward propagate immediate involed in assignments." ; 
FIXME: Typo.  Involved or
 Return non-nil if the function is folded successfully."
   (cl-flet ((rewrite-insn-as-setimm (insn value)
                ;; See `comp-emit-setimm'.
-               (comp-add-const-to-relocs value)
+               (comp--add-const-to-relocs value)
                (setf (car insn) 'setimm
                      (cddr insn) `(,value))))
     (cond
@@ -2599,7 +2602,7 @@ Return non-nil if the function is folded successfully."
         ;; should do basic block pruning in order to be sure that this
         ;; is not dead-code.  This is now left to gcc, to be
         ;; implemented only if we want a reliable diagnostic here.
-        (let* ((f (if-let (f-in-ctxt (comp-symbol-func-to-fun f))
+        (let* ((f (if-let (f-in-ctxt (comp--symbol-func-to-fun f))
                       ;; If the function is IN the compilation ctxt
                       ;; and know to be pure.
                       (comp-func-byte-func f-in-ctxt)
@@ -2645,6 +2648,8 @@ Fold the call in case."
        (_
         (comp-cstr-shallow-copy lval rval))))
     (`(assume ,lval ,(and (pred comp-mvar-p) rval))
+     ;; NOTE we should probably assert this case in the future when
+     ;; will be possible.
      (comp-cstr-shallow-copy lval rval))
     (`(assume ,lval (,kind . ,operands))
      (cl-case kind
@@ -2676,7 +2681,7 @@ Fold the call in case."
                                                (comp-func-blocks comp-func))))
                              (or (comp-latch-p bb)
                                  (when (comp-block-cstr-p bb)
-                                   (comp-latch-p (car (comp-block-preds 
bb)))))))
+                                   (comp-latch-p (car (comp--block-preds 
bb)))))))
                          rest))
             (prop-fn (if from-latch
                          #'comp-cstr-union-no-range
@@ -2743,7 +2748,7 @@ Return t if something was changed."
                      (format "fwprop pass jammed into %s?" (comp-func-name 
f))))
                   (comp-log (format "Propagation run %d times\n" i) 2))
                  (comp-rewrite-non-locals)
-                 (comp-log-func comp-func 3))))
+                 (comp--log-func comp-func 3))))
            (comp-ctxt-funcs-h comp-ctxt)))
 
 
@@ -2766,7 +2771,7 @@ Return t if something was changed."
   "Given FUNC return the `comp-fun' definition in the current context.
 FUNCTION can be a function-name or byte compiled function."
   (if (symbolp func)
-      (comp-symbol-func-to-fun func)
+      (comp--symbol-func-to-fun func)
     (cl-assert (byte-code-function-p func))
     (gethash func (comp-ctxt-byte-func-to-func-h comp-ctxt))))
 
@@ -2783,6 +2788,14 @@ FUNCTION can be a function-name or byte compiled 
function."
                     (symbol-function callee)
                   (cl-assert (byte-code-function-p callee))
                   callee))
+             ;; Below call to `subrp' returns nil on an advised
+             ;; primitive F, so that we do not optimize calls to F
+             ;; with the funcall trampoline removal below.  But if F
+             ;; is advised while we compile its call, it is very
+             ;; likely to be advised also when that call is executed.
+             ;; And in that case an "unoptimized" call to F is
+             ;; actually cheaper since it avoids the call to the
+             ;; intermediate native trampoline (bug#67005).
              (subrp (subrp f))
              (comp-func-callee (comp-func-in-unit callee)))
         (cond
@@ -2804,7 +2817,7 @@ FUNCTION can be a function-name or byte compiled 
function."
          ((and comp-func-callee
                (comp-func-c-name comp-func-callee)
                (or (and (>= (comp-func-speed comp-func) 3)
-                        (comp-func-unique-in-cu-p callee))
+                        (comp--func-unique-in-cu-p callee))
                    (and (>= (comp-func-speed comp-func) 2)
                         ;; Anonymous lambdas can't be redefined so are
                         ;; always safe to optimize.
@@ -2816,7 +2829,7 @@ FUNCTION can be a function-name or byte compiled 
function."
                            args
                          (fill-args args (comp-args-max func-args)))))
             `(,call-type ,(comp-func-c-name comp-func-callee) ,@args)))
-         ((comp-type-hint-p callee)
+         ((comp--type-hint-p callee)
           `(call ,callee ,@args)))))))
 
 (defun comp-call-optim-func ()
@@ -2873,7 +2886,7 @@ Return the list of m-var ids nuked."
      do (cl-loop
          for insn in (comp-block-insns b)
          for (op arg0 . rest) = insn
-         if (comp-assign-op-p op)
+         if (comp--assign-op-p op)
            do (push (comp-mvar-id arg0) l-vals)
               (setf r-vals (nconc (comp-collect-mvar-ids rest) r-vals))
          else
@@ -2891,10 +2904,10 @@ Return the list of m-var ids nuked."
        for b being each hash-value of (comp-func-blocks comp-func)
        do (comp-loop-insn-in-block b
             (cl-destructuring-bind (op &optional arg0 arg1 &rest rest) insn
-              (when (and (comp-assign-op-p op)
+              (when (and (comp--assign-op-p op)
                          (memq (comp-mvar-id arg0) nuke-list))
                 (setf insn
-                      (if (comp-limple-insn-call-p arg1)
+                      (if (comp--limple-insn-call-p arg1)
                           arg1
                         `(comment ,(format "optimized out: %s"
                                            insn))))))))
@@ -2911,7 +2924,7 @@ Return the list of m-var ids nuked."
                 for i from 1
                 while (comp-dead-assignments-func)
                 finally (comp-log (format "dead code rm run %d times\n" i) 2)
-                (comp-log-func comp-func 3))))
+                (comp--log-func comp-func 3))))
            (comp-ctxt-funcs-h comp-ctxt)))
 
 
@@ -2951,7 +2964,7 @@ Return the list of m-var ids nuked."
                         (not (comp-func-has-non-local f)))
                (let ((comp-func f))
                  (comp-tco-func)
-                 (comp-log-func comp-func 3))))
+                 (comp--log-func comp-func 3))))
            (comp-ctxt-funcs-h comp-ctxt)))
 
 
@@ -2967,7 +2980,7 @@ These are substituted with a normal `set' op."
    for b being each hash-value of (comp-func-blocks comp-func)
    do (comp-loop-insn-in-block b
         (pcase insn
-          (`(set ,l-val (call ,(pred comp-type-hint-p) ,r-val))
+          (`(set ,l-val (call ,(pred comp--type-hint-p) ,r-val))
            (setf insn `(set ,l-val ,r-val)))))))
 
 (defun comp-remove-type-hints (_)
@@ -2976,7 +2989,7 @@ These are substituted with a normal `set' op."
              (when (>= (comp-func-speed f) 2)
                (let ((comp-func f))
                  (comp-remove-type-hints-func)
-                 (comp-log-func comp-func 3))))
+                 (comp--log-func comp-func 3))))
            (comp-ctxt-funcs-h comp-ctxt)))
 
 
@@ -3029,7 +3042,7 @@ Set it into the `type' slot."
                              finally return res)))
            (type `(function ,(comp-args-to-lambda-list (comp-func-l-args func))
                             ,(comp-cstr-to-type-spec res-mvar))))
-      (comp-add-const-to-relocs type)
+      (comp--add-const-to-relocs type)
       ;; Fix it up.
       (setf (comp-cstr-imm (comp-func-type func)) type))))
 
@@ -3058,7 +3071,7 @@ Update all insn accordingly."
   ;; Symbols imported by C inlined functions.  We do this here because
   ;; is better to add all objs to the relocation containers before we
   ;; compacting them.
-  (mapc #'comp-add-const-to-relocs '(nil t consp listp symbol-with-pos-p))
+  (mapc #'comp--add-const-to-relocs '(nil t consp listp symbol-with-pos-p))
 
   (let* ((d-default (comp-ctxt-d-default comp-ctxt))
          (d-default-idx (comp-data-container-idx d-default))
@@ -3113,7 +3126,7 @@ Prepare every function for final compilation and drive 
the C back-end."
   (let ((dir (file-name-directory name)))
     (comp-finalize-relocs)
     (maphash (lambda (_ f)
-               (comp-log-func f 1))
+               (comp--log-func f 1))
              (comp-ctxt-funcs-h comp-ctxt))
     (unless (file-exists-p dir)
       ;; In case it's created in the meanwhile.
@@ -3325,9 +3338,9 @@ session."
         ;; Remove the old eln instead of copying the new one into it
         ;; to get a new inode and prevent crashes in case the old one
         ;; is currently loaded.
-        (t (delete-file oldfile)
-           (when newfile
-             (rename-file newfile oldfile)))))
+        (t (if newfile
+               (rename-file newfile oldfile t)
+             (delete-file oldfile)))))
 
 (defun comp--native-compile (function-or-file &optional with-late-load output)
   "Compile FUNCTION-OR-FILE into native code.
@@ -3363,7 +3376,7 @@ the deferred compilation mechanism."
                    for pass in comp-passes
                    unless (memq pass comp-disabled-passes)
                    do
-                   (comp-log (format "(%s) Running pass %s:\n"
+                   (comp-log (format "\n(%s) Running pass %s:\n"
                                      function-or-file pass)
                              2)
                    (setf data (funcall pass data))
@@ -3483,7 +3496,7 @@ last directory in `native-comp-eln-load-path')."
 Make sure that eln file is younger than byte-compiled one and
 return the filename of this last.
 
-This function can be used only in conjuntion with
+This function can be used only in conjunction with
 `byte+native-compile' `byte-to-native-output-buffer-file' (see
 `batch-byte+native-compile')."
   (pcase byte-to-native-output-buffer-file
diff --git a/lisp/emacs-lisp/copyright.el b/lisp/emacs-lisp/copyright.el
index 8295f86c078..54997318426 100644
--- a/lisp/emacs-lisp/copyright.el
+++ b/lisp/emacs-lisp/copyright.el
@@ -1,6 +1,6 @@
 ;;; copyright.el --- update the copyright notice in current buffer  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1991-1995, 1998, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1991-1995, 1998, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
diff --git a/lisp/emacs-lisp/crm.el b/lisp/emacs-lisp/crm.el
index 920118bb093..253dfc6237a 100644
--- a/lisp/emacs-lisp/crm.el
+++ b/lisp/emacs-lisp/crm.el
@@ -1,6 +1,6 @@
 ;;; crm.el --- read multiple strings with completion  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1985-1986, 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1993-2024 Free Software Foundation, Inc.
 
 ;; Author: Sen Nagata <sen@eccosys.com>
 ;; Keywords: completion, minibuffer, multiple elements
diff --git a/lisp/emacs-lisp/cursor-sensor.el b/lisp/emacs-lisp/cursor-sensor.el
index e20365e61e8..3fe41dc5004 100644
--- a/lisp/emacs-lisp/cursor-sensor.el
+++ b/lisp/emacs-lisp/cursor-sensor.el
@@ -1,6 +1,6 @@
 ;;; cursor-sensor.el --- React to cursor movement  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords:
diff --git a/lisp/emacs-lisp/debug-early.el b/lisp/emacs-lisp/debug-early.el
index 4425d13feef..9996ce3da23 100644
--- a/lisp/emacs-lisp/debug-early.el
+++ b/lisp/emacs-lisp/debug-early.el
@@ -1,6 +1,6 @@
 ;;; debug-early.el --- Dump a Lisp backtrace without frills  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Alan Mackenzie <acm@muc.de>
 ;; Maintainer: emacs-devel@gnu.org
@@ -27,7 +27,7 @@
 ;; This file dumps a backtrace on stderr when an error is thrown.  It
 ;; has no dependencies on any Lisp libraries and is thus used for
 ;; generating backtraces for bugs in the early parts of bootstrapping.
-;; It is also always used in batch model.  It was introduced in Emacs
+;; It is also always used in batch mode.  It was introduced in Emacs
 ;; 29, before which there was no backtrace available during early
 ;; bootstrap.
 
@@ -60,8 +60,11 @@ For details, see `debug-early-backtrace'."
              (princ " ")))
        (princ ")\n"))))
 
+;; For bootstrap reasons, we cannot use any macros here since they're
+;; not defined yet.
+
 (defalias 'debug-early-backtrace
-  #'(lambda ()
+  #'(lambda (&optional base)
       "Print a trace of Lisp function calls currently active.
 The output stream used is the value of `standard-output'.
 
@@ -88,7 +91,15 @@ of the build process."
         (mapbacktrace
          #'debug-early-frame))))
 
-(defalias 'debug-early
+(defalias 'debug--early
+  #'(lambda (error base)
+  (princ "\nError: ")
+  (prin1 (car error))  ; The error symbol.
+  (princ " ")
+  (prin1 (cdr error))  ; The error data.
+  (debug-early-backtrace base)))
+
+(defalias 'debug-early                  ;Called from C.
   #'(lambda (&rest args)
   "Print an error message with a backtrace of active Lisp function calls.
 The output stream used is the value of `standard-output'.
@@ -106,10 +117,31 @@ support the latter, except in batch mode which always uses
 
 \(In versions of Emacs prior to Emacs 29, no backtrace was
 available before `debug' was usable.)"
-  (princ "\nError: ")
-  (prin1 (car (car (cdr args))))       ; The error symbol.
-  (princ " ")
-  (prin1 (cdr (car (cdr args))))       ; The error data.
-  (debug-early-backtrace)))
+  (debug--early (car (cdr args)) #'debug-early)))      ; The error object.
+
+(defalias 'debug-early--handler         ;Called from C.
+  #'(lambda (err)
+      (if backtrace-on-error-noninteractive
+          (debug--early err #'debug-early--handler))))
+
+(defalias 'debug-early--muted           ;Called from C.
+  #'(lambda (err)
+      (save-current-buffer
+        (set-buffer (get-buffer-create "*Redisplay-trace*"))
+        (goto-char (point-max))
+        (if (bobp) nil
+          (let ((separator "\n\n\n\n"))
+            (save-excursion
+              ;; The C code tested `backtrace_yet', instead we
+              ;; keep a max of 10 backtraces.
+              (if (search-backward separator nil t 10)
+                (delete-region (point-min) (match-end 0))))
+            (insert separator)))
+        (insert "-- Caught at " (current-time-string) "\n")
+        (let ((standard-output (current-buffer)))
+          (debug--early err #'debug-early--muted))
+        (setq delayed-warnings-list
+              (cons '(error "Error in a redisplay Lisp hook.  See buffer 
*Redisplay-trace*")
+                    delayed-warnings-list)))))
 
 ;;; debug-early.el ends here.
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
index d6f08649ce9..7863df8b6e8 100644
--- a/lisp/emacs-lisp/debug.el
+++ b/lisp/emacs-lisp/debug.el
@@ -1,6 +1,6 @@
 ;;; debug.el --- debuggers and related commands for Emacs  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985-1986, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985-1986, 1994, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -239,12 +239,11 @@ the debugger will not be entered."
          (unwind-protect
              (save-excursion
                (when (eq (car debugger-args) 'debug)
-                 ;; Skip the frames for backtrace-debug, byte-code,
-                 ;; debug--implement-debug-on-entry and the advice's `apply'.
-                 (backtrace-debug 4 t)
-                 ;; Place an extra debug-on-exit for macro's.
-                 (when (eq 'lambda (car-safe (cadr (backtrace-frame 4))))
-                   (backtrace-debug 5 t)))
+                 (let ((base (debugger--backtrace-base)))
+                   (backtrace-debug 1 t base) ;FIXME!
+                   ;; Place an extra debug-on-exit for macro's.
+                   (when (eq 'lambda (car-safe (cadr (backtrace-frame 1 
base))))
+                     (backtrace-debug 2 t base))))
                 (with-current-buffer debugger-buffer
                   (unless (derived-mode-p 'debugger-mode)
                    (debugger-mode))
@@ -345,11 +344,10 @@ Make functions into cross-reference buttons if DO-XREFS 
is non-nil."
 (defun debugger-setup-buffer (args)
   "Initialize the `*Backtrace*' buffer for entry to the debugger.
 That buffer should be current already and in `debugger-mode'."
-  (setq backtrace-frames (nthcdr
-                          ;; Remove debug--implement-debug-on-entry and the
-                          ;; advice's `apply' frame.
-                          (if (eq (car args) 'debug) 3 1)
-                          (backtrace-get-frames 'debug)))
+  (setq backtrace-frames
+        ;; The `base' frame is the one that gets index 0 and it is the entry to
+        ;; the debugger, so drop it with `cdr'.
+        (cdr (backtrace-get-frames (debugger--backtrace-base))))
   (when (eq (car-safe args) 'exit)
     (setq debugger-value (nth 1 args))
     (setf (cl-getf (backtrace-frame-flags (car backtrace-frames))
@@ -479,26 +477,29 @@ removes itself from that hook."
   (setq debugger-jumping-flag nil)
   (remove-hook 'post-command-hook 'debugger-reenable))
 
-(defun debugger-frame-number (&optional skip-base)
+(defun debugger-frame-number ()
   "Return number of frames in backtrace before the one point points at."
-  (let ((index (backtrace-get-index))
-        (count 0))
+  (let ((index (backtrace-get-index)))
     (unless index
       (error "This line is not a function call"))
-    (unless skip-base
-        (while (not (eq (cadr (backtrace-frame count)) 'debug))
-          (setq count (1+ count)))
-        ;; Skip debug--implement-debug-on-entry frame.
-        (when (eq 'debug--implement-debug-on-entry
-                  (cadr (backtrace-frame (1+ count))))
-          (setq count (+ 2 count))))
-    (+ count index)))
+    ;; We have 3 representations of the backtrace: the real in C in `specpdl',
+    ;; the one stored in `backtrace-frames' and the textual version in
+    ;; the buffer.  Check here that the one from `backtrace-frames' is in sync
+    ;; with the one from `specpdl'.
+    (cl-assert (equal (backtrace-frame-fun (nth index backtrace-frames))
+                      (nth 1 (backtrace-frame (1+ index)
+                                              (debugger--backtrace-base)))))
+    ;; The `base' frame is the one that gets index 0 and it is the entry to
+    ;; the debugger, so the first non-debugger frame is 1.
+    ;; This `+1' skips the same frame as the `cdr' in
+    ;; `debugger-setup-buffer'.
+    (1+ index)))
 
 (defun debugger-frame ()
   "Request entry to debugger when this frame exits.
 Applies to the frame whose line point is on in the backtrace."
   (interactive)
-  (backtrace-debug (debugger-frame-number) t)
+  (backtrace-debug (debugger-frame-number) t (debugger--backtrace-base))
   (setf
    (cl-getf (backtrace-frame-flags (nth (backtrace-get-index) 
backtrace-frames))
             :debug-on-exit)
@@ -509,7 +510,7 @@ Applies to the frame whose line point is on in the 
backtrace."
   "Do not enter debugger when this frame exits.
 Applies to the frame whose line point is on in the backtrace."
   (interactive)
-  (backtrace-debug (debugger-frame-number) nil)
+  (backtrace-debug (debugger-frame-number) nil (debugger--backtrace-base))
   (setf
    (cl-getf (backtrace-frame-flags (nth (backtrace-get-index) 
backtrace-frames))
             :debug-on-exit)
@@ -528,10 +529,8 @@ Applies to the frame whose line point is on in the 
backtrace."
 (defun debugger--backtrace-base ()
   "Return the function name that marks the top of the backtrace.
 See `backtrace-frame'."
-  (cond ((eq 'debug--implement-debug-on-entry
-            (cadr (backtrace-frame 1 'debug)))
-        'debug--implement-debug-on-entry)
-       (t 'debug)))
+  (or (cadr (memq :backtrace-base debugger-args))
+      #'debug))
 
 (defun debugger-eval-expression (exp &optional nframe)
   "Eval an expression, in an environment like that outside the debugger.
@@ -539,7 +538,7 @@ The environment used is the one when entering the 
activation frame at point."
   (interactive
    (list (read--expression "Eval in stack frame: ")))
   (let ((nframe (or nframe
-                    (condition-case nil (1+ (debugger-frame-number 'skip-base))
+                    (condition-case nil (debugger-frame-number)
                       (error 0)))) ;; If on first line.
        (base (debugger--backtrace-base)))
     (debugger-env-macro
@@ -672,7 +671,10 @@ functions to break on entry."
   (if (or inhibit-debug-on-entry debugger-jumping-flag)
       nil
     (let ((inhibit-debug-on-entry t))
-      (funcall debugger 'debug))))
+      (funcall debugger 'debug :backtrace-base
+               ;; An offset of 1 because we need to skip the advice
+               ;; OClosure that called us.
+               '(1 . debug--implement-debug-on-entry)))))
 
 ;;;###autoload
 (defun debug-on-entry (function)
diff --git a/lisp/emacs-lisp/derived.el b/lisp/emacs-lisp/derived.el
index 5f7e9fbfe37..2ac602e0a97 100644
--- a/lisp/emacs-lisp/derived.el
+++ b/lisp/emacs-lisp/derived.el
@@ -1,7 +1,7 @@
 ;;; derived.el --- allow inheritance of major modes  -*- lexical-binding: t; 
-*-
 ;; (formerly mode-clone.el)
 
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
 ;; Author: David Megginson <dmeggins@aix1.uottawa.ca>
 ;; Maintainer: emacs-devel@gnu.org
@@ -212,10 +212,10 @@ See Info node `(elisp)Derived Modes' for more details.
        (defvar ,hook nil)
        (unless (get ',hook 'variable-documentation)
          (put ',hook 'variable-documentation
-              ,(format "Hook run after entering %s mode.
+              ,(format "Hook run after entering `%S'.
 No problems result if this variable is not bound.
 `add-hook' automatically binds it.  (This is true for all hook variables.)"
-                       name)))
+                       child)))
        (unless (boundp ',map)
         (put ',map 'definition-name ',child))
        (with-no-warnings (defvar ,map (make-sparse-keymap)))
@@ -366,137 +366,6 @@ which more-or-less shadow%s %s's corresponding table%s."
     docstring))
 
 
-;;; OBSOLETE
-;; The functions below are only provided for backward compatibility with
-;; code byte-compiled with versions of derived.el prior to Emacs-21.
-
-(defsubst derived-mode-setup-function-name (mode)
-  "Construct a setup-function name based on a MODE name."
-  (declare (obsolete nil "28.1"))
-  (intern (concat (symbol-name mode) "-setup")))
-
-
-;; Utility functions for defining a derived mode.
-
-;;;###autoload
-(defun derived-mode-init-mode-variables (mode)
-  "Initialize variables for a new MODE.
-Right now, if they don't already exist, set up a blank keymap, an
-empty syntax table, and an empty abbrev table -- these will be merged
-the first time the mode is used."
-
-  (if (boundp (derived-mode-map-name mode))
-      t
-    (eval `(defvar ,(derived-mode-map-name mode)
-              (make-sparse-keymap)
-              ,(format "Keymap for %s." mode)))
-    (put (derived-mode-map-name mode) 'derived-mode-unmerged t))
-
-  (if (boundp (derived-mode-syntax-table-name mode))
-      t
-    (eval `(defvar ,(derived-mode-syntax-table-name mode)
-            ;; Make a syntax table which doesn't specify anything
-            ;; for any char.  Valid data will be merged in by
-            ;; derived-mode-merge-syntax-tables.
-            (make-char-table 'syntax-table nil)
-            ,(format "Syntax table for %s." mode)))
-    (put (derived-mode-syntax-table-name mode) 'derived-mode-unmerged t))
-
-  (if (boundp (derived-mode-abbrev-table-name mode))
-      t
-    (eval `(defvar ,(derived-mode-abbrev-table-name mode)
-            (progn
-              (define-abbrev-table (derived-mode-abbrev-table-name ',mode) nil)
-              (make-abbrev-table))
-            ,(format "Abbrev table for %s." mode)))))
-
-;; Utility functions for running a derived mode.
-
-(defun derived-mode-set-keymap (mode)
-  "Set the keymap of the new MODE, maybe merging with the parent."
-  (let* ((map-name (derived-mode-map-name mode))
-        (new-map (eval map-name))
-        (old-map (current-local-map)))
-    (and old-map
-        (get map-name 'derived-mode-unmerged)
-        (derived-mode-merge-keymaps old-map new-map))
-    (put map-name 'derived-mode-unmerged nil)
-    (use-local-map new-map)))
-
-(defun derived-mode-set-syntax-table (mode)
-  "Set the syntax table of the new MODE, maybe merging with the parent."
-  (let* ((table-name (derived-mode-syntax-table-name mode))
-        (old-table (syntax-table))
-        (new-table (eval table-name)))
-    (if (get table-name 'derived-mode-unmerged)
-       (derived-mode-merge-syntax-tables old-table new-table))
-    (put table-name 'derived-mode-unmerged nil)
-    (set-syntax-table new-table)))
-
-(defun derived-mode-set-abbrev-table (mode)
-  "Set the abbrev table for MODE if it exists.
-Always merge its parent into it, since the merge is non-destructive."
-  (let* ((table-name (derived-mode-abbrev-table-name mode))
-        (old-table local-abbrev-table)
-        (new-table (eval table-name)))
-    (derived-mode-merge-abbrev-tables old-table new-table)
-    (setq local-abbrev-table new-table)))
-
-(defun derived-mode-run-hooks (mode)
-   "Run the mode hook for MODE."
-   (let ((hooks-name (derived-mode-hook-name mode)))
-     (if (boundp hooks-name)
-         (run-hooks hooks-name))))
-
-;; Functions to merge maps and tables.
-
-(defun derived-mode-merge-keymaps (old new)
-  "Merge an OLD keymap into a NEW one.
-The old keymap is set to be the last cdr of the new one, so that there will
-be automatic inheritance."
-  ;; ?? Can this just use `set-keymap-parent'?
-  (let ((tail new))
-    ;; Scan the NEW map for prefix keys.
-    (while (consp tail)
-      (and (consp (car tail))
-          (let* ((key (vector (car (car tail))))
-                 (subnew (lookup-key new key))
-                 (subold (lookup-key old key)))
-            ;; If KEY is a prefix key in both OLD and NEW, merge them.
-            (and (keymapp subnew) (keymapp subold)
-                 (derived-mode-merge-keymaps subold subnew))))
-      (and (vectorp (car tail))
-          ;; Search a vector of ASCII char bindings for prefix keys.
-          (let ((i (1- (length (car tail)))))
-            (while (>= i 0)
-              (let* ((key (vector i))
-                     (subnew (lookup-key new key))
-                     (subold (lookup-key old key)))
-                ;; If KEY is a prefix key in both OLD and NEW, merge them.
-                (and (keymapp subnew) (keymapp subold)
-                     (derived-mode-merge-keymaps subold subnew)))
-              (setq i (1- i)))))
-      (setq tail (cdr tail))))
-  (setcdr (nthcdr (1- (length new)) new) old))
-
-(defun derived-mode-merge-syntax-tables (old new)
-  "Merge an OLD syntax table into a NEW one.
-Where the new table already has an entry, nothing is copied from the old one."
-  (set-char-table-parent new old))
-
-;; Merge an old abbrev table into a new one.
-;; This function requires internal knowledge of how abbrev tables work,
-;; presuming that they are obarrays with the abbrev as the symbol, the 
expansion
-;; as the value of the symbol, and the hook as the function definition.
-(defun derived-mode-merge-abbrev-tables (old new)
-  (if old
-      (mapatoms
-       (lambda (symbol)
-        (or (intern-soft (symbol-name symbol) new)
-            (define-abbrev new (symbol-name symbol)
-              (symbol-value symbol) (symbol-function symbol))))
-       old)))
-
 (provide 'derived)
 
 ;;; derived.el ends here
diff --git a/lisp/emacs-lisp/disass.el b/lisp/emacs-lisp/disass.el
index d9295686e9f..b7db2adde59 100644
--- a/lisp/emacs-lisp/disass.el
+++ b/lisp/emacs-lisp/disass.el
@@ -1,6 +1,6 @@
 ;;; disass.el --- disassembler for compiled Emacs Lisp code  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1986, 1991, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 1991, 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Doug Cutting <doug@csli.stanford.edu>
 ;;     Jamie Zawinski <jwz@lucid.com>
@@ -191,8 +191,6 @@ OBJ should be a call to BYTE-CODE generated by the byte 
compiler."
     (if (consp obj)
        (setq bytes (car (cdr obj))             ;the byte code
              constvec (car (cdr (cdr obj))))   ;constant vector
-      ;; If it is lazy-loaded, load it now
-      (fetch-bytecode obj)
       (setq bytes (aref obj 1)
            constvec (aref obj 2)))
     (cl-assert (not (multibyte-string-p bytes)))
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el
index 5c4354616dc..fe9a9b0d9b6 100644
--- a/lisp/emacs-lisp/easy-mmode.el
+++ b/lisp/emacs-lisp/easy-mmode.el
@@ -1,6 +1,6 @@
 ;;; easy-mmode.el --- easy definition for major and minor modes  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Georges Brun-Cottan <Georges.Brun-Cottan@inria.fr>
 ;; Maintainer: Stefan Monnier <monnier@gnu.org>
diff --git a/lisp/emacs-lisp/easymenu.el b/lisp/emacs-lisp/easymenu.el
index 21c70fa70e0..6740c2af58d 100644
--- a/lisp/emacs-lisp/easymenu.el
+++ b/lisp/emacs-lisp/easymenu.el
@@ -1,6 +1,6 @@
 ;;; easymenu.el --- support the easymenu interface for defining a menu  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1994, 1996, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1996, 1998-2024 Free Software Foundation, Inc.
 
 ;; Keywords: emulations
 ;; Author: Richard Stallman <rms@gnu.org>
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index 0a1076e5bc6..4dbbeb69312 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -1,6 +1,6 @@
 ;;; edebug.el --- a source-level debugger for Emacs Lisp  -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 1988-1995, 1997, 1999-2023 Free Software Foundation,
+;; Copyright (C) 1988-1995, 1997, 1999-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Daniel LaLiberte <liberte@holonexus.org>
diff --git a/lisp/emacs-lisp/eieio-base.el b/lisp/emacs-lisp/eieio-base.el
index 31ca91ad317..1df33be8571 100644
--- a/lisp/emacs-lisp/eieio-base.el
+++ b/lisp/emacs-lisp/eieio-base.el
@@ -1,6 +1,6 @@
 ;;; eieio-base.el --- Base classes for EIEIO.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: OO, lisp
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el
index 37c5ebdb6da..9c526f67204 100644
--- a/lisp/emacs-lisp/eieio-core.el
+++ b/lisp/emacs-lisp/eieio-core.el
@@ -1,6 +1,6 @@
 ;;; eieio-core.el --- Core implementation for eieio  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1995-1996, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1996, 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Version: 1.4
diff --git a/lisp/emacs-lisp/eieio-custom.el b/lisp/emacs-lisp/eieio-custom.el
index 1e1b9d721b0..704eac65ea2 100644
--- a/lisp/emacs-lisp/eieio-custom.el
+++ b/lisp/emacs-lisp/eieio-custom.el
@@ -1,6 +1,6 @@
 ;;; eieio-custom.el --- eieio object customization  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2001, 2005, 2007-2023 Free Software Foundation,
+;; Copyright (C) 1999-2001, 2005, 2007-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/emacs-lisp/eieio-datadebug.el 
b/lisp/emacs-lisp/eieio-datadebug.el
index a80d1ae2720..455092d1c9b 100644
--- a/lisp/emacs-lisp/eieio-datadebug.el
+++ b/lisp/emacs-lisp/eieio-datadebug.el
@@ -1,6 +1,6 @@
 ;;; eieio-datadebug.el --- EIEIO extensions to the data debugger.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: OO, lisp
diff --git a/lisp/emacs-lisp/eieio-opt.el b/lisp/emacs-lisp/eieio-opt.el
index 7b054169ca1..893f8cd7e7f 100644
--- a/lisp/emacs-lisp/eieio-opt.el
+++ b/lisp/emacs-lisp/eieio-opt.el
@@ -1,6 +1,6 @@
 ;;; eieio-opt.el --- eieio optional functions (debug, printing, speedbar)  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996, 1998-2003, 2005, 2008-2023 Free Software
+;; Copyright (C) 1996, 1998-2003, 2005, 2008-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/emacs-lisp/eieio-speedbar.el 
b/lisp/emacs-lisp/eieio-speedbar.el
index 25626d01ecc..f3094b8b5d6 100644
--- a/lisp/emacs-lisp/eieio-speedbar.el
+++ b/lisp/emacs-lisp/eieio-speedbar.el
@@ -1,6 +1,6 @@
 ;;; eieio-speedbar.el --- Classes for managing speedbar displays.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1999-2002, 2005, 2007-2023 Free Software Foundation,
+;; Copyright (C) 1999-2002, 2005, 2007-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index 8224606ec57..df85a64baf3 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -1,7 +1,7 @@
 ;;; eieio.el --- Enhanced Implementation of Emacs Interpreted Objects  -*- 
lexical-binding:t -*-
 ;;;              or maybe Eric's Implementation of Emacs Interpreted Objects
 
-;; Copyright (C) 1995-1996, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1996, 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Version: 1.4
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index 22144ed7c18..912a7357ca7 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -1,11 +1,11 @@
 ;;; eldoc.el --- Show function arglist or variable docstring in echo area  -*- 
lexical-binding:t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Noah Friedman <friedman@splode.com>
 ;; Keywords: extensions
 ;; Created: 1995-10-06
-;; Version: 1.14.0
+;; Version: 1.15.0
 ;; Package-Requires: ((emacs "26.3"))
 
 ;; This is a GNU ELPA :core package.  Avoid functionality that is not
@@ -312,9 +312,11 @@ Otherwise, it displays the message like `message' would."
                      (not (and (listp mode-line-format)
                                (assq 'eldoc-mode-line-string 
mode-line-format))))
            (setq mode-line-format
-                 (list "" '(eldoc-mode-line-string
-                            (" " eldoc-mode-line-string " "))
-                       mode-line-format)))
+                  (funcall
+                   (if (listp mode-line-format) #'append #'list)
+                   (list "" '(eldoc-mode-line-string
+                             (" " eldoc-mode-line-string " ")))
+                   mode-line-format)))
           (setq eldoc-mode-line-string
                 (when (stringp format-string)
                   (apply #'format-message format-string args)))
@@ -605,25 +607,29 @@ known to be truncated."
                     'maybe)))
        (get-buffer-window eldoc--doc-buffer t)))
 
-(defun eldoc-display-in-echo-area (docs _interactive)
+(defun eldoc-display-in-echo-area (docs interactive)
   "Display DOCS in echo area.
-Honor `eldoc-echo-area-use-multiline-p' and
+INTERACTIVE is non-nil if user explicitly invoked ElDoc.  Honor
+`eldoc-echo-area-use-multiline-p' and
 `eldoc-echo-area-prefer-doc-buffer'."
   (cond
-   (;; Check if we have permission to mess with echo area at all.  For
-    ;; example, if this-command is non-nil while running via an idle
-    ;; timer, we're still in the middle of executing a command, e.g. a
-    ;; query-replace where it would be annoying to overwrite the echo
-    ;; area.
-    (or
-     (not (eldoc-display-message-no-interference-p))
-     this-command
-     (not (eldoc--message-command-p last-command))))
-   (;; If we do but nothing to report, clear the echo area.
+   ((and (not interactive)
+         ;; When called non-interactively, check if we have permission
+         ;; to mess with echo area at all.  For example, if
+         ;; this-command is non-nil while running via an idle timer,
+         ;; we're still in the middle of executing a command, e.g. a
+         ;; query-replace where it would be annoying to overwrite the
+         ;; echo area.
+         (or
+          (not (eldoc-display-message-no-interference-p))
+          this-command
+          (not (eldoc--message-command-p last-command)))))
+   (;; If nothing to report, clear the echo area.
     (null docs)
     (eldoc--message nil))
    (t
-    ;; Otherwise, establish some parameters.
+    ;; Otherwise, proceed to change the echo area.  Start by
+    ;; establishing some parameters.
     (let*
         ((width (1- (window-width (minibuffer-window))))
          (val (if (and (symbolp eldoc-echo-area-use-multiline-p)
@@ -929,7 +935,7 @@ the docstrings eventually produced, using
       (let* ((eldoc--make-callback #'make-callback)
              (res (funcall eldoc-documentation-strategy)))
         ;; Observe the old and the new protocol:
-        (cond (;; Old protocol: got string, e-d-strategy is iself the
+        (cond (;; Old protocol: got string, e-d-strategy is itself the
                ;; origin function, and we output immediately;
                (stringp res)
                (register-doc 0 res nil eldoc-documentation-strategy)
diff --git a/lisp/emacs-lisp/elint.el b/lisp/emacs-lisp/elint.el
index d8ab883b58d..a8bc4bdd1e0 100644
--- a/lisp/emacs-lisp/elint.el
+++ b/lisp/emacs-lisp/elint.el
@@ -1,6 +1,6 @@
 ;;; elint.el --- Lint Emacs Lisp -*- lexical-binding: t -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Peter Liljenberg <petli@lysator.liu.se>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/elp.el b/lisp/emacs-lisp/elp.el
index d50d0e029e9..9181b498a2e 100644
--- a/lisp/emacs-lisp/elp.el
+++ b/lisp/emacs-lisp/elp.el
@@ -1,6 +1,6 @@
 ;;; elp.el --- Emacs Lisp Profiler  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Barry A. Warsaw
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/ert-font-lock.el b/lisp/emacs-lisp/ert-font-lock.el
index 6a02cf7acc4..29114712f92 100644
--- a/lisp/emacs-lisp/ert-font-lock.el
+++ b/lisp/emacs-lisp/ert-font-lock.el
@@ -1,6 +1,6 @@
 ;;; ert-font-lock.el --- ERT Font Lock   -*- lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: Vladimir Kazanov
 ;; Keywords: lisp, tools
@@ -28,7 +28,7 @@
 ;;
 ;; ert-font-lock entry points are functions
 ;; `ert-font-lock-test-string' and `ert-font-lock-test-file' and
-;; covenience macros: `ert-font-lock-deftest' and
+;; convenience macros: `ert-font-lock-deftest' and
 ;; `ert-font-lock-deftest-file'.
 ;;
 ;; See unit tests in ert-font-lock-tests.el for usage examples.
diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el
index e8b0dd92989..cd60f9f457f 100644
--- a/lisp/emacs-lisp/ert-x.el
+++ b/lisp/emacs-lisp/ert-x.el
@@ -1,6 +1,6 @@
 ;;; ert-x.el --- Staging area for experimental extensions to ERT  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2008, 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008, 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Lennart Borgman (lennart O borgman A gmail O com)
 ;;         Christian Ohler <ohler@gnu.org>
@@ -540,10 +540,10 @@ The same keyword arguments are supported as in
 (when (and (featurep 'tramp) (getenv "EMACS_HYDRA_CI"))
   (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
 
-;; If this defconst is used in a test file, `tramp' shall be loaded
+;; If this defvar is used in a test file, `tramp' shall be loaded
 ;; prior `ert-x'.  There is no default value on w32 systems, which
 ;; could work out of the box.
-(defconst ert-remote-temporary-file-directory
+(defvar ert-remote-temporary-file-directory
   (when (featurep 'tramp)
     (cond
      ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index f101c5c1fa6..76d54125668 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -1,6 +1,6 @@
 ;;; ert.el --- Emacs Lisp Regression Testing  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Christian Ohler <ohler@gnu.org>
 ;; Keywords: lisp, tools
@@ -99,7 +99,7 @@ Even modest settings for `print-length' and `print-level' can
 produce extremely long lines in backtraces and lengthy delays in
 forming them.  This variable governs the target maximum line
 length by manipulating these two variables while printing stack
-traces.  Setting this variable to t will re-use the value of
+traces.  Setting this variable to t will reuse the value of
 `backtrace-line-length' while printing stack traces in ERT batch
 mode.  Any other value will be temporarily bound to
 `backtrace-line-length' when producing stack traces in batch
@@ -279,14 +279,6 @@ DATA is displayed to the user and should state the reason 
for skipping."
   (when ert--should-execution-observer
     (funcall ert--should-execution-observer form-description)))
 
-;; See Bug#24402 for why this exists
-(defun ert--should-signal-hook (error-symbol data)
-  "Stupid hack to stop `condition-case' from catching ert signals.
-It should only be stopped when ran from inside `ert--run-test-internal'."
-  (when (and (not (symbolp debugger))   ; only run on anonymous debugger
-             (memq error-symbol '(ert-test-failed ert-test-skipped)))
-    (funcall debugger 'error (cons error-symbol data))))
-
 (defun ert--special-operator-p (thing)
   "Return non-nil if THING is a symbol naming a special operator."
   (and (symbolp thing)
@@ -325,8 +317,7 @@ It should only be stopped when ran from inside 
`ert--run-test-internal'."
               (default-value (gensym "ert-form-evaluation-aborted-")))
           `(let* ((,fn (function ,fn-name))
                   (,args (condition-case err
-                             (let ((signal-hook-function 
#'ert--should-signal-hook))
-                               (list ,@arg-forms))
+                             (list ,@arg-forms)
                            (error (progn (setq ,fn #'signal)
                                          (list (car err)
                                                (cdr err)))))))
@@ -729,78 +720,68 @@ in front of the value of MESSAGE-FORM."
   ;; value and test execution should be terminated.  Should not
   ;; return.
   (exit-continuation (cl-assert nil))
-  ;; The binding of `debugger' outside of the execution of the test.
-  next-debugger
   ;; The binding of `ert-debug-on-error' that is in effect for the
   ;; execution of the current test.  We store it to avoid being
   ;; affected by any new bindings the test itself may establish.  (I
   ;; don't remember whether this feature is important.)
   ert-debug-on-error)
 
-(defun ert--run-test-debugger (info args)
-  "During a test run, `debugger' is bound to a closure that calls this 
function.
+(defun ert--run-test-debugger (info condition debugfun)
+  "Error handler used during the test run.
 
 This function records failures and errors and either terminates
 the test silently or calls the interactive debugger, as
 appropriate.
 
-INFO is the ert--test-execution-info corresponding to this test
-run.  ARGS are the arguments to `debugger'."
-  (cl-destructuring-bind (first-debugger-arg &rest more-debugger-args)
-      args
-    (cl-ecase first-debugger-arg
-      ((lambda debug t exit nil)
-       (apply (ert--test-execution-info-next-debugger info) args))
-      (error
-       (let* ((condition (car more-debugger-args))
-              (type (cl-case (car condition)
-                      ((quit) 'quit)
-                     ((ert-test-skipped) 'skipped)
-                      (otherwise 'failed)))
-              ;; We store the backtrace in the result object for
-              ;; `ert-results-pop-to-backtrace-for-test-at-point'.
-              ;; This means we have to limit `print-level' and
-              ;; `print-length' when printing result objects.  That
-              ;; might not be worth while when we can also use
-              ;; `ert-results-rerun-test-at-point-debugging-errors',
-              ;; (i.e., when running interactively) but having the
-              ;; backtrace ready for printing is important for batch
-              ;; use.
-              ;;
-              ;; Grab the frames above the debugger.
-              (backtrace (cdr (backtrace-get-frames debugger)))
-              (infos (reverse ert--infos)))
-         (setf (ert--test-execution-info-result info)
-               (cl-ecase type
-                 (quit
-                  (make-ert-test-quit :condition condition
-                                      :backtrace backtrace
-                                      :infos infos))
-                 (skipped
-                  (make-ert-test-skipped :condition condition
-                                        :backtrace backtrace
-                                        :infos infos))
-                 (failed
-                  (make-ert-test-failed :condition condition
-                                        :backtrace backtrace
-                                        :infos infos))))
-         ;; Work around Emacs's heuristic (in eval.c) for detecting
-         ;; errors in the debugger.
-         (cl-incf num-nonmacro-input-events)
-         ;; FIXME: We should probably implement more fine-grained
-         ;; control a la non-t `debug-on-error' here.
-         (cond
-          ((ert--test-execution-info-ert-debug-on-error info)
-           (apply (ert--test-execution-info-next-debugger info) args))
-          (t))
-         (funcall (ert--test-execution-info-exit-continuation info)))))))
+INFO is the `ert--test-execution-info' corresponding to this test run.
+ERR is the error object."
+  (let* ((type (cl-case (car condition)
+                 ((quit) 'quit)
+                ((ert-test-skipped) 'skipped)
+                 (otherwise 'failed)))
+         ;; We store the backtrace in the result object for
+         ;; `ert-results-pop-to-backtrace-for-test-at-point'.
+         ;; This means we have to limit `print-level' and
+         ;; `print-length' when printing result objects.  That
+         ;; might not be worth while when we can also use
+         ;; `ert-results-rerun-test-at-point-debugging-errors',
+         ;; (i.e., when running interactively) but having the
+         ;; backtrace ready for printing is important for batch
+         ;; use.
+         ;;
+         ;; Grab the frames above ourselves.
+         (backtrace (cdr (backtrace-get-frames debugfun)))
+         (infos (reverse ert--infos)))
+    (setf (ert--test-execution-info-result info)
+          (cl-ecase type
+            (quit
+             (make-ert-test-quit :condition condition
+                                 :backtrace backtrace
+                                 :infos infos))
+            (skipped
+             (make-ert-test-skipped :condition condition
+                                    :backtrace backtrace
+                                    :infos infos))
+            (failed
+             (make-ert-test-failed :condition condition
+                                   :backtrace backtrace
+                                   :infos infos))))
+    ;; FIXME: We should probably implement more fine-grained
+    ;; control a la non-t `debug-on-error' here.
+    (cond
+     ((ert--test-execution-info-ert-debug-on-error info)
+      ;; The `debugfun' arg tells `debug' which backtrace frame starts
+      ;; the "entering the debugger" code so it can hide those frames
+      ;; from the backtrace.
+      (funcall debugger 'error condition :backtrace-base debugfun))
+     (t))
+    (funcall (ert--test-execution-info-exit-continuation info))))
 
 (defun ert--run-test-internal (test-execution-info)
   "Low-level function to run a test according to TEST-EXECUTION-INFO.
 
 This mainly sets up debugger-related bindings."
-  (setf (ert--test-execution-info-next-debugger test-execution-info) debugger
-        (ert--test-execution-info-ert-debug-on-error test-execution-info)
+  (setf (ert--test-execution-info-ert-debug-on-error test-execution-info)
         ert-debug-on-error)
   (catch 'ert--pass
     ;; For now, each test gets its own temp buffer and its own
@@ -808,26 +789,14 @@ This mainly sets up debugger-related bindings."
     ;; too expensive, we can remove it.
     (with-temp-buffer
       (save-window-excursion
-        ;; FIXME: Use `signal-hook-function' instead of `debugger' to
-        ;; handle ert errors. Once that's done, remove
-        ;; `ert--should-signal-hook'.  See Bug#24402 and Bug#11218 for
-        ;; details.
-        (let ((lexical-binding t)
-              (debugger (lambda (&rest args)
-                          (ert--run-test-debugger test-execution-info
-                                                  args)))
-              (debug-on-error t)
-              ;; Don't infloop if the error being called is erroring
-              ;; out, and we have `debug-on-error' bound to nil inside
-              ;; the test.
-              (backtrace-on-error-noninteractive nil)
-              (debug-on-quit t)
-              ;; FIXME: Do we need to store the old binding of this
-              ;; and consider it in `ert--run-test-debugger'?
-              (debug-ignored-errors nil)
+        (let ((lexical-binding t) ;;FIXME: Why?
               (ert--infos '()))
-          (funcall (ert-test-body (ert--test-execution-info-test
-                                   test-execution-info))))))
+          (letrec ((debugfun (lambda (err)
+                               (ert--run-test-debugger test-execution-info
+                                                       err debugfun))))
+            (handler-bind (((error quit) debugfun))
+              (funcall (ert-test-body (ert--test-execution-info-test
+                                       test-execution-info))))))))
     (ert-pass))
   (setf (ert--test-execution-info-result test-execution-info)
         (make-ert-test-passed))
diff --git a/lisp/emacs-lisp/ewoc.el b/lisp/emacs-lisp/ewoc.el
index 56527afcf12..da481c9850a 100644
--- a/lisp/emacs-lisp/ewoc.el
+++ b/lisp/emacs-lisp/ewoc.el
@@ -1,6 +1,6 @@
 ;;; ewoc.el --- utility to maintain a view of a list of objects in a buffer  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
 
 ;; Author: Per Cederqvist <ceder@lysator.liu.se>
 ;;     Inge Wallin <inge@lysator.liu.se>
diff --git a/lisp/emacs-lisp/faceup.el b/lisp/emacs-lisp/faceup.el
index f8d6c263cd1..f54bd08428c 100644
--- a/lisp/emacs-lisp/faceup.el
+++ b/lisp/emacs-lisp/faceup.el
@@ -1,6 +1,6 @@
 ;;; faceup.el --- Markup language for faces and font-lock regression testing  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Anders Lindgren
 ;; Version: 0.0.6
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index 24d31fefd7d..63f547ebeb8 100644
--- a/lisp/emacs-lisp/find-func.el
+++ b/lisp/emacs-lisp/find-func.el
@@ -1,6 +1,6 @@
 ;;; find-func.el --- find the definition of the Emacs Lisp function near point 
 -*- lexical-binding:t -*-
 
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Jens Petersen <petersen@kurims.kyoto-u.ac.jp>
 ;; Keywords: emacs-lisp, functions, variables
diff --git a/lisp/emacs-lisp/float-sup.el b/lisp/emacs-lisp/float-sup.el
index 84083c65292..32c0b31bdcf 100644
--- a/lisp/emacs-lisp/float-sup.el
+++ b/lisp/emacs-lisp/float-sup.el
@@ -1,6 +1,6 @@
 ;;; float-sup.el --- define some constants useful for floating point numbers.  
-*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1987, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1987, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
diff --git a/lisp/emacs-lisp/generate-lisp-file.el 
b/lisp/emacs-lisp/generate-lisp-file.el
index b2f67ab848d..2c4d2c7cb9a 100644
--- a/lisp/emacs-lisp/generate-lisp-file.el
+++ b/lisp/emacs-lisp/generate-lisp-file.el
@@ -1,6 +1,6 @@
 ;;; generate-lisp-file.el --- utility functions for generated files  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Keywords: maint
 ;; Package: emacs
diff --git a/lisp/emacs-lisp/generator.el b/lisp/emacs-lisp/generator.el
index 82cc954e887..7f97a0eba41 100644
--- a/lisp/emacs-lisp/generator.el
+++ b/lisp/emacs-lisp/generator.el
@@ -1,6 +1,6 @@
 ;;; generator.el --- generators  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Daniel Colascione <dancol@dancol.org>
 ;; Keywords: extensions, elisp
diff --git a/lisp/emacs-lisp/generic.el b/lisp/emacs-lisp/generic.el
index b734bff1108..2d51f93a77b 100644
--- a/lisp/emacs-lisp/generic.el
+++ b/lisp/emacs-lisp/generic.el
@@ -1,6 +1,6 @@
 ;;; generic.el --- defining simple major modes with comment and font-lock  -*- 
lexical-binding: t; -*-
 ;;
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Peter Breton <pbreton@cs.umb.edu>
 ;; Created: Fri Sep 27 1996
diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el
index 97060f0474e..c1be86f52be 100644
--- a/lisp/emacs-lisp/gv.el
+++ b/lisp/emacs-lisp/gv.el
@@ -1,6 +1,6 @@
 ;;; gv.el --- generalized variables  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: extensions
@@ -639,7 +639,7 @@ REF must have been previously obtained with `gv-ref'."
 
 ;;; Generalized variables.
 
-;; You'd think noone would write `(setf (error ...) ..)' but it
+;; You'd think no one would write `(setf (error ...) ..)' but it
 ;; appears naturally as the result of macroexpansion of things like
 ;; (setf (pcase-exhaustive ...)).
 ;; We could generalize this to `throw' and `signal', but it seems
diff --git a/lisp/emacs-lisp/helper.el b/lisp/emacs-lisp/helper.el
index 5d6fa6a77ea..0446109f5ac 100644
--- a/lisp/emacs-lisp/helper.el
+++ b/lisp/emacs-lisp/helper.el
@@ -1,6 +1,6 @@
 ;;; helper.el --- utility help package supporting help in electric modes  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Author: K. Shane Hartman
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/hierarchy.el b/lisp/emacs-lisp/hierarchy.el
index 05509378c82..9011f3d164d 100644
--- a/lisp/emacs-lisp/hierarchy.el
+++ b/lisp/emacs-lisp/hierarchy.el
@@ -1,6 +1,6 @@
 ;;; hierarchy.el --- Library to create and display hierarchical structures  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Damien Cassou <damien@cassou.me>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/icons.el b/lisp/emacs-lisp/icons.el
index 9a6d26243c7..f9591661688 100644
--- a/lisp/emacs-lisp/icons.el
+++ b/lisp/emacs-lisp/icons.el
@@ -1,6 +1,6 @@
 ;;; icons.el --- Handling icons  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: icons buttons
@@ -164,7 +164,7 @@ If OBJECT is an icon, return the icon properties."
 (defun icon-elements (name)
   "Return the elements of icon NAME.
 The elements are represented as a plist where the keys are
-`string', `face' and `display'.  The `image' element is only
+`string', `face' and `image'.  The `image' element is only
 present if the icon is represented by an image."
   (let ((string (icon-string name)))
     (list 'face (get-text-property 0 'face string)
@@ -187,11 +187,13 @@ present if the icon is represented by an image."
   merged)
 
 (cl-defmethod icons--create ((_type (eql 'image)) icon keywords)
-  (let ((file (if (file-name-absolute-p icon)
-                  icon
-                (and (fboundp 'image-search-load-path)
-                     (image-search-load-path icon)))))
-    (and (display-images-p)
+  (let* ((file (if (file-name-absolute-p icon)
+                   icon
+                 (and (fboundp 'image-search-load-path)
+                      (image-search-load-path icon))))
+         (file-exists (and (stringp file) (file-readable-p file))))
+    (and file-exists
+         (display-images-p)
          (fboundp 'image-supported-file-p)
          (image-supported-file-p file)
          (propertize
diff --git a/lisp/emacs-lisp/inline.el b/lisp/emacs-lisp/inline.el
index f761fda29a8..ddbd6fdc017 100644
--- a/lisp/emacs-lisp/inline.el
+++ b/lisp/emacs-lisp/inline.el
@@ -1,6 +1,6 @@
 ;;; inline.el --- Define functions by their inliner  -*- lexical-binding:t; -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 
@@ -80,7 +80,9 @@
   (error "inline-const-p can only be used within define-inline"))
 
 (defmacro inline-const-val (_exp)
-  "Return the value of EXP."
+  "Return the value of EXP.
+During inlining, if the value of EXP is not yet known, this aborts the
+inlining and makes us revert to a non-inlined function call."
   (declare (debug t))
   (error "inline-const-val can only be used within define-inline"))
 
diff --git a/lisp/emacs-lisp/let-alist.el b/lisp/emacs-lisp/let-alist.el
index ed07aecf338..cdd476d9df6 100644
--- a/lisp/emacs-lisp/let-alist.el
+++ b/lisp/emacs-lisp/let-alist.el
@@ -1,6 +1,6 @@
 ;;; let-alist.el --- Easily let-bind values of an assoc-list by their names 
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Artur Malabarba <emacs@endlessparentheses.com>
 ;; Package-Requires: ((emacs "24.1"))
diff --git a/lisp/emacs-lisp/lisp-mnt.el b/lisp/emacs-lisp/lisp-mnt.el
index cb7cff43555..f111a77663c 100644
--- a/lisp/emacs-lisp/lisp-mnt.el
+++ b/lisp/emacs-lisp/lisp-mnt.el
@@ -1,6 +1,7 @@
 ;;; lisp-mnt.el --- utility functions for Emacs Lisp maintainers  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1994, 1997, 2000-2024 Free Software Foundation,
+;; Inc.
 
 ;; Author: Eric S. Raymond <esr@thyrsus.com>
 ;; Maintainer: emacs-devel@gnu.org
@@ -434,6 +435,38 @@ This can be found in an RCS or SCCS header."
             header-max t)
            (match-string-no-properties 1)))))))
 
+(defun lm--prepare-package-dependencies (deps)
+  "Turn DEPS into an acceptable list of dependencies.
+
+Any parts missing a version string get a default version string
+of \"0\" (meaning any version) and an appropriate level of lists
+is wrapped around any parts requiring it."
+  (cond
+   ((not (listp deps))
+    (error "Invalid requirement specifier: %S" deps))
+   (t (mapcar (lambda (dep)
+                (cond
+                 ((symbolp dep) `(,dep "0"))
+                 ((stringp dep)
+                  (error "Invalid requirement specifier: %S" dep))
+                 ((and (listp dep) (null (cdr dep)))
+                  (list (car dep) "0"))
+                 (t dep)))
+              deps))))
+
+(declare-function package-read-from-string "package" (str))
+
+(defun lm-package-requires (&optional file)
+  "Return dependencies listed in file FILE, or current buffer if FILE is nil.
+The return value is a list of elements of the form (PACKAGE VERSION)
+where PACKAGE is the package name (a symbol) and VERSION is the
+package version (a string)."
+  (require 'package)
+  (lm-with-file file
+    (and-let* ((require-lines (lm-header-multiline "package-requires")))
+      (lm--prepare-package-dependencies
+       (package-read-from-string (mapconcat #'identity require-lines " "))))))
+
 (defun lm-keywords (&optional file)
   "Return the keywords given in file FILE, or current buffer if FILE is nil.
 The return is a `downcase'-ed string, or nil if no keywords
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index b1fc65b09ac..ad0525e24be 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -1,6 +1,6 @@
 ;;; lisp-mode.el --- Lisp mode, and its idiosyncratic commands  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1985-1986, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1999-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: lisp, languages
@@ -343,7 +343,7 @@ This will generate compile-time constants from BINDINGS."
      (lisp-vdefs '("defvar"))
      (lisp-kw '("cond" "if" "while" "let" "let*" "progn" "prog1"
                 "prog2" "lambda" "unwind-protect" "condition-case"
-                "when" "unless" "with-output-to-string"
+                "when" "unless" "with-output-to-string" "handler-bind"
                 "ignore-errors" "dotimes" "dolist" "declare"))
      (lisp-errs '("warn" "error" "signal"))
      ;; Elisp constructs.  Now they are update dynamically
@@ -376,7 +376,7 @@ This will generate compile-time constants from BINDINGS."
      (cl-kw '("block" "break" "case" "ccase" "compiler-let" "ctypecase"
               "declaim" "destructuring-bind" "do" "do*"
               "ecase" "etypecase" "eval-when" "flet" "flet*"
-              "go" "handler-case" "handler-bind" "in-package" ;; "inline"
+              "go" "handler-case" "in-package" ;; "inline"
               "labels" "letf" "locally" "loop"
               "macrolet" "multiple-value-bind" "multiple-value-prog1"
               "proclaim" "prog" "prog*" "progv"
@@ -1346,7 +1346,6 @@ Lisp function does not specify a special indentation."
 (put 'catch 'lisp-indent-function 1)
 (put 'condition-case 'lisp-indent-function 2)
 (put 'handler-case 'lisp-indent-function 1) ;CL
-(put 'handler-bind 'lisp-indent-function 1) ;CL
 (put 'unwind-protect 'lisp-indent-function 1)
 (put 'with-output-to-temp-buffer 'lisp-indent-function 1)
 (put 'closure 'lisp-indent-function 2)
@@ -1421,14 +1420,15 @@ A prefix argument specifies pretty-printing."
 
 ;;;; Lisp paragraph filling commands.
 
-(defcustom emacs-lisp-docstring-fill-column 65
+(defcustom emacs-lisp-docstring-fill-column 72
   "Value of `fill-column' to use when filling a docstring.
 Any non-integer value means do not use a different value of
 `fill-column' when filling docstrings."
   :type '(choice (integer)
                  (const :tag "Use the current `fill-column'" t))
   :safe (lambda (x) (or (eq x t) (integerp x)))
-  :group 'lisp)
+  :group 'lisp
+  :version "30.1")
 
 (defun lisp-fill-paragraph (&optional justify)
   "Like \\[fill-paragraph], but handle Emacs Lisp comments and docstrings.
diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el
index ee481dc4ed3..c57b1357f63 100644
--- a/lisp/emacs-lisp/lisp.el
+++ b/lisp/emacs-lisp/lisp.el
@@ -1,6 +1,6 @@
 ;;; lisp.el --- Lisp editing commands for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1986, 1994, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1985-1986, 1994, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -93,7 +93,7 @@ report errors as appropriate for this kind of usage."
 
 (defun mark-sexp (&optional arg allow-extend)
   "Set mark ARG sexps from point or move mark one sexp.
-When called from Lisp with ALLOW-EXTEND ommitted or nil, mark is
+When called from Lisp with ALLOW-EXTEND omitted or nil, mark is
 set ARG sexps from point.
 With ARG and ALLOW-EXTEND both non-nil (interactively, with prefix
 argument), the place to which mark goes is the same place \\[forward-sexp]
diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el
index 04bea4723a2..5f152d3b509 100644
--- a/lisp/emacs-lisp/loaddefs-gen.el
+++ b/lisp/emacs-lisp/loaddefs-gen.el
@@ -1,6 +1,6 @@
 ;;; loaddefs-gen.el --- generate loaddefs.el files  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Keywords: maint
 ;; Package: emacs
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index 63800891efd..e55eb72b985 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -1,6 +1,6 @@
 ;;; macroexp.el --- Additional macro-expansion support -*- lexical-binding: t 
-*-
 ;;
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Miles Bader <miles@gnu.org>
 ;; Keywords: lisp, compiler, macros
@@ -39,6 +39,12 @@ of `byte-compile-form', etc., and manually popped off at its 
end.
 This is to preserve the data in it in the event of a
 condition-case handling a signaled error.")
 
+(defmacro macroexp--with-extended-form-stack (expr &rest body)
+  "Evaluate BODY with EXPR pushed onto `byte-compile-form-stack'."
+  (declare (indent 1))
+  `(let ((byte-compile-form-stack (cons ,expr byte-compile-form-stack)))
+     ,@body))
+
 ;; Bound by the top-level `macroexpand-all', and modified to include any
 ;; macros defined by `defmacro'.
 (defvar macroexpand-all-environment nil)
@@ -343,8 +349,7 @@ Only valid during macro-expansion."
   "Expand all macros in FORM.
 This is an internal version of `macroexpand-all'.
 Assumes the caller has bound `macroexpand-all-environment'."
-  (push form byte-compile-form-stack)
-  (prog1
+  (macroexp--with-extended-form-stack form
       (if (eq (car-safe form) 'backquote-list*)
           ;; Special-case `backquote-list*', as it is normally a macro that
           ;; generates exceedingly deep expansions from relatively shallow 
input
@@ -543,8 +548,7 @@ Assumes the caller has bound `macroexpand-all-environment'."
             ((guard (and (not byte-compile-in-progress)
                          (symbol-with-pos-p form)))
              (bare-symbol form))
-            (_ form))))
-    (pop byte-compile-form-stack)))
+            (_ form))))))
 
 ;;;###autoload
 (defun macroexpand-all (form &optional environment)
diff --git a/lisp/emacs-lisp/map-ynp.el b/lisp/emacs-lisp/map-ynp.el
index fffb199e2ea..b603f2e6d0b 100644
--- a/lisp/emacs-lisp/map-ynp.el
+++ b/lisp/emacs-lisp/map-ynp.el
@@ -1,6 +1,6 @@
 ;;; map-ynp.el --- general-purpose boolean question-asker  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1991-1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-1995, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Roland McGrath <roland@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el
index b46c74343c0..ffbb29615da 100644
--- a/lisp/emacs-lisp/map.el
+++ b/lisp/emacs-lisp/map.el
@@ -1,6 +1,6 @@
 ;;; map.el --- Map manipulation functions  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Petton <nicolas@petton.fr>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/memory-report.el b/lisp/emacs-lisp/memory-report.el
index 36754277034..661f28ffcb8 100644
--- a/lisp/emacs-lisp/memory-report.el
+++ b/lisp/emacs-lisp/memory-report.el
@@ -1,6 +1,6 @@
 ;;; memory-report.el --- Short function summaries  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Keywords: lisp, help
 
diff --git a/lisp/emacs-lisp/multisession.el b/lisp/emacs-lisp/multisession.el
index 4f95fc91dd8..8299e3dffcc 100644
--- a/lisp/emacs-lisp/multisession.el
+++ b/lisp/emacs-lisp/multisession.el
@@ -1,6 +1,6 @@
 ;;; multisession.el --- Multisession storage for variables  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el
index e8aad839c8c..0a20fd96201 100644
--- a/lisp/emacs-lisp/nadvice.el
+++ b/lisp/emacs-lisp/nadvice.el
@@ -1,6 +1,6 @@
 ;;; nadvice.el --- Light-weight advice primitives for Elisp functions  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: extensions, lisp, tools
@@ -562,8 +562,6 @@ HOW can be one of:
 <<>>"
   ;; TODO:
   ;; - record the advice location, to display in describe-function.
-  ;; - change all defadvice in lisp/**/*.el.
-  ;; - obsolete advice.el.
   (let* ((f (symbol-function symbol))
         (nf (advice--normalize symbol f)))
     (unless (eq f nf) (fset symbol nf))
@@ -594,6 +592,32 @@ Contrary to `remove-function', this also works when SYMBOL 
is a macro
 or an autoload and it preserves `fboundp'.
 Instead of the actual function to remove, FUNCTION can also be the `name'
 of the piece of advice."
+  (interactive
+   (let* ((pred (lambda (sym) (advice--p (advice--symbol-function sym))))
+          (default (when-let* ((f (function-called-at-point))
+                               ((funcall pred f)))
+                     (symbol-name f)))
+          (prompt (format-prompt "Remove advice from function" default))
+          (symbol (intern (completing-read prompt obarray pred t nil nil 
default)))
+          advices)
+     (advice-mapc (lambda (f p)
+                    (let ((k (or (alist-get 'name p) f)))
+                      (push (cons
+                             ;; "name" (string) and 'name (symbol) are
+                             ;; considered different names so we use
+                             ;; `prin1-to-string' even if the name is
+                             ;; a string to distinguish between these
+                             ;; two cases.
+                             (prin1-to-string k)
+                             ;; We use `k' here instead of `f' because
+                             ;; the same advice can have multiple
+                             ;; names.
+                             k)
+                            advices)))
+                  symbol)
+     (list symbol (cdr (assoc-string
+                        (completing-read "Advice to remove: " advices nil t)
+                        advices)))))
   (let ((f (symbol-function symbol)))
     (remove-function (cond ;This is `advice--symbol-function' but as a "place".
                       ((get symbol 'advice--pending)
@@ -614,8 +638,8 @@ of the piece of advice."
 (defmacro define-advice (symbol args &rest body)
   "Define an advice and add it to function named SYMBOL.
 See `advice-add' and `add-function' for explanation on the
-arguments.  Note if NAME is nil the advice is anonymous;
-otherwise it is named `SYMBOL@NAME'.
+arguments.  If NAME is non-nil, the advice is named `SYMBOL@NAME'
+and installed with the name NAME; otherwise, the advice is anonymous.
 
 \(fn SYMBOL (HOW LAMBDA-LIST &optional NAME DEPTH) &rest BODY)"
   (declare (indent 2) (doc-string 3) (debug (sexp sexp def-body)))
@@ -626,7 +650,9 @@ otherwise it is named `SYMBOL@NAME'.
          (lambda-list   (nth 1 args))
          (name          (nth 2 args))
          (depth         (nth 3 args))
-         (props         (and depth `((depth . ,depth))))
+         (props         (append
+                         (and depth `((depth . ,depth)))
+                         (and name `((name . ,name)))))
          (advice (cond ((null name) `(lambda ,lambda-list ,@body))
                        ((or (stringp name) (symbolp name))
                         (intern (format "%s@%s" symbol name)))
diff --git a/lisp/emacs-lisp/oclosure.el b/lisp/emacs-lisp/oclosure.el
index c23dd5a36da..26cd8594dfc 100644
--- a/lisp/emacs-lisp/oclosure.el
+++ b/lisp/emacs-lisp/oclosure.el
@@ -1,6 +1,6 @@
 ;;; oclosure.el --- Open Closures       -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Package: emacs
diff --git a/lisp/emacs-lisp/package-vc.el b/lisp/emacs-lisp/package-vc.el
index 9780e4d53de..db0cc515e46 100644
--- a/lisp/emacs-lisp/package-vc.el
+++ b/lisp/emacs-lisp/package-vc.el
@@ -1,6 +1,6 @@
 ;;; package-vc.el --- Manage packages from VC checkouts     -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Philip Kaludercic <philipk@posteo.net>
 ;; Keywords: tools
@@ -29,7 +29,7 @@
 ;; To install a package from source use `package-vc-install'.  If you
 ;; aren't interested in activating a package, you can use
 ;; `package-vc-checkout' instead, which will prompt you for a target
-;; directory.  If you wish to re-use an existing checkout, the command
+;; directory.  If you wish to reuse an existing checkout, the command
 ;; `package-vc-install-from-checkout' will create a symbolic link and
 ;; prepare the package.
 ;;
@@ -503,10 +503,6 @@ identify a package as a VC package later on), building
 documentation and marking the package as installed."
   (let ((pkg-spec (package-vc--desc->spec pkg-desc))
         missing)
-    ;; Remove any previous instance of PKG-DESC from `package-alist'
-    (let ((pkgs (assq (package-desc-name pkg-desc) package-alist)))
-      (when pkgs
-        (setf (cdr pkgs) (seq-remove #'package-vc-p (cdr pkgs)))))
 
     ;; In case the package was installed directly from source, the
     ;; dependency list wasn't know beforehand, and they might have
@@ -531,7 +527,7 @@ documentation and marking the package as installed."
               (thread-last
                 (mapconcat #'identity require-lines " ")
                 package-read-from-string
-                package--prepare-dependencies
+                lm--prepare-package-dependencies
                 (nconc deps)
                 (setq deps))))))
       (dolist (dep deps)
@@ -576,6 +572,11 @@ documentation and marking the package as installed."
         (dolist (doc-file (ensure-list (plist-get pkg-spec :doc)))
           (package-vc--build-documentation pkg-desc doc-file))))
 
+    ;; Remove any previous instance of PKG-DESC from `package-alist'
+    (let ((pkgs (assq (package-desc-name pkg-desc) package-alist)))
+      (when pkgs
+        (setf (cdr pkgs) (seq-remove #'package-vc-p (cdr pkgs)))))
+
     ;; Update package-alist.
     (let ((new-desc (package-load-descriptor pkg-dir)))
       ;; Activation has to be done before compilation, so that if we're
@@ -862,7 +863,7 @@ package uses `file-name-base' on the URL to obtain the 
package
 name, otherwise NAME is the package name as a symbol.
 
 PACKAGE can also be a cons cell (PNAME . SPEC) where PNAME is the
-package name as a symbol, and SPEC is a plist that specifes how
+package name as a symbol, and SPEC is a plist that specifies how
 to fetch and build the package.  For possible values, see the
 subsection \"Specifying Package Sources\" in the Info
 node `(emacs)Fetching Package Sources'.
diff --git a/lisp/emacs-lisp/package-x.el b/lisp/emacs-lisp/package-x.el
index 6c4e2a578b2..ca1b8532fa4 100644
--- a/lisp/emacs-lisp/package-x.el
+++ b/lisp/emacs-lisp/package-x.el
@@ -1,6 +1,6 @@
 ;;; package-x.el --- Package extras  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Tom Tromey <tromey@redhat.com>
 ;; Created: 10 Mar 2007
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index d4bb6710283..868373f46c2 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -1,6 +1,6 @@
 ;;; package.el --- Simple package system for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Tom Tromey <tromey@redhat.com>
 ;;         Daniel Hackney <dan@haxney.org>
@@ -1149,27 +1149,8 @@ Signal an error if the entire string was not used."
                (error "Can't read whole string"))
       (end-of-file expr))))
 
-(defun package--prepare-dependencies (deps)
-  "Turn DEPS into an acceptable list of dependencies.
-
-Any parts missing a version string get a default version string
-of \"0\" (meaning any version) and an appropriate level of lists
-is wrapped around any parts requiring it."
-  (cond
-   ((not (listp deps))
-    (error "Invalid requirement specifier: %S" deps))
-   (t (mapcar (lambda (dep)
-                (cond
-                 ((symbolp dep) `(,dep "0"))
-                 ((stringp dep)
-                  (error "Invalid requirement specifier: %S" dep))
-                 ((and (listp dep) (null (cdr dep)))
-                  (list (car dep) "0"))
-                 (t dep)))
-              deps))))
-
 (declare-function lm-header "lisp-mnt" (header))
-(declare-function lm-header-multiline "lisp-mnt" (header))
+(declare-function lm-package-requires "lisp-mnt" (&optional file))
 (declare-function lm-website "lisp-mnt" (&optional file))
 (declare-function lm-keywords-list "lisp-mnt" (&optional file))
 (declare-function lm-maintainers "lisp-mnt" (&optional file))
@@ -1192,8 +1173,14 @@ boundaries."
     ;; requirement for a "footer line" without unduly impacting users
     ;; on earlier Emacs versions.  See Bug#26490 for more details.
     (unless (search-forward (concat ";;; " file-name ".el ends here") nil 
'move)
-      (lwarn '(package package-format) :warning
-             "Package lacks a terminating comment"))
+      ;; Starting in Emacs 30.1, avoid warning if the minimum Emacs
+      ;; version is specified as 30.1 or later.
+      (let ((min-emacs (cadar (seq-filter (lambda (x) (eq (car x) 'emacs))
+                                          (lm-package-requires)))))
+        (when (or (null min-emacs)
+                  (version< min-emacs "30.1"))
+          (lwarn '(package package-format) :warning
+                 "Package lacks a terminating comment"))))
     ;; Try to include a trailing newline.
     (forward-line)
     (narrow-to-region start (point))
@@ -1212,9 +1199,7 @@ boundaries."
            (error "Package lacks a \"Version\" or \"Package-Version\" 
header")))
       (package-desc-from-define
        file-name pkg-version desc
-       (and-let* ((require-lines (lm-header-multiline "package-requires")))
-         (package--prepare-dependencies
-          (package-read-from-string (mapconcat #'identity require-lines " "))))
+       (lm-package-requires)
        :kind 'single
        :url website
        :keywords keywords
@@ -1720,18 +1705,26 @@ The variable `package-load-list' controls which 
packages to load."
                    package-quickstart-file))))
     ;; The quickstart file presumes that it has a blank slate,
     ;; so don't use it if we already activated some packages.
-    (if (and qs (not (bound-and-true-p package-activated-list)))
-        ;; Skip load-source-file-function which would slow us down by a factor
-        ;; 2 when loading the .el file (this assumes we were careful to
-        ;; save this file so it doesn't need any decoding).
-        (let ((load-source-file-function nil))
-          (unless (boundp 'package-activated-list)
-            (setq package-activated-list nil))
-          (load qs nil 'nomessage))
-      (require 'package)
-      (package--activate-all)))))
+    (or (and qs (not (bound-and-true-p package-activated-list))
+             ;; Skip `load-source-file-function' which would slow us down by
+             ;; a factor 2 when loading the .el file (this assumes we were
+             ;; careful to save this file so it doesn't need any decoding).
+             (with-demoted-errors "Error during quickstart: %S"
+               (let ((load-source-file-function nil))
+                 (unless (boundp 'package-activated-list)
+                   (setq package-activated-list nil))
+                 (load qs nil 'nomessage)
+                 t)))
+        (progn
+          (require 'package)
+          ;; Silence the "unknown function" warning when this is compiled
+          ;; inside `loaddefs.el'.
+          ;; FIXME: We use `with-no-warnings' because the effect of
+          ;; `declare-function' is currently not scoped, so if we use
+          ;; it here, we end up with a redefinition warning instead :-)
+          (with-no-warnings
+            (package--activate-all)))))))
 
-;;;###autoload
 (defun package--activate-all ()
   (dolist (elt (package--alist))
     (condition-case err
@@ -2811,8 +2804,7 @@ Helper function for `describe-package'."
          (status (if desc (package-desc-status desc) "orphan"))
          (incompatible-reason (package--incompatible-p desc))
          (signed (if desc (package-desc-signed desc)))
-         (maintainers (or (cdr (assoc :maintainers extras))
-                          (list (cdr (assoc :maintainer extras)))))
+         (maintainers (cdr (assoc :maintainer extras)))
          (authors (cdr (assoc :authors extras)))
          (news (and-let* (pkg-dir
                           ((not built-in))
@@ -4077,8 +4069,8 @@ invocations."
 (defun package-menu--version-predicate (A B)
   "Predicate to sort \"*Packages*\" buffer by the version column.
 This is used for `tabulated-list-format' in `package-menu-mode'."
-  (let ((vA (or (version-to-list (aref (cadr A) 1)) '(0)))
-        (vB (or (version-to-list (aref (cadr B) 1)) '(0))))
+  (let ((vA (or (ignore-error error (version-to-list (aref (cadr A) 1))) '(0)))
+        (vB (or (ignore-error error (version-to-list (aref (cadr B) 1))) 
'(0))))
     (if (version-list-= vA vB)
         (package-menu--name-predicate A B)
       (version-list-< vA vB))))
@@ -4706,18 +4698,23 @@ will be signaled in that case."
   (let* ((name (package-desc-name pkg-desc))
          (extras (package-desc-extras pkg-desc))
          (maint (alist-get :maintainer extras)))
+    (unless (listp (cdr maint))
+      (setq maint (list maint)))
     (cond
      ((and (null maint) (null no-error))
       (user-error "Package `%s' has no explicit maintainer" name))
      ((and (not (progn
                   (require 'ietf-drums)
-                  (ietf-drums-parse-address (cdr maint))))
+                  (ietf-drums-parse-address (cdar maint))))
            (null no-error))
       (user-error "Package `%s' has no maintainer address" name))
-     ((not (null maint))
+     (t
       (with-temp-buffer
-        (package--print-email-button maint)
-        (string-trim (substring-no-properties (buffer-string))))))))
+        (mapc #'package--print-email-button maint)
+        (replace-regexp-in-string
+         "\n" ", " (string-trim
+                    (buffer-substring-no-properties
+                     (point-min) (point-max)))))))))
 
 ;;;###autoload
 (defun package-report-bug (desc)
@@ -4727,17 +4724,19 @@ DESC must be a `package-desc' object."
                package-menu-mode)
   (let ((maint (package-maintainers desc))
         (name (symbol-name (package-desc-name desc)))
+        (pkgdir (package-desc-dir desc))
         vars)
-    (dolist-with-progress-reporter (group custom-current-group-alist)
-        "Scanning for modified user options..."
-      (when (and (car group)
-                 (file-in-directory-p (car group) (package-desc-dir desc)))
-        (dolist (ent (get (cdr group) 'custom-group))
-          (when (and (custom-variable-p (car ent))
-                     (boundp (car ent))
-                     (not (eq (custom--standard-value (car ent))
-                              (default-toplevel-value (car ent)))))
-            (push (car ent) vars)))))
+    (when pkgdir
+      (dolist-with-progress-reporter (group custom-current-group-alist)
+          "Scanning for modified user options..."
+        (when (and (car group)
+                   (file-in-directory-p (car group) pkgdir))
+          (dolist (ent (get (cdr group) 'custom-group))
+            (when (and (custom-variable-p (car ent))
+                       (boundp (car ent))
+                       (not (eq (custom--standard-value (car ent))
+                                (default-toplevel-value (car ent)))))
+              (push (car ent) vars))))))
     (dlet ((reporter-prompt-for-summary-p t))
       (reporter-submit-bug-report maint name vars))))
 
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index a089b9c11a6..0eb0ac84147 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -1,6 +1,6 @@
 ;;; pcase.el --- ML-style pattern-matching macro for Elisp -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: extensions
@@ -42,6 +42,14 @@
 ;; - ideally we'd want (pcase s ((re RE1) E1) ((re RE2) E2)) to be able to
 ;;   generate a lex-style DFA to decide whether to run E1 or E2.
 
+;; While the first version was written before I knew about Racket's `match'
+;; construct, the second version was significantly influenced by it,
+;; so a good presentation of the underlying ideas can be found at:
+;;
+;;   Extensible Pattern Matching in an Extensible Language
+;;   Sam Tobin-Hochstadt, 2010
+;;   https://arxiv.org/abs/1106.2578
+
 ;;; Code:
 
 (require 'macroexp)
diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el
index a93e634c685..1d722051406 100644
--- a/lisp/emacs-lisp/pp.el
+++ b/lisp/emacs-lisp/pp.el
@@ -1,6 +1,6 @@
 ;;; pp.el --- pretty printer for Emacs Lisp  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1989, 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Randal Schwartz <merlyn@stonehenge.com>
 ;; Keywords: lisp
diff --git a/lisp/emacs-lisp/radix-tree.el b/lisp/emacs-lisp/radix-tree.el
index 9b80b6c4614..7c4354fdc48 100644
--- a/lisp/emacs-lisp/radix-tree.el
+++ b/lisp/emacs-lisp/radix-tree.el
@@ -1,6 +1,6 @@
 ;;; radix-tree.el --- A simple library of radix trees  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords:
diff --git a/lisp/emacs-lisp/range.el b/lisp/emacs-lisp/range.el
index f441c240a27..19a6da34acb 100644
--- a/lisp/emacs-lisp/range.el
+++ b/lisp/emacs-lisp/range.el
@@ -1,6 +1,6 @@
 ;;; ranges.el --- range functions  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 
diff --git a/lisp/emacs-lisp/re-builder.el b/lisp/emacs-lisp/re-builder.el
index 0b2b9cde795..0a47cca0231 100644
--- a/lisp/emacs-lisp/re-builder.el
+++ b/lisp/emacs-lisp/re-builder.el
@@ -1,6 +1,6 @@
 ;;; re-builder.el --- building Regexps with visual feedback -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Detlev Zundel <dzu@gnu.org>
 ;; Keywords: matching, lisp, tools
diff --git a/lisp/emacs-lisp/regexp-opt.el b/lisp/emacs-lisp/regexp-opt.el
index 39325a3c35e..59c1b7d8e10 100644
--- a/lisp/emacs-lisp/regexp-opt.el
+++ b/lisp/emacs-lisp/regexp-opt.el
@@ -1,6 +1,6 @@
 ;;; regexp-opt.el --- generate efficient regexps to match strings -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Marshall <simon@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/regi.el b/lisp/emacs-lisp/regi.el
index cac617c9637..8c87edcb6db 100644
--- a/lisp/emacs-lisp/regi.el
+++ b/lisp/emacs-lisp/regi.el
@@ -1,6 +1,6 @@
 ;;; regi.el --- REGular expression Interpreting engine  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: 1993 Barry A. Warsaw, Century Computing, Inc. <bwarsaw@cen.com>
 ;; Created:       24-Feb-1993
diff --git a/lisp/emacs-lisp/ring.el b/lisp/emacs-lisp/ring.el
index d0d96721121..efd9316b2ef 100644
--- a/lisp/emacs-lisp/ring.el
+++ b/lisp/emacs-lisp/ring.el
@@ -1,6 +1,6 @@
 ;;; ring.el --- handle rings of items   -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: extensions
diff --git a/lisp/emacs-lisp/rmc.el b/lisp/emacs-lisp/rmc.el
index 45e2bbf3831..378687c0326 100644
--- a/lisp/emacs-lisp/rmc.el
+++ b/lisp/emacs-lisp/rmc.el
@@ -1,6 +1,6 @@
 ;;; rmc.el --- read from a multiple choice question -*- lexical-binding: t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 
diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el
index afc9826eefa..246e41cff0b 100644
--- a/lisp/emacs-lisp/rx.el
+++ b/lisp/emacs-lisp/rx.el
@@ -1,6 +1,6 @@
 ;;; rx.el --- S-exp notation for regexps           --*- lexical-binding: t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index 346250c1d35..4c6553972c2 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -1,6 +1,6 @@
 ;;; seq.el --- Sequence manipulation functions  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Petton <nicolas@petton.fr>
 ;; Keywords: sequences
diff --git a/lisp/emacs-lisp/shadow.el b/lisp/emacs-lisp/shadow.el
index 12c3ffde2c1..e1aa9da14ba 100644
--- a/lisp/emacs-lisp/shadow.el
+++ b/lisp/emacs-lisp/shadow.el
@@ -1,6 +1,6 @@
 ;;; shadow.el --- locate Emacs Lisp file shadowings  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Terry Jones <terry@santafe.edu>
 ;; Keywords: lisp
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index 1fa798beae1..a6a49c72f74 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -1,6 +1,6 @@
 ;;; shortdoc.el --- Short function summaries  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Keywords: lisp, help
 ;; Package: emacs
@@ -572,10 +572,7 @@ A FUNC form can have any number of `:no-eval' (or 
`:no-value'),
    :result-string "#s(hash-table ...)")
   (hash-table-count
    :no-eval (hash-table-count table)
-   :eg-result 15)
-  (hash-table-size
-   :no-eval (hash-table-size table)
-   :eg-result 65))
+   :eg-result 15))
 
 (define-short-documentation-group list
   "Making Lists"
diff --git a/lisp/emacs-lisp/shorthands.el b/lisp/emacs-lisp/shorthands.el
index b0665a55695..6348aaccf93 100644
--- a/lisp/emacs-lisp/shorthands.el
+++ b/lisp/emacs-lisp/shorthands.el
@@ -1,6 +1,6 @@
 ;;; shorthands.el --- Read code considering Elisp shorthands  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: João Távora <joaotavora@gmail.com>
 ;; Keywords: lisp
diff --git a/lisp/emacs-lisp/smie.el b/lisp/emacs-lisp/smie.el
index 2bc7674b8bf..c5eea4b3427 100644
--- a/lisp/emacs-lisp/smie.el
+++ b/lisp/emacs-lisp/smie.el
@@ -1,6 +1,6 @@
 ;;; smie.el --- Simple Minded Indentation Engine -*- lexical-binding: t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: languages, lisp, internal, parsing, indentation
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index fec0a0301a7..699be767ee7 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -1,6 +1,6 @@
 ;;; subr-x.el --- extra Lisp functions  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: convenience
diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el
index ba0c91d68c4..e8eb8598fd0 100644
--- a/lisp/emacs-lisp/syntax.el
+++ b/lisp/emacs-lisp/syntax.el
@@ -1,6 +1,6 @@
 ;;; syntax.el --- helper functions to find syntactic context  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
diff --git a/lisp/emacs-lisp/tabulated-list.el 
b/lisp/emacs-lisp/tabulated-list.el
index ddac6ed1746..9884a2fc24b 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -1,6 +1,6 @@
 ;;; tabulated-list.el --- generic major mode for tabulated lists -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Chong Yidong <cyd@stupidchicken.com>
 ;; Keywords: extensions, lisp
diff --git a/lisp/emacs-lisp/tcover-ses.el b/lisp/emacs-lisp/tcover-ses.el
index 75df1ed0db8..4f66f7eade2 100644
--- a/lisp/emacs-lisp/tcover-ses.el
+++ b/lisp/emacs-lisp/tcover-ses.el
@@ -1,6 +1,6 @@
 ;;; tcover-ses.el --- Example use of `testcover' to test "SES"  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Jonathan Yavner <jyavner@member.fsf.org>
 ;; Keywords: spreadsheet lisp utility
diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el
index ed31b90ca32..fb4a2a82d07 100644
--- a/lisp/emacs-lisp/testcover.el
+++ b/lisp/emacs-lisp/testcover.el
@@ -1,6 +1,6 @@
 ;;; testcover.el --- Visual code-coverage tool  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Jonathan Yavner <jyavner@member.fsf.org>
 ;; Keywords: lisp utility
diff --git a/lisp/emacs-lisp/text-property-search.el 
b/lisp/emacs-lisp/text-property-search.el
index 669cdd97319..f05219f839b 100644
--- a/lisp/emacs-lisp/text-property-search.el
+++ b/lisp/emacs-lisp/text-property-search.el
@@ -1,6 +1,6 @@
 ;;; text-property-search.el --- search for text properties  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: convenience
diff --git a/lisp/emacs-lisp/thunk.el b/lisp/emacs-lisp/thunk.el
index 45d69c6e164..1776ca0de40 100644
--- a/lisp/emacs-lisp/thunk.el
+++ b/lisp/emacs-lisp/thunk.el
@@ -1,6 +1,6 @@
 ;;; thunk.el --- Lazy form evaluation  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Petton <nicolas@petton.fr>
 ;; Keywords: sequences
diff --git a/lisp/emacs-lisp/timer-list.el b/lisp/emacs-lisp/timer-list.el
index b9a171adc07..52309a247c0 100644
--- a/lisp/emacs-lisp/timer-list.el
+++ b/lisp/emacs-lisp/timer-list.el
@@ -1,6 +1,6 @@
 ;;; timer-list.el --- list active timers in a buffer  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Package: emacs
diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el
index 468c46519fd..f6f2a8d87c0 100644
--- a/lisp/emacs-lisp/timer.el
+++ b/lisp/emacs-lisp/timer.el
@@ -1,6 +1,6 @@
 ;;; timer.el --- run a function with args at some time in future -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Package: emacs
diff --git a/lisp/emacs-lisp/tq.el b/lisp/emacs-lisp/tq.el
index 700e7c45e1e..b45efa3e331 100644
--- a/lisp/emacs-lisp/tq.el
+++ b/lisp/emacs-lisp/tq.el
@@ -1,6 +1,6 @@
 ;;; tq.el --- utility to maintain a transaction queue  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1985-1987, 1992, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985-1987, 1992, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Scott Draves <spot@cs.cmu.edu>
diff --git a/lisp/emacs-lisp/trace.el b/lisp/emacs-lisp/trace.el
index d802648d8ab..29775e77716 100644
--- a/lisp/emacs-lisp/trace.el
+++ b/lisp/emacs-lisp/trace.el
@@ -1,6 +1,6 @@
 ;;; trace.el --- tracing facility for Emacs Lisp functions  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
 ;; Author: Hans Chalupsky <hans@cs.buffalo.edu>
 ;; Maintainer: emacs-devel@gnu.org
@@ -128,6 +128,8 @@
 
 ;;; Code:
 
+(require 'cl-print)
+
 (defgroup trace nil
   "Tracing facility for Emacs Lisp functions."
   :prefix "trace-"
@@ -154,45 +156,44 @@
 (defun trace-values (&rest values)
   "Helper function to get internal values.
 You can call this function to add internal values in the trace buffer."
-  (unless inhibit-trace
-    (with-current-buffer (get-buffer-create trace-buffer)
-      (goto-char (point-max))
-      (insert
-       (trace-entry-message
-        'trace-values trace-level values "")))))
+  (trace--entry-message
+   'trace-values trace-level values (lambda () "")))
 
-(defun trace-entry-message (function level args context)
+(defun trace--entry-message (function level args context)
   "Generate a string that describes that FUNCTION has been entered.
-LEVEL is the trace level, ARGS is the list of arguments passed to FUNCTION,
-and CONTEXT is a string describing the dynamic context (e.g. values of
-some global variables)."
-  (let ((print-circle t)
-        (print-escape-newlines t))
-    (format "%s%s%d -> %S%s\n"
-            (mapconcat #'char-to-string (make-string (max 0 (1- level)) ?|) " 
")
-            (if (> level 1) " " "")
-            level
-            ;; FIXME: Make it so we can click the function name to jump to its
-            ;; definition and/or untrace it.
-            (cons function args)
-            context)))
-
-(defun trace-exit-message (function level value context)
+LEVEL is the trace level, ARGS is the list of arguments passed to FUNCTION."
+  (unless inhibit-trace
+    (trace--insert
+     (let ((ctx (funcall context))
+           (print-circle t)
+           (print-escape-newlines t))
+       (format "%s%s%d -> %s%s\n"
+               (mapconcat #'char-to-string
+                          (make-string (max 0 (1- level)) ?|) " ")
+               (if (> level 1) " " "")
+               level
+               ;; FIXME: Make it so we can click the function name to
+               ;; jump to its definition and/or untrace it.
+               (cl-prin1-to-string (cons function args))
+               ctx)))))
+
+(defun trace--exit-message (function level value context)
   "Generate a string that describes that FUNCTION has exited.
-LEVEL is the trace level, VALUE value returned by FUNCTION,
-and CONTEXT is a string describing the dynamic context (e.g. values of
-some global variables)."
-  (let ((print-circle t)
-        (print-escape-newlines t))
-    (format "%s%s%d <- %s: %S%s\n"
-            (mapconcat 'char-to-string (make-string (1- level) ?|) " ")
-            (if (> level 1) " " "")
-            level
-            function
-            ;; Do this so we'll see strings:
-            value
-            context)))
-
+LEVEL is the trace level, VALUE value returned by FUNCTION."
+  (unless inhibit-trace
+    (trace--insert
+     (let ((ctx (funcall context))
+           (print-circle t)
+           (print-escape-newlines t))
+       (format "%s%s%d <- %s: %s%s\n"
+               (mapconcat 'char-to-string (make-string (1- level) ?|) " ")
+               (if (> level 1) " " "")
+               level
+               function
+               ;; Do this so we'll see strings:
+               (cl-prin1-to-string value)
+               ctx)))))
+    
 (defvar trace--timer nil)
 
 (defun trace--display-buffer (buf)
@@ -206,43 +207,40 @@ some global variables)."
                            (setq trace--timer nil)
                            (display-buffer buf nil 0))))))
 
+(defun trace--insert (msg)
+  (if noninteractive
+      (message "%s" (if (eq ?\n (aref msg (1- (length msg))))
+                        (substring msg 0 -1) msg))
+    (with-current-buffer trace-buffer
+      (setq-local window-point-insertion-type t)
+      (goto-char (point-max))
+      (let ((deactivate-mark nil))      ;Protect deactivate-mark.
+        (insert msg)))))
 
 (defun trace-make-advice (function buffer background context)
   "Build the piece of advice to be added to trace FUNCTION.
 FUNCTION is the name of the traced function.
 BUFFER is the buffer where the trace should be printed.
 BACKGROUND if nil means to display BUFFER.
-CONTEXT if non-nil should be a function that returns extra info that should
-be printed along with the arguments in the trace."
+CONTEXT should be a function that returns extra text that should
+be printed after the arguments in the trace."
   (lambda (body &rest args)
     (let ((trace-level (1+ trace-level))
-          (trace-buffer (get-buffer-create buffer))
-          (deactivate-mark nil)         ;Protect deactivate-mark.
-          (ctx (funcall context)))
+          (trace-buffer (get-buffer-create buffer)))
+      ;; Insert a separator from previous trace output:
       (unless inhibit-trace
-        (with-current-buffer trace-buffer
-          (setq-local window-point-insertion-type t)
-          (unless background (trace--display-buffer trace-buffer))
-          (goto-char (point-max))
-          ;; Insert a separator from previous trace output:
-          (if (= trace-level 1) (insert trace-separator))
-          (insert
-           (trace-entry-message
-            function trace-level args ctx))))
+        (unless background (trace--display-buffer trace-buffer))
+        (if (= trace-level 1) (trace--insert trace-separator)))
+      (trace--entry-message
+       function trace-level args context)
       (let ((result))
         (unwind-protect
             (setq result (list (apply body args)))
-          (unless inhibit-trace
-            (let ((ctx (funcall context)))
-              (with-current-buffer trace-buffer
-                (unless background (trace--display-buffer trace-buffer))
-                (goto-char (point-max))
-                (insert
-                 (trace-exit-message
-                  function
-                  trace-level
-                  (if result (car result) '\!non-local\ exit\!)
-                  ctx))))))
+          (trace--exit-message
+           function
+           trace-level
+           (if result (car result) '\!non-local\ exit\!)
+           context))
         (car result)))))
 
 (defun trace-function-internal (function buffer background context)
diff --git a/lisp/emacs-lisp/unsafep.el b/lisp/emacs-lisp/unsafep.el
index e722cbc52dd..c64619e9b9e 100644
--- a/lisp/emacs-lisp/unsafep.el
+++ b/lisp/emacs-lisp/unsafep.el
@@ -1,6 +1,6 @@
 ;;; unsafep.el --- Determine whether a Lisp form is safe to evaluate  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Jonathan Yavner <jyavner@member.fsf.org>
 ;; Keywords: safety lisp utility
diff --git a/lisp/emacs-lisp/vtable.el b/lisp/emacs-lisp/vtable.el
index 61670ea69ca..02020552e7f 100644
--- a/lisp/emacs-lisp/vtable.el
+++ b/lisp/emacs-lisp/vtable.el
@@ -1,6 +1,6 @@
 ;;; vtable.el --- Displaying data in tables  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/emacs-lisp/warnings.el b/lisp/emacs-lisp/warnings.el
index b99b1d2ae29..6c62a56e99c 100644
--- a/lisp/emacs-lisp/warnings.el
+++ b/lisp/emacs-lisp/warnings.el
@@ -1,6 +1,6 @@
 ;;; warnings.el --- log and display warnings  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
diff --git a/lisp/emacs-lock.el b/lisp/emacs-lock.el
index a7ea4896129..633b223f730 100644
--- a/lisp/emacs-lock.el
+++ b/lisp/emacs-lock.el
@@ -1,6 +1,6 @@
 ;;; emacs-lock.el --- protect buffers against killing or exiting -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Juanma Barranquero <lekktu@gmail.com>
 ;; Inspired by emacs-lock.el by Tom Wurgler <twurgler@goodyear.com>
diff --git a/lisp/emulation/cua-base.el b/lisp/emulation/cua-base.el
index 6d21088cb29..fb6a8515d9e 100644
--- a/lisp/emulation/cua-base.el
+++ b/lisp/emulation/cua-base.el
@@ -1,6 +1,6 @@
 ;;; cua-base.el --- emulate CUA key bindings  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Kim F. Storm <storm@cua.dk>
 ;; Keywords: keyboard emulations convenience cua
diff --git a/lisp/emulation/cua-gmrk.el b/lisp/emulation/cua-gmrk.el
index ccf1c96eb01..88369ac3bea 100644
--- a/lisp/emulation/cua-gmrk.el
+++ b/lisp/emulation/cua-gmrk.el
@@ -1,6 +1,6 @@
 ;;; cua-gmrk.el --- CUA unified global mark support  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Kim F. Storm <storm@cua.dk>
 ;; Keywords: keyboard emulations convenience cua mark
diff --git a/lisp/emulation/cua-rect.el b/lisp/emulation/cua-rect.el
index 4e52abbb2c9..e50924dbd1f 100644
--- a/lisp/emulation/cua-rect.el
+++ b/lisp/emulation/cua-rect.el
@@ -1,6 +1,6 @@
 ;;; cua-rect.el --- CUA unified rectangle support  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Kim F. Storm <storm@cua.dk>
 ;; Keywords: keyboard emulations convenience CUA
diff --git a/lisp/emulation/edt-lk201.el b/lisp/emulation/edt-lk201.el
index a0696737482..09e834503bf 100644
--- a/lisp/emulation/edt-lk201.el
+++ b/lisp/emulation/edt-lk201.el
@@ -1,6 +1,6 @@
 ;;; edt-lk201.el --- enhanced EDT keypad mode emulation for LK-201 keyboards  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1986, 1992-1993, 1995, 2001-2023 Free Software
+;; Copyright (C) 1986, 1992-1993, 1995, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Kevin Gallagher <kevin.gal@verizon.net>
diff --git a/lisp/emulation/edt-mapper.el b/lisp/emulation/edt-mapper.el
index af2b02eb74e..00b7ab82cea 100644
--- a/lisp/emulation/edt-mapper.el
+++ b/lisp/emulation/edt-mapper.el
@@ -1,6 +1,6 @@
 ;;; edt-mapper.el --- create an EDT LK-201 map file for X-Windows Emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1994-1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1995, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Kevin Gallagher <kevin.gal@verizon.net>
 ;; Keywords: emulations
diff --git a/lisp/emulation/edt-pc.el b/lisp/emulation/edt-pc.el
index 5e42db7b45b..33179f84d0b 100644
--- a/lisp/emulation/edt-pc.el
+++ b/lisp/emulation/edt-pc.el
@@ -1,6 +1,6 @@
 ;;; edt-pc.el --- enhanced EDT keypad mode emulation for PC 101 keyboards  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1986, 1994-1995, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1986, 1994-1995, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Kevin Gallagher <kevin.gal@verizon.net>
diff --git a/lisp/emulation/edt-vt100.el b/lisp/emulation/edt-vt100.el
index d0dcebb2670..a34f6f2a19d 100644
--- a/lisp/emulation/edt-vt100.el
+++ b/lisp/emulation/edt-vt100.el
@@ -1,6 +1,6 @@
 ;;; edt-vt100.el --- enhanced EDT keypad mode emulation for VT series 
terminals  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1986, 1992-1993, 1995, 2002-2023 Free Software
+;; Copyright (C) 1986, 1992-1993, 1995, 2002-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Kevin Gallagher <kevin.gal@verizon.net>
diff --git a/lisp/emulation/edt.el b/lisp/emulation/edt.el
index ca353d6dfd2..d5a8fc36758 100644
--- a/lisp/emulation/edt.el
+++ b/lisp/emulation/edt.el
@@ -1,6 +1,6 @@
 ;;; edt.el --- enhanced EDT keypad mode emulation for GNU Emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1986, 1992-1995, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1986, 1992-1995, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Kevin Gallagher <kevin.gal@verizon.net>
diff --git a/lisp/emulation/keypad.el b/lisp/emulation/keypad.el
index ba133ae27a8..73c62a64cb3 100644
--- a/lisp/emulation/keypad.el
+++ b/lisp/emulation/keypad.el
@@ -1,6 +1,6 @@
 ;;; keypad.el --- simplified keypad bindings  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Kim F. Storm <storm@cua.dk>
 ;; Keywords: keyboard convenience
diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el
index 78114db0972..192eb99a570 100644
--- a/lisp/emulation/viper-cmd.el
+++ b/lisp/emulation/viper-cmd.el
@@ -1,6 +1,6 @@
 ;;; viper-cmd.el --- Vi command support for Viper  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: viper
@@ -4637,7 +4637,7 @@ sensitive for VI-style look-and-feel."
        (insert (substitute-command-keys "
 Please specify your level of familiarity with the venomous VI PERil
 \(and the VI Plan for Emacs Rescue).
-You can change it at any time by typing `\\[viper-set-expert-level]'
+You can change it at any time by typing \\[viper-set-expert-level]
 
  1 -- BEGINNER: Almost all Emacs features are suppressed.
        Feels almost like straight Vi.  File name completion and
diff --git a/lisp/emulation/viper-ex.el b/lisp/emulation/viper-ex.el
index ecbcace2dd4..11e00aef33d 100644
--- a/lisp/emulation/viper-ex.el
+++ b/lisp/emulation/viper-ex.el
@@ -1,6 +1,6 @@
 ;;; viper-ex.el --- functions implementing the Ex commands for Viper  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1994-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: viper
diff --git a/lisp/emulation/viper-init.el b/lisp/emulation/viper-init.el
index c39e3cf5142..9f724551239 100644
--- a/lisp/emulation/viper-init.el
+++ b/lisp/emulation/viper-init.el
@@ -1,6 +1,6 @@
 ;;; viper-init.el --- some common definitions for Viper  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: viper
@@ -257,11 +257,11 @@ that deletes a file.")
 
 (defvar viper-expert-level (if (boundp 'viper-expert-level) viper-expert-level 
0)
   "User's expert level.
-The minor mode viper-vi-diehard-minor-mode is in effect when
-viper-expert-level is 1 or 2 or when viper-want-emacs-keys-in-vi is t.
-The minor mode viper-insert-diehard-minor-mode is in effect when
-viper-expert-level is 1 or 2 or if viper-want-emacs-keys-in-insert is t.
-Use `\\[viper-set-expert-level]' to change this.")
+The minor mode `viper-vi-diehard-minor-mode' is in effect when
+`viper-expert-level' is 1 or 2 or when `viper-want-emacs-keys-in-vi' is t.
+The minor mode `viper-insert-diehard-minor-mode' is in effect when
+`viper-expert-level' is 1 or 2 or if `viper-want-emacs-keys-in-insert' is t.
+Use \\[viper-set-expert-level] to change this.")
 
 ;; Max expert level supported by Viper.  This is NOT a user option.
 ;; It is here to make it hard for the user from resetting it.
diff --git a/lisp/emulation/viper-keym.el b/lisp/emulation/viper-keym.el
index 9bf13bbea41..9b550932ccd 100644
--- a/lisp/emulation/viper-keym.el
+++ b/lisp/emulation/viper-keym.el
@@ -1,6 +1,6 @@
 ;;; viper-keym.el --- Viper keymaps  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1994-1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1997, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: viper
diff --git a/lisp/emulation/viper-macs.el b/lisp/emulation/viper-macs.el
index a983e8ed130..68e6ed1a1db 100644
--- a/lisp/emulation/viper-macs.el
+++ b/lisp/emulation/viper-macs.el
@@ -1,6 +1,6 @@
 ;;; viper-macs.el --- functions implementing keyboard macros for Viper  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1994-1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1997, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: viper
diff --git a/lisp/emulation/viper-mous.el b/lisp/emulation/viper-mous.el
index 65e2d0968dd..322027b56c4 100644
--- a/lisp/emulation/viper-mous.el
+++ b/lisp/emulation/viper-mous.el
@@ -1,6 +1,6 @@
 ;;; viper-mous.el --- mouse support for Viper  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1994-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: viper
diff --git a/lisp/emulation/viper-util.el b/lisp/emulation/viper-util.el
index 4a38e6640d7..d28c319de98 100644
--- a/lisp/emulation/viper-util.el
+++ b/lisp/emulation/viper-util.el
@@ -1,6 +1,6 @@
 ;;; viper-util.el --- Utilities used by viper.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: viper
diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el
index 767ad57c471..83fcdf89375 100644
--- a/lisp/emulation/viper.el
+++ b/lisp/emulation/viper.el
@@ -3,7 +3,7 @@
 ;;              and a venomous VI PERil.
 ;;              Viper Is also a Package for Emacs Rebels.
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Keywords: emulations
diff --git a/lisp/env.el b/lisp/env.el
index 281934af054..e0a8df8476c 100644
--- a/lisp/env.el
+++ b/lisp/env.el
@@ -1,6 +1,6 @@
 ;;; env.el --- functions to manipulate environment variables  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: processes, unix
diff --git a/lisp/epa-dired.el b/lisp/epa-dired.el
index 309d4358883..5fa576bb7b0 100644
--- a/lisp/epa-dired.el
+++ b/lisp/epa-dired.el
@@ -1,6 +1,6 @@
 ;;; epa-dired.el --- the EasyPG Assistant, dired extension -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Keywords: PGP, GnuPG
diff --git a/lisp/epa-file.el b/lisp/epa-file.el
index a27f241c0c3..a4942e78de7 100644
--- a/lisp/epa-file.el
+++ b/lisp/epa-file.el
@@ -1,6 +1,6 @@
 ;;; epa-file.el --- the EasyPG Assistant, transparent file encryption -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Keywords: PGP, GnuPG
diff --git a/lisp/epa-hook.el b/lisp/epa-hook.el
index 00df6732e52..458db3e0323 100644
--- a/lisp/epa-hook.el
+++ b/lisp/epa-hook.el
@@ -1,6 +1,6 @@
 ;;; epa-hook.el --- preloaded code to enable epa-file.el -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Keywords: PGP, GnuPG
diff --git a/lisp/epa-ks.el b/lisp/epa-ks.el
index 3dbce0259b3..c3c11bb0b0b 100644
--- a/lisp/epa-ks.el
+++ b/lisp/epa-ks.el
@@ -1,6 +1,6 @@
 ;;; epa-ks.el --- EasyPG Key Server Client -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Philip K. <philipk@posteo.net>
 ;; Keywords: PGP, GnuPG
diff --git a/lisp/epa-mail.el b/lisp/epa-mail.el
index 749d4471a39..0c93b18eea1 100644
--- a/lisp/epa-mail.el
+++ b/lisp/epa-mail.el
@@ -1,6 +1,6 @@
 ;;; epa-mail.el --- the EasyPG Assistant, minor-mode for mail composer -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Keywords: PGP, GnuPG, mail, message
diff --git a/lisp/epa.el b/lisp/epa.el
index 8126584e4fb..53da3bf6cce 100644
--- a/lisp/epa.el
+++ b/lisp/epa.el
@@ -1,6 +1,6 @@
 ;;; epa.el --- the EasyPG Assistant -*- lexical-binding: t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Keywords: PGP, GnuPG
@@ -384,7 +384,7 @@ DOC is documentation text to insert at the start."
   (epa--list-keys name nil
                   "The letters at the start of a line have these meanings.
 e  expired key.  n  never trust.  m  trust marginally.  u  trust ultimately.
-f  trust fully (keys you have signed, usually).
+f  trust fully (keys you have signed, usually).  r  revoked key.
 q  trust status questionable.  -  trust status unspecified.
  See GPG documentation for more explanation.
 \n"))
diff --git a/lisp/epg-config.el b/lisp/epg-config.el
index 6797e159ba7..01ee2cff5b5 100644
--- a/lisp/epg-config.el
+++ b/lisp/epg-config.el
@@ -1,6 +1,6 @@
 ;;; epg-config.el --- configuration of the EasyPG Library  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Keywords: PGP, GnuPG
diff --git a/lisp/epg.el b/lisp/epg.el
index b994c1b9ca2..7bec91f616d 100644
--- a/lisp/epg.el
+++ b/lisp/epg.el
@@ -1,6 +1,6 @@
 ;;; epg.el --- the EasyPG Library -*- lexical-binding: t -*-
 
-;; Copyright (C) 1999-2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Keywords: PGP, GnuPG
diff --git a/lisp/erc/ChangeLog.1 b/lisp/erc/ChangeLog.1
index 8a569ebfdb3..f1605f70f3e 100644
--- a/lisp/erc/ChangeLog.1
+++ b/lisp/erc/ChangeLog.1
@@ -11703,7 +11703,7 @@
 
        * erc-speak.el, erc.el: New file.
 
-  Copyright (C) 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/erc/ChangeLog.2 b/lisp/erc/ChangeLog.2
index ebef621064b..b10b0b68f00 100644
--- a/lisp/erc/ChangeLog.2
+++ b/lisp/erc/ChangeLog.2
@@ -757,7 +757,7 @@
 
 See ChangeLog.1 for earlier changes.
 
-  Copyright (C) 2009-2023 Free Software Foundation, Inc.
+  Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-autoaway.el b/lisp/erc/erc-autoaway.el
index b586d4523b4..13da725f1ac 100644
--- a/lisp/erc/erc-autoaway.el
+++ b/lisp/erc/erc-autoaway.el
@@ -1,6 +1,6 @@
 ;;; erc-autoaway.el --- Provides autoaway for ERC  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Jorgen Schaefer <forcer@forcix.cx>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index 56e34f06966..9f00464f93d 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -1,6 +1,6 @@
 ;;; erc-backend.el --- Backend network communication for ERC  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Filename: erc-backend.el
 ;; Author: Lawrence Mitchell <wence@gmx.li>
@@ -101,39 +101,25 @@
 (eval-when-compile (require 'cl-lib))
 (require 'erc-common)
 
-(defvar erc--called-as-input-p)
 (defvar erc--display-context)
 (defvar erc--target)
-(defvar erc--cmem-from-nick-function)
 (defvar erc-channel-list)
-(defvar erc-channel-users)
+(defvar erc-channel-members)
 (defvar erc-default-nicks)
 (defvar erc-default-recipients)
 (defvar erc-ensure-target-buffer-on-privmsg)
-(defvar erc-format-nick-function)
-(defvar erc-format-query-as-channel-p)
 (defvar erc-hide-prompt)
 (defvar erc-input-marker)
 (defvar erc-insert-marker)
-(defvar erc-invitation)
 (defvar erc-join-buffer)
-(defvar erc-kill-buffer-on-part)
-(defvar erc-kill-server-buffer-on-quit)
-(defvar erc-log-p)
-(defvar erc-minibuffer-ignored)
 (defvar erc-networks--id)
 (defvar erc-nick)
 (defvar erc-nick-change-attempt-count)
-(defvar erc-prompt-for-channel-key)
-(defvar erc-prompt-hidden)
-(defvar erc-receive-query-display)
-(defvar erc-receive-query-display-defer)
-(defvar erc-reuse-buffers)
 (defvar erc-verbose-server-ping)
-(defvar erc-whowas-on-nosuchnick)
 
 (declare-function erc--init-channel-modes "erc" (channel raw-args))
 (declare-function erc--open-target "erc" (target))
+(declare-function erc--parse-nuh "erc" (string))
 (declare-function erc--target-from-string "erc" (string))
 (declare-function erc--update-modes "erc" (raw-args))
 (declare-function erc-active-buffer "erc" nil)
@@ -156,7 +142,6 @@
 (declare-function erc-display-server-message "erc" (_proc parsed))
 (declare-function erc-emacs-time-to-erc-time "erc" (&optional specified-time))
 (declare-function erc-format-message "erc" (msg &rest args))
-(declare-function erc-format-privmessage "erc" (nick msg privp msgp))
 (declare-function erc-get-buffer "erc" (target &optional proc))
 (declare-function erc-handle-login "erc" nil)
 (declare-function erc-handle-user-status-change "erc" (type nlh &optional l))
@@ -187,6 +172,9 @@
 (declare-function erc-update-mode-line-buffer "erc" (buffer))
 (declare-function erc-wash-quit-reason "erc" (reason nick login host))
 
+(declare-function erc--determine-speaker-message-format-args "erc"
+                  (nick target message queryp privmsgp statusmsgp inputp
+                        &optional prefix disp-nick))
 (declare-function erc-display-message "erc"
                   (parsed type buffer msg &rest args))
 (declare-function erc-get-buffer-create "erc"
@@ -445,7 +433,11 @@ and optionally alter the attempts tally."
 
 (defcustom erc-split-line-length 440
   "The maximum length of a single message.
-If a message exceeds this size, it is broken into multiple ones.
+ERC normally splits chat input submitted at its prompt into
+multiple messages when the initial size exceeds this value in
+bytes.  Modules can tell ERC to forgo splitting entirely by
+setting this to zero locally or, preferably, by binding it around
+a remapped `erc-send-current-line' command.
 
 IRC allows for lines up to 512 bytes.  Two of them are CR LF.
 And a typical message looks like this:
@@ -608,7 +600,8 @@ escape hatch for inhibiting their transmission.")
                 (if (= (car cmp) (point-min))
                     (goto-char (nth 1 cmp))
                   (goto-char (car cmp)))))
-            (cl-assert (/= (point-min) (point)))
+            (when (= (point-min) (point))
+              (goto-char (point-max)))
             (push (buffer-substring-no-properties (point-min) (point)) out)
             (delete-region (point-min) (point)))
           (or (nreverse out) (list "")))
@@ -816,6 +809,7 @@ Make sure you are in an ERC buffer when running this."
                   nil nil nil erc-session-client-certificate
                   erc-session-username
                   (erc-networks--id-given erc-networks--id))
+        (defvar erc-reuse-buffers)
         (unless (with-suppressed-warnings ((obsolete erc-reuse-buffers))
                   erc-reuse-buffers)
           (cl-assert (not (eq buffer (current-buffer)))))))))
@@ -1038,6 +1032,7 @@ Conditionally try to reconnect and take appropriate 
action."
           (erc-update-mode-line)
           ;; Kill server buffer if user wants it
           (set-buffer-modified-p nil)
+          (defvar erc-kill-server-buffer-on-quit)
           (when erc-kill-server-buffer-on-quit
             (kill-buffer (current-buffer))))
       ;; unexpected disconnect
@@ -1055,6 +1050,7 @@ Conditionally try to reconnect and take appropriate 
action."
   (when-let (((null erc--hidden-prompt-overlay))
              (ov (make-overlay erc-insert-marker (1- erc-input-marker)
                                nil 'front-advance)))
+    (defvar erc-prompt-hidden)
     (overlay-put ov 'display erc-prompt-hidden)
     (setq erc--hidden-prompt-overlay ov)))
 
@@ -1117,11 +1113,10 @@ Change value of property `erc-prompt' from t to 
`hidden'."
                    (setq erc-server-ping-handler nil)))
           (run-hook-with-args 'erc-disconnected-hook
                               (erc-current-nick) (system-name) "")
-          (dolist (buf (erc-buffer-filter (lambda () (boundp 
'erc-channel-users)) cproc))
-            (with-current-buffer buf
-              (when (erc--target-channel-p erc--target)
-                (setf (erc--target-channel-joined-p erc--target) nil))
-              (setq erc-channel-users (make-hash-table :test 'equal))))
+          (erc-with-all-buffers-of-server cproc (lambda () erc-channel-members)
+            (when (erc--target-channel-p erc--target)
+              (setf (erc--target-channel-joined-p erc--target) nil))
+            (clrhash erc-channel-members))
           ;; Hide the prompt
           (erc--hide-prompt cproc)
           ;; Decide what to do with the buffer
@@ -1721,6 +1716,7 @@ add things to `%s' instead."
         (chnl (erc-response.contents parsed)))
     (pcase-let ((`(,nick ,login ,host)
                  (erc-parse-user (erc-response.sender parsed))))
+      (defvar erc-invitation)
       (setq erc-invitation chnl)
       (when (string= target (erc-current-nick))
         (erc-display-message
@@ -1893,6 +1889,7 @@ add things to `%s' instead."
         (with-suppressed-warnings ((obsolete erc-delete-default-channel))
           (erc-delete-default-channel chnl buffer))
         (erc-update-mode-line buffer)
+        (defvar erc-kill-buffer-on-part)
         (when erc-kill-buffer-on-part
           (kill-buffer buffer))))))
 
@@ -1920,16 +1917,80 @@ add things to `%s' instead."
          ?s (if (/= erc-server-lag 1) "s" "")))
       (erc-update-mode-line))))
 
+(defun erc--statusmsg-target (target)
+  "Return actual target from given TARGET if it has a leading prefix char."
+  (and-let* ((erc-ensure-target-buffer-on-privmsg)
+             ((not (eq erc-ensure-target-buffer-on-privmsg 'status)))
+             ((not (erc-channel-p target)))
+             (chars (erc--get-isupport-entry 'STATUSMSG 'single))
+             ((string-search (string (aref target 0)) chars))
+             (trimmed (substring target 1))
+             ((erc-channel-p trimmed)))
+    trimmed))
+
+;; Moved to this file from erc.el in ERC 5.6.
+(defvar-local erc-current-message-catalog 'english
+  "Current language or context catalog for formatting inserted messages.
+See `erc-format-message'.")
+
+;; This variable can be made public if the current design proves
+;; sufficient.
+(defvar erc--message-speaker-catalog '-speaker
+  "The \"speaker\" catalog symbol used to format PRIVMSGs and NOTICEs.
+
+This symbol defines a \"catalog\" of variables and functions
+whose names reflect their membership via a corresponding CATALOG
+component, as in \"erc-message-CATALOG-KEY\".  Here, KEY refers
+to a common set of interface members (variables or functions),
+that an implementer must define:
+
+- `statusmsg' and `statusmsg-input': PRIVMSGs whose target is a
+   status-prefixed channel; the latter is the \"echoed\" version
+
+- `chan-privmsg', `query-privmsg', `chan-notice', `query-notice':
+   standard chat messages traditionally prefixed by a <nickname>
+   indicating the message's \"speaker\"
+
+- `input-chan-privmsg', `input-query-privmsg', `input-query-notice',
+  `input-chan-notice': \"echoed\" versions of the above
+
+- `ctcp-action', `ctcp-action-input', `ctcp-action-statusmsg',
+  `ctcp-action-statusmsg-input': \"CTCP ACTION\" versions of the
+   above
+
+The other part of this interface is the per-key collection of
+`format-spec' parameters members must support.  For simplicity,
+this catalog currently defines a common set for all keys, some of
+which may be assigned the empty string when not applicable:
+
+  %n - nickname
+  %m - message body
+  %p - nickname's status prefix (when applicable)
+  %s - current target's STATUSMSG prefix (when applicable)
+
+As an added means of communicating with various modules, if this
+catalog's symbol has the property `erc--msg-prop-overrides',
+consumers calling `erc-display-message' will see the value added
+to the `erc--msg-props' \"environment\" in modification hooks,
+like `erc-insert-modify-hook'.")
+
+(defvar erc--speaker-status-prefix-wanted-p (gensym "erc-")
+  "Sentinel to detect whether `erc-format-@nick' has just run.")
+
 (define-erc-response-handler (PRIVMSG NOTICE)
   "Handle private messages, including messages in channels." nil
   (let ((sender-spec (erc-response.sender parsed))
         (cmd (erc-response.command parsed))
         (tgt (car (erc-response.command-args parsed)))
         (msg (erc-response.contents parsed)))
-    (if (or (erc-ignored-user-p sender-spec)
-            (erc-ignored-reply-p msg tgt proc))
+    (defvar erc-minibuffer-ignored)
+    (defvar erc-ignore-list)
+    (defvar erc-ignore-reply-list)
+    (if (or (and erc-ignore-list (erc-ignored-user-p sender-spec))
+            (and erc-ignore-reply-list (erc-ignored-reply-p msg tgt proc)))
         (when erc-minibuffer-ignored
           (message "Ignored %s from %s to %s" cmd sender-spec tgt))
+      (defvar erc--msg-prop-overrides)
       (let* ((sndr (erc-parse-user sender-spec))
              (nick (nth 0 sndr))
              (login (nth 1 sndr))
@@ -1937,16 +1998,22 @@ add things to `%s' instead."
              (msgp (string= cmd "PRIVMSG"))
              (noticep (string= cmd "NOTICE"))
              ;; S.B. downcase *both* tgt and current nick
-             (privp (erc-current-nick-p tgt))
+             (medown (erc-downcase (erc-current-nick)))
+             (inputp (string= medown (erc-downcase nick)))
+             (privp (string= (erc-downcase tgt) medown))
              (erc--display-context `((erc-buffer-display . ,(intern cmd))
                                      ,@erc--display-context))
-             s buffer
-             fnick)
-        (setf (erc-response.contents parsed) msg)
+             (erc--msg-prop-overrides `((erc--tmp) ,@erc--msg-prop-overrides))
+             (erc--speaker-status-prefix-wanted-p nil)
+             (erc-current-message-catalog erc--message-speaker-catalog)
+             ;;
+             buffer statusmsg cmem-prefix fnick)
         (setq buffer (erc-get-buffer (if privp nick tgt) proc))
         ;; Even worth checking for empty target here? (invalid anyway)
         (unless (or buffer noticep (string-empty-p tgt) (eq ?$ (aref tgt 0))
                     (erc-is-message-ctcp-and-not-action-p msg))
+          (defvar erc-receive-query-display)
+          (defvar erc-receive-query-display-defer)
           (if privp
               (when-let ((erc-join-buffer
                           (or (and (not erc-receive-query-display-defer)
@@ -1957,9 +2024,14 @@ add things to `%s' instead."
                 (push `(erc-receive-query-display . ,(intern cmd))
                       erc--display-context)
                 (setq buffer (erc--open-target nick)))
-            ;; A channel buffer has been killed but is still joined.
-            (when erc-ensure-target-buffer-on-privmsg
-              (setq buffer (erc--open-target tgt)))))
+            (cond
+             ;; Target is a channel and contains leading @+ chars.
+             ((and-let* ((trimmed(erc--statusmsg-target tgt)))
+                (setq buffer (erc-get-buffer trimmed proc)
+                      statusmsg (and buffer (substring tgt 0 1)))))
+             ;; A channel buffer has been killed but is still joined.
+             (erc-ensure-target-buffer-on-privmsg
+              (setq buffer (erc--open-target tgt))))))
         (when buffer
           (with-current-buffer buffer
             (when privp (erc--unhide-prompt))
@@ -1968,35 +2040,43 @@ add things to `%s' instead."
             ;; at this point.
             (erc-update-channel-member (if privp nick tgt) nick nick
                                        privp nil nil nil nil nil host login 
nil nil t)
+            (defvar erc--cmem-from-nick-function)
+            (defvar erc-format-nick-function)
+            (defvar erc-show-speaker-membership-status)
+            (defvar erc-speaker-from-channel-member-function)
             (let ((cdata (funcall erc--cmem-from-nick-function
                                   (erc-downcase nick) sndr parsed)))
-              (setq fnick (funcall erc-format-nick-function
-                                   (car cdata) (cdr cdata))))))
-        (cond
-         ((erc-is-message-ctcp-p msg)
-          (setq s (if msgp
-                      (erc-process-ctcp-query proc parsed nick login host)
-                    (erc-process-ctcp-reply proc parsed nick login host
-                                            (match-string 1 msg)))))
-         (t
+              (setq fnick (funcall erc-speaker-from-channel-member-function
+                                   (car cdata) (cdr cdata))
+                    cmem-prefix (and (or erc--speaker-status-prefix-wanted-p
+                                         erc-show-speaker-membership-status
+                                         inputp)
+                                     (cdr cdata))))))
+        (if (erc-is-message-ctcp-p msg)
+            (if noticep
+                (erc-process-ctcp-reply proc parsed nick login host
+                                        (match-string 1 msg))
+              (setq parsed (erc--ctcp-response-from-parsed
+                            :parsed parsed :buffer buffer :statusmsg statusmsg
+                            :prefix cmem-prefix :dispname fnick))
+              (erc-process-ctcp-query proc parsed nick login host))
           (setq erc-server-last-peers (cons nick (cdr erc-server-last-peers)))
-          (setq s (erc-format-privmessage
-                   (or fnick nick) msg
-                   ;; If buffer is a query buffer,
-                   ;; format the nick as for a channel.
-                   (and (not (and buffer
-                                  (erc-query-buffer-p buffer)
-                                  erc-format-query-as-channel-p))
-                        privp)
-                   msgp))))
-        (when s
-          (if (and noticep privp)
-              (progn
-                (run-hook-with-args 'erc-echo-notice-always-hook
-                                    s parsed buffer nick)
-                (run-hook-with-args-until-success
-                 'erc-echo-notice-hook s parsed buffer nick))
-            (erc-display-message parsed nil buffer s)))))))
+          (with-current-buffer (or buffer (current-buffer))
+            ;; Re-bind in case either buffer has a local value.
+            (let ((erc-current-message-catalog erc--message-speaker-catalog)
+                  (msg-args (erc--determine-speaker-message-format-args
+                             nick msg privp msgp inputp statusmsg
+                             cmem-prefix fnick)))
+              (if (or msgp (not privp))
+                  ;; This is a PRIVMSG or a NOTICE to a channel.
+                  (apply #'erc-display-message parsed nil buffer msg-args)
+                ;; This is a NOTICE directed at the client's current nick.
+                (push (cons 'erc--msg (car msg-args)) erc--msg-prop-overrides)
+                (let ((fmtmsg (apply #'erc-format-message msg-args)))
+                  (run-hook-with-args 'erc-echo-notice-always-hook
+                                      fmtmsg parsed buffer nick)
+                  (run-hook-with-args-until-success
+                   'erc-echo-notice-hook fmtmsg parsed buffer nick))))))))))
 
 (define-erc-response-handler (QUIT)
   "Another user has quit IRC." nil
@@ -2126,7 +2206,9 @@ primitive value."
 ;; While it's better to depend on interfaces than specific types,
 ;; using `cl-struct-slot-value' or similar to extract a known slot at
 ;; runtime would incur a small "ducktyping" tax, which should probably
-;; be avoided when running dozens of times per incoming message.
+;; be avoided when running hundreds of times per incoming message.
+;; Instead of separate keys per data type, we could increment a
+;; counter whenever a new 005 arrives.
 (defmacro erc--with-isupport-data (param var &rest body)
   "Return structured data stored in VAR for \"ISUPPORT\" PARAM.
 Expect VAR's value to be an instance of `erc--isupport-data'.  If
@@ -2416,6 +2498,7 @@ See `erc-display-server-message'." nil
     (erc-display-message parsed 'notice (erc-get-buffer channel proc)
                          's341 ?n nick ?c channel)))
 
+;; FIXME update or add server user instead when channel is "*".
 (define-erc-response-handler (352)
   "WHO notice." nil
   (pcase-let ((`(,channel ,user ,host ,_server ,nick ,away-flag)
@@ -2481,9 +2564,28 @@ See `erc-display-server-message'." nil
    's391 ?s (cadr (erc-response.command-args parsed))
    ?t (nth 2 (erc-response.command-args parsed))))
 
+;; https://defs.ircdocs.horse/defs/numerics.html#rpl-visiblehost-396
+;; As of ERC 5.6, if the client hasn't yet joined any channels,
+;; there's a good chance a server user for the current nick simply
+;; doesn't exist (and there's not enough info in this reply to create
+;; one).  To fix this, ERC could WHO itself on 372 or similar if it
+;; hasn't yet received a 900.
+(define-erc-response-handler (396)
+  "RPL_VISIBLEHOST or RPL_YOURDISPLAYHOST or RPL_HOSTHIDDEN." nil
+  (pcase-let* ((userhost (cadr (erc-response.command-args parsed)))
+               ;; Behavior blindly copied from event_hosthidden in irssi 1.4.
+               (rejectrx (rx (| (: bot (in ?@ ?: ?-)) (in ?* ?? ?! ?# ?& ?\s)
+                                (: ?- eot))))
+               (`(,_ ,user ,host) (and (not (string-match rejectrx userhost))
+                                       (erc--parse-nuh userhost))))
+    (when host
+      (erc-update-user-nick (erc-current-nick) nil host user)
+      (erc-display-message parsed 'notice 'active 's396 ?s userhost))))
+
 (define-erc-response-handler (401)
   "No such nick/channel." nil
   (let ((nick/channel (cadr (erc-response.command-args parsed))))
+    (defvar erc-whowas-on-nosuchnick)
     (when erc-whowas-on-nosuchnick
       (erc-log (format "cmd: WHOWAS: %s" nick/channel))
       (erc-server-send (format "WHOWAS %s 1" nick/channel)))
@@ -2584,6 +2686,8 @@ See `erc-display-server-message'." nil
   "Channel key needed." nil
   (erc-display-message parsed '(notice error) nil 's475
                        ?c (cadr (erc-response.command-args parsed)))
+  (defvar erc-prompt-for-channel-key)
+  (defvar erc--called-as-input-p)
   (when erc-prompt-for-channel-key
     (let ((channel (cadr (erc-response.command-args parsed)))
           (erc--called-as-input-p t)
diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el
index e1c10be53f6..6b78e451b54 100644
--- a/lisp/erc/erc-button.el
+++ b/lisp/erc/erc-button.el
@@ -1,6 +1,6 @@
 ;;; erc-button.el --- A way of buttonizing certain things in ERC buffers  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1996-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -70,6 +70,11 @@
   "ERC button face."
   :group 'erc-faces)
 
+(defface erc-button-nick-default-face '((t :inherit erc-nick-default-face))
+  "Default face for a buttonized nickname."
+  :package-version '(ERC . "5.6")
+  :group 'erc-faces)
+
 (defcustom erc-button-face 'erc-button
   "Face used for highlighting buttons in ERC buffers.
 
@@ -78,8 +83,9 @@ A button is a piece of text that you can activate by pressing
   :type 'face
   :group 'erc-faces)
 
-(defcustom erc-button-nickname-face 'erc-nick-default-face
+(defcustom erc-button-nickname-face 'erc-button-nick-default-face
   "Face used for ERC nickname buttons."
+  :package-version '(ERC . "5.6")
   :type 'face
   :group 'erc-faces)
 
@@ -216,6 +222,9 @@ PAR is a number of a regexp grouping whose text will be 
passed to
   "URL of the EmacsWiki ELisp area."
   :type 'string)
 
+(defvar erc-button-highlight-nick-once '(QUIT PART JOIN)
+  "Messages for which to buttonize only the first nick occurrence.")
+
 (defvar erc-button-keymap
   (let ((map (make-sparse-keymap)))
     (define-key map (kbd "RET") #'erc-button-press-button)
@@ -357,13 +366,14 @@ specified by `erc-button-alist'."
   ( user nil :type (or null erc-server-user)
     ;; Not necessarily present in `erc-server-users'.
     :documentation "A possibly nil or spoofed `erc-server-user'.")
-  ( cuser nil :type (or null erc-channel-user)
-    ;; The CDR of a value from an `erc-channel-users' table.
+  ( cusr nil :type (or null erc-channel-user)
+    ;; The CDR of a value from an `erc-channel-members' table.
     :documentation "A possibly nil `erc-channel-user'.")
   ( nickname-face erc-button-nickname-face :type symbol
     :documentation "Temp `erc-button-nickname-face' while buttonizing.")
   ( mouse-face erc-button-mouse-face :type symbol
-    :documentation "Temp `erc-button-mouse-face' while buttonizing."))
+    :documentation "Function to return possibly cached face.")
+  ( face-cache nil :type (or null function)))
 
 ;; This variable is intended to serve as a "core" to be wrapped by
 ;; (built-in) modules during setup.  It's unclear whether
@@ -382,11 +392,22 @@ be updated at will.")
 
 (defvar-local erc-button--phantom-cmems nil)
 
-(defvar erc-button--fallback-cmem-function #'ignore
+(defvar erc-button--fallback-cmem-function
+  #'erc-button--get-user-from-spkr-prop
   "Function to determine channel member if not found in the usual places.
-Called with DOWNCASED-NICK, NICK, and NICK-BOUNDS when
+Called with DOWNCASED-NICK, NICK, NICK-BOUNDS, and COUNT when
 `erc-button-add-nickname-buttons' cannot find a user object for
-DOWNCASED-NICK in `erc-channel-users' or `erc-server-users'.")
+DOWNCASED-NICK in `erc-channel-members' or `erc-server-users'.
+NICK-BOUNDS is a cons of buffer positions, and COUNT is a number
+incremented with each visit, starting at 1.")
+
+(defun erc-button--get-user-from-spkr-prop (_ _ _ count)
+  "Attempt to obtain an `erc-channel-user' from current \"msg props\".
+But only do so when COUNT is 1, meaning this is the first button
+candidate in the just-inserted message."
+  (and-let* (((= 1 count))
+             (nick (erc--check-msg-prop 'erc--spkr)))
+    (gethash nick erc-channel-members)))
 
 ;; Historical or fictitious users.  As long as these two structs
 ;; remain superficial "subclasses" with the same slots and defaults,
@@ -408,7 +429,7 @@ DOWNCASED-NICK in `erc-channel-users' or 
`erc-server-users'.")
     (puthash downcased (cons user cuser) erc-button--phantom-cmems)
     (cons user cuser)))
 
-(defun erc-button--get-phantom-cmem (down _word _bounds)
+(defun erc-button--get-phantom-cmem (down _word _bounds _count)
   (gethash down erc-button--phantom-cmems))
 
 (define-minor-mode erc-button--phantom-users-mode
@@ -422,7 +443,7 @@ of the channel.  However, don't bother creating an actual
 Instead, just spoof an `erc-server-user' and stash it during
 \"PRIVMSG\" handling via `erc--cmem-from-nick-function' and
 retrieve it during buttonizing via
-`erc-button--fallback-user-function'."
+`erc-button--fallback-cmem-function'."
   :interactive nil
   (if erc-button--phantom-users-mode
       (progn
@@ -446,37 +467,37 @@ retrieve it during buttonizing via
                           (and erc-button-buttonize-nicks
                                erc-button--modify-nick-function)))
                      (erc-button--extract-form form)))
+             (oncep (if-let ((erc-button-highlight-nick-once)
+                             (c (erc--check-msg-prop 'erc--cmd))
+                             ((memq c erc-button-highlight-nick-once)))
+                        1 0))
              (seen 0))
     (goto-char (point-min))
     (while-let
-        (((erc-forward-word))
+        (((or (zerop seen) (zerop oncep)))
+         ((erc-forward-word))
          (bounds (or (and (= 1 (cl-incf seen)) (erc--get-speaker-bounds))
                      (erc-bounds-of-word-at-point)))
          (word (buffer-substring-no-properties (car bounds) (cdr bounds)))
          (down (erc-downcase word)))
-      (let* ((erc-button-mouse-face erc-button-mouse-face)
-             (erc-button-nickname-face erc-button-nickname-face)
-             (cuser (and erc-channel-users
-                         (or (gethash down erc-channel-users)
-                             (funcall erc-button--fallback-cmem-function
-                                      down word bounds))))
-             (user (or (and cuser (car cuser))
+      (let* ((nick-obj t)
+             (cmem (and erc-channel-members
+                        (or (gethash down erc-channel-members)
+                            (funcall erc-button--fallback-cmem-function
+                                     down word bounds seen))))
+             (user (or (and cmem (car cmem))
                        (and erc-server-users (gethash down erc-server-users))))
              (data (list word)))
         (when (or (not (functionp form))
-                  (and-let* ((user)
-                             (obj (funcall form (make-erc-button--nick
-                                                 :bounds bounds :data data
-                                                 :downcased down :user user
-                                                 :cuser (cdr cuser)))))
-                    (setq erc-button-mouse-face ; might be null
-                          (erc-button--nick-mouse-face obj)
-                          erc-button-nickname-face ; might be null
-                          (erc-button--nick-nickname-face obj)
-                          data (erc-button--nick-data obj)
-                          bounds (erc-button--nick-bounds obj))))
+                  (and user
+                       (setq nick-obj (funcall form (make-erc-button--nick
+                                                     :bounds bounds :data data
+                                                     :downcased down :user user
+                                                     :cusr (cdr cmem)))
+                             data (erc-button--nick-data nick-obj)
+                             bounds (erc-button--nick-bounds nick-obj))))
           (erc-button-add-button (car bounds) (cdr bounds) (nth 3 entry)
-                                 'nickp data))))))
+                                 nick-obj data))))))
 
 (defun erc-button-add-buttons-1 (regexp entry)
   "Search through the buffer for matches to ENTRY and add buttons."
@@ -535,13 +556,20 @@ REGEXP is the regular expression which matched for this 
button."
           (move-marker pos (point))))))
   (if nick-p
       (when erc-button-nickname-face
-        (erc-button-add-face from to erc-button-nickname-face))
+        (erc--merge-prop from to 'font-lock-face
+                         (if (erc-button--nick-p nick-p)
+                             (erc-button--nick-nickname-face nick-p)
+                           erc-button-nickname-face)
+                         nil (and (erc-button--nick-p nick-p)
+                                  (erc-button--nick-face-cache nick-p))))
     (when erc-button-face
-      (erc-button-add-face from to erc-button-face)))
+      (erc--merge-prop from to 'font-lock-face erc-button-face)))
   (add-text-properties
    from to
-   (nconc (and erc-button-mouse-face
-               (list 'mouse-face erc-button-mouse-face))
+   (nconc (and-let* ((face (or (and (erc-button--nick-p nick-p)
+                                    (erc-button--nick-mouse-face nick-p))
+                               erc-button-mouse-face)))
+            (list 'mouse-face face))
           (list 'erc-callback fun)
           (list 'keymap erc-button-keymap)
           (list 'rear-nonsticky t)
@@ -733,11 +761,11 @@ In server buffers, also prompt for a channel."
                                       (erc-get-channel-user nick)))
                           t nil t (caar targets))))
    nick
-   (read-from-minibuffer "Reason: ")))
+   (read-string "Reason: ")))
 
 (defun erc-button-cmd-MSG (nick)
   "Prompt for a message to NICK, and send it via `erc-cmd-MSG'."
-  (let ((msg (read-from-minibuffer (concat "Message to " nick ": "))))
+  (let ((msg (read-string (concat "Message to " nick ": "))))
     (erc-cmd-MSG (concat nick " " msg))))
 
 (defvar-local erc-button--nick-popup-alist nil
@@ -801,6 +829,7 @@ argument when calling `erc-display-message'.  Otherwise, 
add it
 to STRINGS.  If STRINGS contains any trailing non-nil
 non-strings, concatenate leading string members before applying
 `format'.  Otherwise, just concatenate everything."
+  (defvar erc-stamp--skip)
   (let* ((buffer (if (bufferp maybe-buffer)
                      maybe-buffer
                    (when (stringp maybe-buffer)
@@ -816,8 +845,10 @@ non-strings, concatenate leading string members before 
applying
                  (push head strings))
                #'format))
          (string (apply op strings))
-         (erc-insert-modify-hook (remove 'erc-add-timestamp
-                                         erc-insert-modify-hook))
+         ;; Avoid timestamps unless left-sided.
+         (erc-stamp--skip (or (bound-and-true-p erc-stamp--display-margin-mode)
+                              (not (fboundp 'erc-timestamp-offset))
+                              (zerop (erc-timestamp-offset))))
          (erc-insert-post-hook
           (cons (lambda ()
                   (setq string (buffer-substring (point-min)
@@ -841,8 +872,8 @@ non-strings, concatenate leading string members before 
applying
       (with-syntax-table lisp-mode-syntax-table
         (skip-syntax-forward "^-"))
       (forward-char)
-      (display-warning
-       'erc (buffer-substring-no-properties (point) (point-max))))))
+      (erc--lwarn
+       'erc :warning (buffer-substring-no-properties (point) (point-max))))))
 
 (provide 'erc-button)
 
diff --git a/lisp/erc/erc-capab.el b/lisp/erc/erc-capab.el
index bb0921da7f0..ca86e88fccb 100644
--- a/lisp/erc/erc-capab.el
+++ b/lisp/erc/erc-capab.el
@@ -1,6 +1,6 @@
 ;;; erc-capab.el --- support for dancer-ircd and hyperion's CAPAB  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
 
diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el
index 8daedf9b019..abcdc4c8843 100644
--- a/lisp/erc/erc-common.el
+++ b/lisp/erc/erc-common.el
@@ -1,6 +1,6 @@
 ;;; erc-common.el --- Macros and types for ERC  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 ;;
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
 ;; Keywords: comm, IRC, chat, client, internet
@@ -29,9 +29,7 @@
 (defvar erc--casemapping-rfc1459)
 (defvar erc--casemapping-rfc1459-strict)
 (defvar erc-channel-users)
-(defvar erc-dbuf)
 (defvar erc-insert-this)
-(defvar erc-log-p)
 (defvar erc-modules)
 (defvar erc-send-this)
 (defvar erc-server-process)
@@ -39,6 +37,7 @@
 (defvar erc-session-server)
 
 (declare-function erc--get-isupport-entry "erc-backend" (key &optional single))
+(declare-function erc--init-cusr-fallback-status "erc" (v h o a q))
 (declare-function erc-get-buffer "erc" (target &optional proc))
 (declare-function erc-server-buffer "erc" nil)
 (declare-function widget-apply-action "wid-edit" (widget &optional event))
@@ -51,10 +50,26 @@
 (declare-function widget-type "wid-edit" (widget))
 
 (cl-defstruct erc-input
-  string insertp sendp refoldp)
+  "Object shared among members of `erc-pre-send-functions'.
+Any use outside of the hook is not supported."
+  ( string "" :type string
+    :documentation "String to send and, without `substxt', insert.
+ERC treats separate lines as separate messages.")
+  ( insertp nil :type boolean
+    :documentation "Whether to insert outgoing message.
+When nil, ERC still sends `string'.")
+  ( sendp nil :type boolean
+    :documentation "Whether to send and (for compat reasons) insert.
+To insert without sending, define a (slash) command.")
+  ( substxt nil :type (or function string null)
+    :documentation "Alternate string to insert without splitting.
+The function form is for internal use.")
+  ( refoldp nil :type boolean
+    :documentation "Whether to resplit a possibly overlong `string'.
+ERC only refolds `string', never `substxt'."))
 
 (cl-defstruct (erc--input-split (:include erc-input
-                                          (string :read-only)
+                                          (string "" :read-only t)
                                           (insertp erc-insert-this)
                                           (sendp (with-suppressed-warnings
                                                      ((obsolete erc-send-this))
@@ -69,8 +84,23 @@
   ;; Buffers
   (buffers nil))
 
-(cl-defstruct (erc-channel-user (:type vector) :named)
-  voice halfop op admin owner
+(cl-defstruct (erc-channel-user (:type vector)
+                                (:constructor
+                                 erc-channel-user--make
+                                 (&key (status 0) (last-message-time nil)))
+                                (:constructor
+                                 make-erc-channel-user
+                                 ( &key voice halfop op admin owner
+                                   last-message-time
+                                   &aux (status
+                                         (if (or voice halfop op admin owner)
+                                             (erc--init-cusr-fallback-status
+                                              voice halfop op admin owner)
+                                           0))))
+                                :named)
+  "Object containing channel-specific data for a single user."
+  ;; voice halfop op admin owner
+  (status 0 :type integer)
   ;; Last message time (in the form of the return value of
   ;; (current-time)
   ;;
@@ -101,6 +131,23 @@
   (contents "" :type string)
   (tags '() :type list))
 
+(cl-defstruct (erc--ctcp-response
+               (:include erc-response)
+               (:constructor
+                erc--ctcp-response-from-parsed
+                (&key parsed buffer statusmsg prefix dispname
+                      &aux (unparsed (erc-response.unparsed parsed))
+                      (sender (erc-response.sender parsed))
+                      (command (erc-response.command parsed))
+                      (command-args (erc-response.command-args parsed))
+                      (contents (erc-response.contents parsed))
+                      (tags (erc-response.tags parsed)))))
+  "Data for a processed CTCP query or reply."
+  (buffer nil :type (or buffer null))
+  (statusmsg nil :type (or null string))
+  (prefix nil :type (or erc-channel-user null))
+  (dispname nil :type (or string null)))
+
 (cl-defstruct erc--isupport-data
   "Abstract \"class\" for parsed ISUPPORT data.
 For use with the macro `erc--with-isupport-data'."
@@ -109,9 +156,12 @@ For use with the macro `erc--with-isupport-data'."
 (cl-defstruct (erc--parsed-prefix (:include erc--isupport-data))
   "Server-local data for recognized membership-status prefixes.
 Derived from the advertised \"PREFIX\" ISUPPORT parameter."
-  (letters "qaohv" :type string)
-  (statuses "~&@%+" :type string)
-  (alist nil :type (list-of cons)))
+  ( letters "vhoaq" :type string
+    :documentation "Status letters ranked lowest to highest.")
+  ( statuses "+%@&~" :type string
+    :documentation "Status prefixes ranked lowest to highest.")
+  ( alist nil :type (list-of cons)
+    :documentation "Alist of letters-prefix pairs."))
 
 (cl-defstruct (erc--channel-mode-types (:include erc--isupport-data))
   "Server-local \"CHANMODES\" data."
@@ -302,6 +352,7 @@ instead of a `set' state, which precludes any actual 
saving."
     (read (current-buffer))))
 
 (defmacro erc--find-feature (name alias)
+  ;; Don't use this outside of the file that defines NAME.
   `(pcase (erc--find-group ',name ,(and alias (list 'quote alias)))
      ('erc (and-let* ((file (or (macroexp-file-name) buffer-file-name)))
              (intern (file-name-base file))))
@@ -319,8 +370,12 @@ See Info node `(elisp) Defining Minor Modes' for more.")
 (defmacro define-erc-module (name alias doc enable-body disable-body
                                   &optional local-p)
   "Define a new minor mode using ERC conventions.
-Symbol NAME is the name of the module.
-Symbol ALIAS is the alias to use, or nil.
+Expect NAME to be the module's name and ALIAS, when non-nil, to
+be a retired name used only for compatibility purposes.  In new
+code, assume NAME is the same symbol users should specify when
+customizing `erc-modules' (see info node `(erc) Module Loading'
+for more on naming).
+
 DOC is the documentation string to use for the minor mode.
 ENABLE-BODY is a list of expressions used to enable the mode.
 DISABLE-BODY is a list of expressions used to disable the mode.
@@ -351,7 +406,10 @@ Example:
   (let* ((sn (symbol-name name))
          (mode (intern (format "erc-%s-mode" (downcase sn))))
          (enable (intern (format "erc-%s-enable" (downcase sn))))
-         (disable (intern (format "erc-%s-disable" (downcase sn)))))
+         (disable (intern (format "erc-%s-disable" (downcase sn))))
+         (nmodule (erc--normalize-module-symbol name))
+         (amod (and alias (intern (format "erc-%s-mode"
+                                          (downcase (symbol-name alias)))))))
     `(progn
        (define-minor-mode
          ,mode
@@ -368,13 +426,9 @@ if ARG is omitted or nil.
            (if ,mode (,enable) (,disable))))
        ,(erc--assemble-toggle local-p name enable mode t enable-body)
        ,(erc--assemble-toggle local-p name disable mode nil disable-body)
-       ,@(and-let* ((alias)
-                    ((not (eq name alias)))
-                    (aname (intern (format "erc-%s-mode"
-                                           (downcase (symbol-name alias))))))
-           `((defalias ',aname #',mode)
-             (put ',aname 'erc-module ',(erc--normalize-module-symbol name))))
-       (put ',mode 'erc-module ',(erc--normalize-module-symbol name))
+       ,@(and amod `((defalias ',amod #',mode)
+                     (put ',amod 'erc-module ',nmodule)))
+       (put ',mode 'erc-module ',nmodule)
        ;; For find-function and find-variable.
        (put ',mode    'definition-name ',name)
        (put ',enable  'definition-name ',name)
@@ -431,10 +485,9 @@ If no server buffer exists, return nil."
              ,@body)))))
 
 (defmacro erc-with-all-buffers-of-server (process pred &rest forms)
-  "Execute FORMS in all buffers which have same process as this server.
-FORMS will be evaluated in all buffers having the process PROCESS and
-where PRED matches or in all buffers of the server process if PRED is
-nil."
+  "Evaluate FORMS in all buffers of PROCESS in which PRED returns non-nil.
+When PROCESS is nil, do so in all ERC buffers.  When PRED is nil,
+run FORMS unconditionally."
   (declare (indent 2) (debug (form form body)))
   (macroexp-let2 nil pred pred
     `(erc-buffer-filter (lambda ()
@@ -458,6 +511,7 @@ nil."
     (if session-buffer
         (progn
           (set-buffer session-buffer)
+          (defvar erc-dbuf)
           (if (not (and erc-dbuf (bufferp erc-dbuf) (buffer-live-p erc-dbuf)))
               (progn
                 (setq erc-dbuf (get-buffer-create
@@ -473,6 +527,9 @@ nil."
           (set-buffer cb))
       (message "ERC: ** %s" string))))
 
+(defvar erc-log-p nil
+  "When non-nil, generate debug messages in an \"*ERC-DEBUG*\" buffer.")
+
 (define-inline erc-log (string)
   "Logs STRING if logging is on (see `erc-log-p')."
   (inline-quote
@@ -488,15 +545,17 @@ Use the CASEMAPPING ISUPPORT parameter to determine the 
style."
                      (_ erc--casemapping-rfc1459))
     (downcase string)))
 
-(define-inline erc-get-channel-user (nick)
-  "Find NICK in the current buffer's `erc-channel-users' hash table."
+(define-inline erc-get-channel-member (nick)
+  "Find NICK in the current buffer's `erc-channel-members' hash table."
   (inline-quote (gethash (erc-downcase ,nick) erc-channel-users)))
+(defalias 'erc-get-channel-user #'erc-get-channel-member)
 
 (define-inline erc-get-server-user (nick)
   "Find NICK in the current server's `erc-server-users' hash table."
   (inline-letevals (nick)
-    (inline-quote (erc-with-server-buffer
-                    (gethash (erc-downcase ,nick) erc-server-users)))))
+    (inline-quote
+     (gethash (erc-downcase ,nick)
+              (erc-with-server-buffer erc-server-users)))))
 
 (defmacro erc--with-dependent-type-match (type &rest features)
   "Massage Custom :type TYPE with :match function that pre-loads FEATURES."
@@ -506,6 +565,77 @@ Use the CASEMAPPING ISUPPORT parameter to determine the 
style."
                              (,(widget-get (widget-convert type) :match) w v))
                     ',(cdr type)))
 
+;; This internal variant exists as a transition aid to avoid
+;; immediately having to reflow lengthy definition lists, like the one
+;; in erc.el.  These sites should switch to using the public macro
+;; when undergoing their next major edit.
+(defmacro erc--define-catalog (name entries)
+  "Define `erc-display-message' formatting templates for NAME, a symbol.
+
+See `erc-define-message-format-catalog' for the meaning of
+ENTRIES, an alist, and `erc-tests-common-pp-propertized-parts' in
+tests/lisp/erc/erc-tests.el for a convenience command to convert
+a literal string into a sequence of `propertize' forms, which are
+much easier to review and edit.  When ENTRIES begins with a
+sequence of keyword-value pairs remove them and consider their
+evaluated values before processing the alist proper.
+
+Currently, the only recognized keyword is `:parent', which tells
+ERC to search recursively for a given template key using the
+keyword's associated value, another catalog symbol, if not found
+in catalog NAME."
+  (declare (indent 1))
+  (let (out)
+    (while (keywordp (car entries))
+      (push (pcase-exhaustive (pop entries)
+              (:parent `(put ',name 'erc--base-format-catalog
+                             ,(pop entries))))
+            out))
+    (dolist (e entries (cons 'progn (nreverse out)))
+      (push `(defvar ,(intern (format "erc-message-%s-%s" name (car e)))
+               ,(cdr e)
+               ,(let* ((first (format "Message template for key `%s'" (car e)))
+                       (last (format "catalog `%s'." name))
+                       (combined (concat first " in " last)))
+                  (if (< (length combined) 80)
+                      combined
+                    (concat first ".\nFor use with " last))))
+            out))))
+
+(defmacro erc-define-message-format-catalog (language &rest entries)
+  "Define message-formatting templates for LANGUAGE, a symbol.
+Expect ENTRIES to be pairs of (KEY . FORMAT), where KEY is a
+symbol, and FORMAT evaluates to a format string compatible with
+`format-spec'.  Expect modules that only define a handful of
+entries to do so manually, instead of using this macro, so that
+the resulting variables will end up with more useful doc strings."
+  (declare (indent 1)
+           (debug (symbolp [&rest [keywordp form]] &rest (symbolp . form))))
+  `(erc--define-catalog ,language ,entries))
+
+(define-inline erc--strpos (char string)
+  "Return position of CHAR in STRING or nil if not found."
+  (inline-quote (string-search (string ,char) ,string)))
+
+(defmacro erc--doarray (spec &rest body)
+  "Map over ARRAY, running BODY with VAR bound to iteration element.
+Behave more or less like `seq-doseq', but tailor operations for
+arrays.
+
+\(fn (VAR ARRAY [RESULT]) BODY...)"
+  (declare (indent 1) (debug ((symbolp form &optional form) body)))
+  (let ((array (make-symbol "array"))
+        (len (make-symbol "len"))
+        (i (make-symbol "i")))
+    `(let* ((,array ,(nth 1 spec))
+            (,len (length ,array))
+            (,i 0))
+       (while-let (((< ,i ,len))
+                   (,(car spec) (aref ,array ,i)))
+         ,@body
+         (cl-incf ,i))
+       ,(nth 2 spec))))
+
 (provide 'erc-common)
 
 ;;; erc-common.el ends here
diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el
index e0f6e9b5134..dede833a93d 100644
--- a/lisp/erc/erc-compat.el
+++ b/lisp/erc/erc-compat.el
@@ -1,6 +1,6 @@
 ;;; erc-compat.el --- ERC compatibility code for older Emacsen  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <alex@gnu.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el
index f05ae41fc51..522973a0156 100644
--- a/lisp/erc/erc-dcc.el
+++ b/lisp/erc/erc-dcc.el
@@ -1,6 +1,6 @@
 ;;; erc-dcc.el --- CTCP DCC module for ERC  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
 ;; Author: Ben A. Mesander <ben@gnu.ai.mit.edu>
 ;;         Noah Friedman <friedman@prep.ai.mit.edu>
@@ -131,9 +131,8 @@ Looks like:
     (open-network-stream procname buffer addr port
                          :type (and (plist-get entry :secure) 'tls))))
 
-(erc-define-catalog
- 'english
- '((dcc-chat-discarded
+(erc--define-catalog english
+  ((dcc-chat-discarded
     . "DCC: previous chat request from %n (%u@%h) discarded")
    (dcc-chat-ended . "DCC: chat with %n ended %t: %e")
    (dcc-chat-no-request . "DCC: chat request from %n not found")
@@ -714,8 +713,8 @@ It extracts the information about the dcc request and adds 
it to
              (port (match-string 4 query))
              (size (match-string 5 query))
              (sub (substring (match-string 6 query) 0 -4))
-             (secure (seq-contains-p sub ?S #'eq))
-             (turbo (seq-contains-p sub ?T #'eq)))
+             (secure (string-search "S" sub))
+             (turbo (string-search "T" sub)))
         ;; FIXME: a warning really should also be sent
         ;; if the ip address != the host the dcc sender is on.
         (erc-display-message
@@ -1252,14 +1251,16 @@ other client."
 (defun erc-dcc-chat-parse-output (proc str)
   (save-match-data
     (let ((posn 0)
+          (erc--msg-prop-overrides `((erc--spkr . ,erc-dcc-from)))
+          (nick (propertize (erc--speakerize-nick erc-dcc-from)
+                            'font-lock-face 'erc-nick-default-face))
           line)
       (while (string-match "\n" str posn)
         (setq line (substring str posn (match-beginning 0)))
         (setq posn (match-end 0))
         (erc-display-message
          nil nil proc
-         'dcc-chat-privmsg ?n (propertize erc-dcc-from 'font-lock-face
-                                          'erc-nick-default-face) ?m line))
+         'dcc-chat-privmsg ?n nick ?m line))
       (setq erc-dcc-unprocessed-output (substring str posn)))))
 
 (defun erc-dcc-chat-buffer-killed ()
diff --git a/lisp/erc/erc-desktop-notifications.el 
b/lisp/erc/erc-desktop-notifications.el
index 5721bc0204a..2e905097f97 100644
--- a/lisp/erc/erc-desktop-notifications.el
+++ b/lisp/erc/erc-desktop-notifications.el
@@ -1,6 +1,6 @@
 ;;; erc-desktop-notifications.el --- Send notification on PRIVMSG or mentions 
-*- lexical-binding:t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Julien Danjou <julien@danjou.info>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-ezbounce.el b/lisp/erc/erc-ezbounce.el
index 38ac4de5ac7..33d01438819 100644
--- a/lisp/erc/erc-ezbounce.el
+++ b/lisp/erc/erc-ezbounce.el
@@ -1,6 +1,6 @@
 ;;; erc-ezbounce.el ---  Handle EZBounce bouncer commands  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002, 2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Andreas Fuchs <asf@void.at>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el
index 82e881cb71c..b91ce007087 100644
--- a/lisp/erc/erc-fill.el
+++ b/lisp/erc/erc-fill.el
@@ -1,6 +1,6 @@
 ;;; erc-fill.el --- Filling IRC messages in various ways  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2001-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Andreas Fuchs <asf@void.at>
 ;;         Mario Lang <mlang@delysid.org>
@@ -144,12 +144,14 @@ user-defined functions."
   :package-version '(ERC . "5.6")
   :type 'boolean)
 
-(defcustom erc-fill-line-spacing nil
+(defvar erc-fill-line-spacing nil
   "Extra space between messages on graphical displays.
-Its value should be larger than that of the variable
-`line-spacing', if set.  When unsure, start with 0.5."
-  :package-version '(ERC . "5.6")
-  :type '(choice (const nil) number))
+Its value should probably be larger than that of the variable
+`line-spacing', if non-nil.  When unsure, start with 1.0.  Note
+that as of ERC 5.6, this feature doesn't combine well with the
+`scrolltobottom' module, which is de facto required when using
+the `fill-wrap' filling style.  Users should therefore regard
+this variable as experimental for the time being.")
 
 (defvar-local erc-fill--function nil
   "Internal copy of `erc-fill-function'.
@@ -177,11 +179,10 @@ You can put this on `erc-insert-modify-hook' and/or 
`erc-send-modify-hook'."
           (when-let ((erc-fill-line-spacing)
                      (p (point-min)))
             (widen)
-            (when (or (erc--check-msg-prop 'erc-msg 'msg)
-                      (and-let* ((m (save-excursion
-                                      (forward-line -1)
-                                      (erc--get-inserted-msg-prop 'erc-msg))))
-                        (eq 'msg m)))
+            (when (or (erc--check-msg-prop 'erc--spkr)
+                      (save-excursion
+                        (forward-line -1)
+                        (erc--get-inserted-msg-prop 'erc--spkr)))
               (put-text-property (1- p) p
                                  'line-spacing erc-fill-line-spacing))))))))
 
@@ -190,7 +191,7 @@ You can put this on `erc-insert-modify-hook' and/or 
`erc-send-modify-hook'."
   (save-restriction
     (goto-char (point-min))
     (when-let (((looking-at "^\\(\\S-+\\)"))
-               ((not (erc--check-msg-prop 'erc-msg 'datestamp)))
+               ((not (erc--check-msg-prop 'erc--msg 'datestamp)))
                (nick (match-string 1)))
       (progn
         (let ((fill-column (- erc-fill-column (erc-timestamp-offset)))
@@ -262,9 +263,7 @@ the value of `erc-fill-wrap-visual-keys'."
   "Whether to consolidate consecutive messages from the same speaker.
 When non-nil, ERC omits redundant speaker labels for subsequent
 messages less than a day apart.  To help distinguish between
-merged messages, see related options `erc-fill-line-spacing', for
-graphical displays, and `erc-fill-wrap-merge-indicator' for text
-terminals."
+merged messages, see option `erc-fill-wrap-merge-indicator'."
   :package-version '(ERC . "5.6")
   :type 'boolean)
 
@@ -282,19 +281,25 @@ Only matters when the option `erc-fill-wrap-merge' is 
enabled.
 If the first element is the symbol `pre', ERC uses this option to
 generate a replacement for the speaker's name tag.  If the first
 element is `post', ERC affixes a short string to the end of the
-previous message.  (Note that the latter variant nullifies any
-intervening padding supplied by `erc-fill-line-spacing' and is
-meant to supplant that option in text terminals.)  In either
-case, the second element should be a character, like ?>, and the
-last element a valid face.  In special cases, you may also
-specify a cons of `pre'/`post' and a string, which tells ERC you
-know what you're doing and not to manage the process for you.  If
-unsure, try either of the first two presets, both of which
-replace a continued speaker's name with a dot-product-like glyph
-in `shadow' face.  Note that this option is still experimental,
-and changing its value mid-session is not yet supported (though,
-if you must, make sure to run \\[erc-fill-wrap-refill-buffer]
-afterward)."
+previous message.  In either case, the second element should be a
+character, like ?>, and the last element a valid face.  In
+special cases, you may also specify a cons of either
+aforementioned symbol and a string, which tells ERC not to manage
+the process for you.  If unsure, try either of the first two
+presets, both of which replace a continued speaker's name with a
+dot-product-like character in a `shadow'-like face.
+
+Note that as of ERC 5.6, this option is still experimental, and
+changing its value mid-session is not yet supported (though, if
+you must, make sure to run \\[erc-fill-wrap-refill-buffer]
+afterward).  Also note that users on versions of Emacs older than
+29.2 may experience a \"glitching\" effect when point resides on
+a \"merged\" message occupying the first or last line in a
+window.  If that happens, try replacing `top' with the integer 1
+in the option `recenter-positions' while also maybe adjusting
+`scroll-margin' and/or `scroll-preserve-screen-position' to avoid
+\"dragging\" point when issuing a `scroll-up' or `scroll-down'
+command."
   :package-version '(ERC . "5.6")
   :type
   '(choice (const nil)
@@ -469,12 +474,12 @@ cycling between logical- and screen-line oriented command
 movement.  Similarly, use \\[erc-fill-wrap-refill-buffer] to fix
 alignment problems after running certain commands, like
 `text-scale-adjust'.  Also see related stylistic options
-`erc-fill-line-spacing', `erc-fill-wrap-merge', and
-`erc-fill-wrap-merge-indicator'.  Hint: in narrow windows, where
-is space tight, try setting `erc-fill-static-center' to 1.  And
-if you also use the option `erc-fill-wrap-merge-indicator', set
-that to value-menu item \"Leading MIDDLE DOT (U+00B7) sans gap\"
-or one of the various \"trailing\" items.
+`erc-fill-wrap-merge', and `erc-fill-wrap-merge-indicator'.
+\(Hint: in narrow windows, where is space tight, try setting
+`erc-fill-static-center' to 1.  And if you also use the option
+`erc-fill-wrap-merge-indicator', set that to value-menu item
+\"Leading MIDDLE DOT sans gap\" or one of the various
+\"trailing\" items.)
 
 This module imposes various restrictions on the appearance of
 timestamps.  Most notably, it insists on displaying them in the
@@ -547,43 +552,38 @@ behavior of taking the length from the first \"word\".  
This
 variable can be converted to a public one if needed by third
 parties.")
 
-(defvar-local erc-fill--wrap-last-msg nil)
-(defvar erc-fill--wrap-max-lull (* 24 60 60))
+(defvar-local erc-fill--wrap-last-msg nil "Marker for merging speakers.")
+(defvar erc-fill--wrap-max-lull (* 24 60 60) "Max secs for merging speakers.")
 
 (defun erc-fill--wrap-continued-message-p ()
   "Return non-nil when the current speaker hasn't changed.
-That is, indicate whether the text just inserted is from the same
-sender as that of the previous \"PRIVMSG\"."
-  (and
-   (not (erc--check-msg-prop 'erc-ephemeral))
-   (progn ; preserve blame for now, unprogn on next major change
-     (prog1
-         (and-let*
-             ((m (or erc-fill--wrap-last-msg
-                     (setq erc-fill--wrap-last-msg (point-min-marker))
-                     nil))
-              ((< (1+ (point-min)) (- (point) 2)))
-              (props (save-restriction
-                       (widen)
-                       (and-let*
-                           (((eq 'msg (get-text-property m 'erc-msg)))
-                            ((not (eq (get-text-property m 'erc-ctcp)
-                                      'ACTION)))
-                            ((not (invisible-p m)))
-                            (spr (next-single-property-change m 'erc-speaker)))
-                         (cons (get-text-property m 'erc-ts)
-                               (get-text-property spr 'erc-speaker)))))
-              (ts (pop props))
-              (props)
-              ((not (time-less-p (erc-stamp--current-time) ts)))
-              ((time-less-p (time-subtract (erc-stamp--current-time) ts)
-                            erc-fill--wrap-max-lull))
-              ;; Assume presence of leading angle bracket or hyphen.
-              (speaker (next-single-property-change (point-min) 'erc-speaker))
-              ((not (erc--check-msg-prop 'erc-ctcp 'ACTION)))
-              (nick (get-text-property speaker 'erc-speaker))
-              ((erc-nick-equal-p props nick))))
-       (set-marker erc-fill--wrap-last-msg (point-min))))))
+But only if the `erc--msg' text property also hasn't.  That is,
+indicate whether the chat message just inserted is from the same
+person as the prior one and is formatted in the same manner.  As
+a side effect, advance `erc-fill--wrap-last-msg' unless the
+message has been marked `erc--ephemeral'."
+  (and-let*
+      (((not (erc--check-msg-prop 'erc--ephemeral)))
+       ;; Always set/move `erc-fill--wrap-last-msg' from here on down.
+       (m (or (and erc-fill--wrap-last-msg
+                   (prog1 (marker-position erc-fill--wrap-last-msg)
+                     (set-marker erc-fill--wrap-last-msg (point-min))))
+              (ignore (setq erc-fill--wrap-last-msg (point-min-marker)))))
+       ((>= (point) 4)) ; skip the first message
+       (props (save-restriction
+                (widen)
+                (and-let* ((speaker (get-text-property m 'erc--spkr))
+                           (type (get-text-property m 'erc--msg))
+                           ((not (invisible-p m))))
+                  (list (get-text-property m 'erc--ts) type speaker))))
+       (ts (nth 0 props))
+       (type (nth 1 props))
+       (speaker (nth 2 props))
+       ((not (time-less-p (erc-stamp--current-time) ts)))
+       ((time-less-p (time-subtract (erc-stamp--current-time) ts)
+                     erc-fill--wrap-max-lull))
+       ((erc--check-msg-prop 'erc--msg type))
+       ((erc-nick-equal-p speaker (erc--check-msg-prop 'erc--spkr))))))
 
 (defun erc-fill--wrap-measure (beg end)
   "Return display spec width for inserted region between BEG and END.
@@ -666,12 +666,12 @@ See `erc-fill-wrap-mode' for details."
     (goto-char (point-min))
     (let ((len (or (and erc-fill--wrap-length-function
                         (funcall erc-fill--wrap-length-function))
-                   (and-let* ((msg-prop (erc--check-msg-prop 'erc-msg))
+                   (and-let* ((msg-prop (erc--check-msg-prop 'erc--msg))
                               ((not (eq msg-prop 'unknown))))
                      (when-let ((e (erc--get-speaker-bounds))
                                 (b (pop e))
                                 ((or erc-fill--wrap-action-dedent-p
-                                     (not (erc--check-msg-prop 'erc-ctcp
+                                     (not (erc--check-msg-prop 'erc--ctcp
                                                                'ACTION)))))
                        (goto-char e))
                      (skip-syntax-forward "^-")
@@ -744,16 +744,19 @@ With REPAIRP, destructively fill gaps and re-merge 
speakers."
       (remove-text-properties beg (1+ end) '(line-prefix nil wrap-prefix nil))
       (when-let ((repairp)
                  (dbeg (text-property-not-all beg end 'display nil))
-                 ((get-text-property (1+ dbeg) 'erc-speaker))
+                 ((get-text-property (1+ dbeg) 'erc--speaker))
                  (dval (get-text-property dbeg 'display))
                  ((equal "" dval)))
         (remove-text-properties
          dbeg (text-property-not-all dbeg end 'display dval) '(display)))
-      (let* ((pos (if (eq 'date-left (get-text-property beg 'erc-stamp-type))
-                      (field-beginning beg)
+      ;; This "should" work w/o `front-sticky' and `rear-nonsticky'.
+      (let* ((pos (if-let (((eq 'erc-timestamp (field-at-pos beg)))
+                           (b (field-beginning beg))
+                           ((eq 'datestamp (get-text-property b 'erc--msg))))
+                      b
                     beg))
              (erc--msg-props (map-into (text-properties-at pos) 'hash-table))
-             (erc-stamp--current-time (gethash 'erc-ts erc--msg-props)))
+             (erc-stamp--current-time (gethash 'erc--ts erc--msg-props)))
         (save-restriction
           (narrow-to-region beg (1+ end))
           (let ((erc-fill--wrap-last-msg erc-fill--wrap-rejigger-last-message))
@@ -765,7 +768,7 @@ With REPAIRP, destructively fill gaps and re-merge 
speakers."
       ;; Skip to end of message upon encountering accidental gaps
       ;; introduced by third parties (or bugs).
       (if-let (((/= ?\n (char-after end)))
-               (next (erc--get-inserted-msg-bounds 'end beg)))
+               (next (erc--get-inserted-msg-end beg)))
           (progn
             (cl-assert (= ?\n (char-after next)))
             (when repairp ; eol <= next
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 6c8ec567bd9..7e30b1060fd 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -1,6 +1,6 @@
 ;;; erc-goodies.el --- Collection of ERC modules  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Jorgen Schaefer <forcer@forcix.cx>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -83,7 +83,7 @@ be experimental.  It currently only works with Emacs 28+."
    (when (and erc-scrolltobottom-all (< emacs-major-version 28))
      (erc-button--display-error-notice-with-keys
       "Option `erc-scrolltobottom-all' requires Emacs 28+. Disabling.")
-     (setopt erc-scrolltobottom-all nil))
+     (setq erc-scrolltobottom-all nil))
    (unless erc--updating-modules-p (erc-buffer-do #'erc--scrolltobottom-setup))
    (if erc-scrolltobottom-all
        (progn
@@ -300,7 +300,10 @@ A value of t means \"all\" ERC buffers."
 
 (defcustom erc-keep-place-indicator-follow nil
   "Whether to sync visual kept place to window's top when reading.
-For use with `erc-keep-place-indicator-mode'."
+For use with `erc-keep-place-indicator-mode'.  When enabled, the
+indicator updates when the last window displaying the same buffer
+switches away, but only if the indicator resides earlier in the
+buffer than the window's start."
   :group 'erc
   :package-version '(ERC . "5.6")
   :type 'boolean)
@@ -328,42 +331,30 @@ For use with `erc-keep-place-indicator-mode'."
 (defvar-local erc--keep-place-indicator-overlay nil
   "Overlay for `erc-keep-place-indicator-mode'.")
 
-(defun erc--keep-place-indicator-on-window-configuration-change ()
+(defun erc--keep-place-indicator-on-window-buffer-change (_)
   "Maybe sync `erc--keep-place-indicator-overlay'.
-Specifically, do so unless switching to or from another window in
-the active frame."
-  (when erc-keep-place-indicator-follow
-    (unless (or (minibuffer-window-active-p (minibuffer-window))
-                (eq (window-old-buffer) (current-buffer)))
-      (when (< (overlay-end erc--keep-place-indicator-overlay)
-               (window-start)
-               erc-insert-marker)
-        (erc-keep-place-move (window-start))))))
-
-(defun erc--keep-place-indicator-setup ()
-  "Initialize buffer for maintaining `erc--keep-place-indicator-overlay'."
-  (require 'fringe)
-  (erc--restore-initialize-priors erc-keep-place-indicator-mode
-    erc--keep-place-indicator-overlay (make-overlay 0 0))
-  (add-hook 'erc-keep-place-mode-hook
-            #'erc--keep-place-indicator-on-global-module nil t)
-  (add-hook 'window-configuration-change-hook
-            #'erc--keep-place-indicator-on-window-configuration-change nil t)
-  (when-let* (((memq erc-keep-place-indicator-style '(t arrow)))
-              (ov-property (if (zerop (fringe-columns 'left))
-                               'after-string
-                             'before-string))
-              (display (if (zerop (fringe-columns 'left))
-                           `((margin left-margin) ,overlay-arrow-string)
-                         '(left-fringe right-triangle
-                                       erc-keep-place-indicator-arrow)))
-              (bef (propertize " " 'display display)))
-    (overlay-put erc--keep-place-indicator-overlay ov-property bef))
-  (when (memq erc-keep-place-indicator-style '(t face))
-    (overlay-put erc--keep-place-indicator-overlay 'face
-                 'erc-keep-place-indicator-line)))
+Do so only when switching to a new buffer in the same window if
+the replaced buffer is no longer visible in another window and
+its `window-start' at the time of switching is strictly greater
+than the indicator's position."
+  (when-let ((erc-keep-place-indicator-follow)
+             (window (selected-window))
+             ((not (eq window (active-minibuffer-window))))
+             (old-buffer (window-old-buffer window))
+             ((buffer-live-p old-buffer))
+             ((not (eq old-buffer (current-buffer))))
+             (ov (buffer-local-value 'erc--keep-place-indicator-overlay
+                                     old-buffer))
+             ((not (get-buffer-window old-buffer 'visible)))
+             (prev (assq old-buffer (window-prev-buffers window)))
+             (old-start (nth 1 prev))
+             (old-inmkr (buffer-local-value 'erc-insert-marker old-buffer))
+             ((< (overlay-end ov) old-start old-inmkr)))
+    (with-current-buffer old-buffer
+      (erc-keep-place-move old-start))))
 
 ;;;###autoload(put 'keep-place-indicator 'erc--feature 'erc-goodies)
+;;;###autoload(autoload 'erc-keep-place-indicator-mode "erc-goodies" nil t)
 (define-erc-module keep-place-indicator nil
   "Buffer-local `keep-place' with fringe arrow and/or highlighted face.
 Play nice with global module `keep-place' but don't depend on it.
@@ -374,29 +365,58 @@ and `keep-place-indicator' in different buffers."
           (erc-keep-place-mode +1))
          ;; Enable a local version of `keep-place-mode'.
          (t (add-hook 'erc-insert-pre-hook  #'erc-keep-place 65 t)))
+   (require 'fringe)
+   (add-hook 'window-buffer-change-functions
+             #'erc--keep-place-indicator-on-window-buffer-change 40)
+   (add-hook 'erc-keep-place-mode-hook
+             #'erc--keep-place-indicator-on-global-module 40)
    (if (pcase erc-keep-place-indicator-buffer-type
          ('target erc--target)
          ('server (not erc--target))
          ('t t))
-       (erc--keep-place-indicator-setup)
+       (progn
+         (erc--restore-initialize-priors erc-keep-place-indicator-mode
+           erc--keep-place-indicator-overlay (make-overlay 0 0))
+         (when-let (((memq erc-keep-place-indicator-style '(t arrow)))
+                    (ov-property (if (zerop (fringe-columns 'left))
+                                     'after-string
+                                   'before-string))
+                    (display (if (zerop (fringe-columns 'left))
+                                 `((margin left-margin) ,overlay-arrow-string)
+                               '(left-fringe right-triangle
+                                             erc-keep-place-indicator-arrow)))
+                    (bef (propertize " " 'display display)))
+           (overlay-put erc--keep-place-indicator-overlay ov-property bef))
+         (when (memq erc-keep-place-indicator-style '(t face))
+           (overlay-put erc--keep-place-indicator-overlay 'face
+                        'erc-keep-place-indicator-line)))
      (erc-keep-place-indicator-mode -1)))
   ((when erc--keep-place-indicator-overlay
      (delete-overlay erc--keep-place-indicator-overlay))
-   (remove-hook 'window-configuration-change-hook
-                #'erc--keep-place-indicator-on-window-configuration-change t)
+   (let ((buffer (current-buffer)))
+     ;; Remove global hooks unless others exist with mode enabled.
+     (unless (erc-buffer-filter (lambda ()
+                                  (and (not (eq buffer (current-buffer)))
+                                       erc-keep-place-indicator-mode)))
+       (remove-hook 'erc-keep-place-mode-hook
+                    #'erc--keep-place-indicator-on-global-module)
+       (remove-hook 'window-buffer-change-functions
+                    #'erc--keep-place-indicator-on-window-buffer-change)))
+   (when (local-variable-p 'erc-insert-pre-hook)
+     (remove-hook 'erc-insert-pre-hook  #'erc-keep-place t))
    (remove-hook 'erc-keep-place-mode-hook
                 #'erc--keep-place-indicator-on-global-module t)
-   (remove-hook 'erc-insert-pre-hook  #'erc-keep-place t)
    (kill-local-variable 'erc--keep-place-indicator-overlay))
   'local)
 
 (defun erc--keep-place-indicator-on-global-module ()
-  "Ensure `keep-place-indicator' can cope with `erc-keep-place-mode'.
-That is, ensure the local module can survive a user toggling the
-global one."
-  (if erc-keep-place-mode
-      (remove-hook 'erc-insert-pre-hook  #'erc-keep-place t)
-    (add-hook 'erc-insert-pre-hook  #'erc-keep-place 65 t)))
+  "Ensure `keep-place-indicator' survives toggling `erc-keep-place-mode'.
+Do this by simulating `keep-place' in all buffers where
+`keep-place-indicator' is enabled."
+  (erc-with-all-buffers-of-server nil (lambda () erc-keep-place-indicator-mode)
+    (if erc-keep-place-mode
+        (remove-hook 'erc-insert-pre-hook  #'erc-keep-place t)
+      (add-hook 'erc-insert-pre-hook  #'erc-keep-place 65 t))))
 
 (defun erc-keep-place-move (pos)
   "Move keep-place indicator to current line or POS.
@@ -450,8 +470,7 @@ For use with `keep-place-indicator' module."
     (forward-line -1)
     (when erc-keep-place-indicator-mode
       (unless (or (minibuffer-window-active-p (selected-window))
-                  (and (frame-visible-p (selected-frame))
-                       (get-buffer-window (current-buffer) (selected-frame))))
+                  (get-buffer-window nil 'visible))
         (erc-keep-place-move nil)))
     ;; if `switch-to-buffer-preserve-window-point' is set,
     ;; we cannot rely on point being saved, and must commit
@@ -564,21 +583,24 @@ Do nothing if the variable `erc-command-indicator' is 
nil."
   "Insert `erc-input' STATE's message if it's an echoed command."
   (cl-assert erc-command-indicator-mode)
   (when (erc--input-split-cmdp state)
-    (setf (erc--input-split-insertp state) #'erc--command-indicator-display)
+    (setf (erc--input-split-insertp state) t
+          (erc--input-split-substxt state) #'erc--command-indicator-display)
     (erc-send-distinguish-noncommands state)))
 
 ;; This function used to be called `erc-display-command'.  It was
 ;; neutered in ERC 5.3.x (Emacs 24.5), commented out in 5.4, removed
 ;; in 5.5, and restored in 5.6.
-(defun erc--command-indicator-display (line)
+(defun erc--command-indicator-display (line &rest rest)
   "Insert command LINE as echoed input resembling that of REPLs and shells."
   (when erc-insert-this
+    (when rest
+      (setq line (string-join (cons line rest) "\n")))
     (save-excursion
       (erc--assert-input-bounds)
       (let ((insert-position (marker-position (goto-char erc-insert-marker)))
             (erc--msg-props (or erc--msg-props
                                 (let ((ovs erc--msg-prop-overrides))
-                                  (map-into `((erc-msg . slash-cmd)
+                                  (map-into `((erc--msg . slash-cmd)
                                               ,@(reverse ovs))
                                             'hash-table)))))
         (when-let ((string (erc-command-indicator))
@@ -803,7 +825,7 @@ The value `erc-interpret-controls-p' must also be t for 
this to work."
 ;;;###autoload(autoload 'erc-irccontrols-mode "erc-goodies" nil t)
 (define-erc-module irccontrols nil
   "This mode enables the interpretation of IRC control chars."
-  ((add-hook 'erc-insert-modify-hook #'erc-controls-highlight)
+  ((add-hook 'erc-insert-modify-hook #'erc-controls-highlight -50)
    (add-hook 'erc-send-modify-hook #'erc-controls-highlight)
    (erc--modify-local-map t "C-c C-c" #'erc-toggle-interpret-controls))
   ((remove-hook 'erc-insert-modify-hook #'erc-controls-highlight)
diff --git a/lisp/erc/erc-ibuffer.el b/lisp/erc/erc-ibuffer.el
index 790efae97ac..6e8a196255b 100644
--- a/lisp/erc/erc-ibuffer.el
+++ b/lisp/erc/erc-ibuffer.el
@@ -1,6 +1,6 @@
 ;;; erc-ibuffer.el --- ibuffer integration with ERC  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2002, 2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-identd.el b/lisp/erc/erc-identd.el
index 5fdac58716c..2c95b16c12e 100644
--- a/lisp/erc/erc-identd.el
+++ b/lisp/erc/erc-identd.el
@@ -1,6 +1,6 @@
 ;;; erc-identd.el --- RFC1413 (identd authentication protocol) server  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-imenu.el b/lisp/erc/erc-imenu.el
index f053c6279b8..4c9cbfc1580 100644
--- a/lisp/erc/erc-imenu.el
+++ b/lisp/erc/erc-imenu.el
@@ -1,6 +1,6 @@
 ;;; erc-imenu.el --- Imenu support for ERC  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-join.el b/lisp/erc/erc-join.el
index 2a57e77a622..cb57d8a00a1 100644
--- a/lisp/erc/erc-join.el
+++ b/lisp/erc/erc-join.el
@@ -1,6 +1,6 @@
 ;;; erc-join.el --- autojoin channels on connect and reconnects  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <alex@gnu.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-lang.el b/lisp/erc/erc-lang.el
index 9261d659c72..9613a7f2c32 100644
--- a/lisp/erc/erc-lang.el
+++ b/lisp/erc/erc-lang.el
@@ -1,6 +1,6 @@
 ;;; erc-lang.el --- provide the LANG command to ERC  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2002, 2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <alex@gnu.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-list.el b/lisp/erc/erc-list.el
index 099096771ac..3beb9ffe741 100644
--- a/lisp/erc/erc-list.el
+++ b/lisp/erc/erc-list.el
@@ -1,6 +1,6 @@
 ;;; erc-list.el --- /list support for ERC  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Tom Tromey <tromey@redhat.com>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el
index 79fece5779e..d5c56bcc2b3 100644
--- a/lisp/erc/erc-log.el
+++ b/lisp/erc/erc-log.el
@@ -1,6 +1,6 @@
 ;;; erc-log.el --- Logging facilities for ERC.  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Lawrence Mitchell <wence@gmx.li>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -231,7 +231,7 @@ also be a predicate function.  To only log when you are not 
set away, use:
    (add-hook 'erc-part-hook #'erc-conditional-save-buffer)
    ;; append, so that 'erc-initialize-log-marker runs first
    (add-hook 'erc-connect-pre-hook #'erc-log-setup-logging 'append)
-   (add-hook 'erc--pre-clear-functions #'erc-save-buffer-in-logs)
+   (add-hook 'erc--pre-clear-functions #'erc-save-buffer-in-logs 50)
    (dolist (buffer (erc-buffer-list))
      (erc-log-setup-logging buffer))
    (erc--modify-local-map t "C-c C-l" #'erc-save-buffer-in-logs))
@@ -430,7 +430,8 @@ You can save every individual message by putting this 
function on
              (if (and erc-truncate-buffer-on-save
                       (called-interactively-p 'interactive))
                   (let ((erc-log--save-in-progress-p t))
-                    (erc-cmd-CLEAR)
+                    (save-excursion (goto-char erc-insert-marker)
+                                    (erc-cmd-CLEAR))
                     (erc-button--display-error-notice-with-keys
                      (erc-server-buffer) "Option `%s' is deprecated."
                      " Use /CLEAR instead." 'erc-truncate-buffer-on-save))
diff --git a/lisp/erc/erc-match.el b/lisp/erc/erc-match.el
index 6fff54d3cf4..8497382a733 100644
--- a/lisp/erc/erc-match.el
+++ b/lisp/erc/erc-match.el
@@ -1,6 +1,6 @@
 ;;; erc-match.el --- Highlight messages matching certain regexps  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Andreas Fuchs <asf@void.at>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-menu.el b/lisp/erc/erc-menu.el
index 7f877a34c0a..ee32bd4d29f 100644
--- a/lisp/erc/erc-menu.el
+++ b/lisp/erc/erc-menu.el
@@ -1,6 +1,6 @@
 ;;; erc-menu.el --- Menu-bar definitions for ERC  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2002, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2002, 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-netsplit.el b/lisp/erc/erc-netsplit.el
index 5dd11ab1869..15798793df8 100644
--- a/lisp/erc/erc-netsplit.el
+++ b/lisp/erc/erc-netsplit.el
@@ -1,6 +1,6 @@
 ;;; erc-netsplit.el --- Reduce JOIN/QUIT messages on netsplits  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -41,7 +41,7 @@ netsplits, so that it can filter the JOIN messages on a 
netjoin too."
 ;;;###autoload(autoload 'erc-netsplit-mode "erc-netsplit")
 (define-erc-module netsplit nil
   "This mode hides quit/join messages if a netsplit occurs."
-  ((erc-netsplit-install-message-catalogs)
+  ( ; FIXME delete newline on next edit
    (add-hook 'erc-server-JOIN-functions #'erc-netsplit-JOIN)
    (add-hook 'erc-server-MODE-functions #'erc-netsplit-MODE)
    (add-hook 'erc-server-QUIT-functions #'erc-netsplit-QUIT)
@@ -85,13 +85,22 @@ where FIRST-JOIN is t or nil, depending on whether or not 
the first
 join from that split has been detected or not.")
 
 (defun erc-netsplit-install-message-catalogs ()
+  (declare (obsolete "defined at top level in erc-netsplit.el" "30.1"))
+  (with-suppressed-warnings ((obsolete erc-define-catalog)) ; indentation
   (erc-define-catalog
    'english
    '((netsplit        . "netsplit: %s")
      (netjoin         . "netjoin: %s, %N were split")
      (netjoin-done     . "netjoin: All lost souls are back!")
      (netsplit-none    . "No netsplits in progress")
-     (netsplit-wholeft . "split: %s missing: %n %t"))))
+     (netsplit-wholeft . "split: %s missing: %n %t"))))) ; indentation
+
+(erc-define-message-format-catalog english
+  (netsplit . "netsplit: %s")
+  (netjoin . "netjoin: %s, %N were split")
+  (netjoin-done . "netjoin: All lost souls are back!")
+  (netsplit-none . "No netsplits in progress")
+  (netsplit-wholeft . "split: %s missing: %n %t"))
 
 (defun erc-netsplit-JOIN (proc parsed)
   "Show/don't show rejoins."
diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el
index f168c90df65..1b26afa1164 100644
--- a/lisp/erc/erc-networks.el
+++ b/lisp/erc/erc-networks.el
@@ -1,6 +1,6 @@
 ;;; erc-networks.el --- IRC networks  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@lexx.delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -42,25 +42,19 @@
 
 (defvar erc--target)
 (defvar erc-insert-marker)
-(defvar erc-kill-buffer-hook)
-(defvar erc-kill-server-hook)
 (defvar erc-modules)
 (defvar erc-rename-buffers)
 (defvar erc-reuse-buffers)
 (defvar erc-server-announced-name)
 (defvar erc-server-connected)
-(defvar erc-server-parameters)
 (defvar erc-server-process)
-(defvar erc-session-server)
 
 (declare-function erc--get-isupport-entry "erc-backend" (key &optional single))
 (declare-function erc-buffer-filter "erc" (predicate &optional proc))
 (declare-function erc-current-nick "erc" nil)
 (declare-function erc-display-error-notice "erc" (parsed string))
 (declare-function erc-display-message "erc" (parsed type buffer msg &rest 
args))
-(declare-function erc-error "erc" (&rest args))
 (declare-function erc-get-buffer "erc" (target &optional proc))
-(declare-function erc-server-buffer "erc" nil)
 (declare-function erc-server-process-alive "erc-backend" (&optional buffer))
 (declare-function erc-set-active-buffer "erc" (buffer))
 
@@ -1129,10 +1123,27 @@ TARGET to be an `erc--target' object."
      (lambda ()
        (when (and erc--target (eq (erc--target-symbol erc--target)
                                   (erc--target-symbol target)))
-         (let ((oursp (if (erc--target-channel-local-p target)
-                          (equal announced erc-server-announced-name)
-                        (erc-networks--id-equal-p identity erc-networks--id))))
-           (funcall (if oursp on-dupe on-collision))))))))
+         ;; When a server sends administrative queries immediately
+         ;; after connection registration and before the session has a
+         ;; net-id, the buffer remains orphaned until reassociated
+         ;; here retroactively.
+         (unless erc-networks--id
+           (let ((id (erc-with-server-buffer erc-networks--id))
+                 (server-buffer (process-buffer erc-server-process)))
+             (apply #'erc-button--display-error-notice-with-keys
+                    server-buffer
+                    (concat "Missing network session (ID) for %S. "
+                            (if id "Using `%S' from %S." "Ignoring."))
+                    (current-buffer)
+                    (and id (list (erc-networks--id-symbol
+                                   (setq erc-networks--id id))
+                                  server-buffer)))))
+         (when erc-networks--id
+           (let ((oursp (if (erc--target-channel-local-p target)
+                            (equal announced erc-server-announced-name)
+                          (erc-networks--id-equal-p identity
+                                                    erc-networks--id))))
+             (funcall (if oursp on-dupe on-collision)))))))))
 
 (defconst erc-networks--qualified-sep "@"
   "Separator used for naming a target buffer.")
@@ -1229,6 +1240,8 @@ Use the server parameter NETWORK if provided, otherwise 
parse the
 server name and search for a match in `erc-networks-alist'."
   ;; The server made it easy for us and told us the name of the NETWORK
   (declare (obsolete "maybe see `erc-networks--determine'" "29.1"))
+  (defvar erc-server-parameters)
+  (defvar erc-session-server)
   (let ((network-name (cdr (assoc "NETWORK" erc-server-parameters))))
     (if network-name
        (intern network-name)
@@ -1381,6 +1394,8 @@ already been copied over to the current, replacement 
buffer.")
 (defun erc-networks--copy-over-server-buffer-contents (existing name)
   "Kill off existing server buffer after copying its contents.
 Must be called from the replacement buffer."
+  (defvar erc-kill-buffer-hook)
+  (defvar erc-kill-server-hook)
   ;; ERC expects `erc-open' to be idempotent when setting up local
   ;; vars and other context properties for a new identity.  Thus, it's
   ;; unlikely we'll have to copy anything else over besides text.  And
@@ -1586,14 +1601,29 @@ return the host alone sans URL formatting (for 
compatibility)."
   '((pals Libera.Chat ("kensanata" "shapr" "anti\\(fuchs\\|gone\\)"))
     (format-nick-function (Libera.Chat "#emacs") erc-format-@nick))
   "Experimental: Alist of configuration options.
+
+WARNING: this variable is a vestige from a long-abandoned
+experiment.  ERC may redefine it using the same name for any
+purpose at any time.
+
 The format is (VARNAME SCOPE VALUE) where
 VARNAME is a symbol identifying the configuration option,
 SCOPE is either a symbol which identifies an entry from
   `erc-networks-alist' or a list (NET TARGET) where NET is a network symbol and
   TARGET is a string identifying the channel/query target.
 VALUE is the options value.")
+(make-obsolete-variable 'erc-settings
+                        "temporarily deprecated for later repurposing" "30.1")
 
 (defun erc-get (var &optional net target)
+  "Retrieve configuration values from `erc-settings'.
+
+WARNING: this function is a non-functioning remnant from a
+long-abandoned experiment.  ERC may redefine it using the same
+name for any purpose at any time.
+
+\(fn &rest UNKNOWN)"
+  (declare (obsolete "temporarily deprecated for later repurposing" "30.1"))
   (let ((items erc-settings)
        elt val)
     (while items
diff --git a/lisp/erc/erc-nicks.el b/lisp/erc/erc-nicks.el
index fcd3afdbbc4..64f9ec42783 100644
--- a/lisp/erc/erc-nicks.el
+++ b/lisp/erc/erc-nicks.el
@@ -1,6 +1,6 @@
 ;;; erc-nicks.el -- Nick colors for ERC  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: David Leatherman <leathekd@gmail.com>
 ;;         Andy Stewart <lazycat.manatee@gmail.com>
@@ -173,6 +173,20 @@ adding extra characters or padding, for example, with 
something
 like \"@%-012n\"."
   :type 'string)
 
+(defcustom erc-nicks-track-faces 'prioritize
+  "Show nick faces in the `track' module's portion of the mode line.
+A value of nil means don't show nick faces at all.  A value of
+`defer' means have `track' consider nick faces only after those
+ranked faces in `erc-track-faces-normal-list'.  This has the
+effect of \"alternating\" between a ranked \"normal\" and a nick.
+The value `prioritize' means have `track' consider nick faces to
+be \"normal\" unless the current speaker is the same as the
+previous one, in which case pretend the value is `defer'.  Like
+most options in this module, updating the value mid-session is
+not officially supported, although cycling \\[erc-nicks-mode] may
+be worth a shot."
+  :type '(choice (const nil) (const defer) (const prioritize)))
+
 (defvar erc-nicks--max-skip-search 3 ; make this an option?
   "Max number of faces to visit when testing `erc-nicks-skip-faces'.")
 
@@ -195,6 +209,7 @@ Keys are nonempty strings but need not be valid nicks.")
 
 (defvar help-xref-stack)
 (defvar help-xref-stack-item)
+(defvar erc-track--normal-faces)
 
 ;; https://stackoverflow.com/questions/596216#answer-56678483
 (defun erc-nicks--get-luminance (color)
@@ -454,7 +469,9 @@ Favor a custom erc-nicks-NICK@NETWORK-face when defined."
           (put new-face 'erc-nicks--nick nick)
           (put new-face 'erc-nicks--netid erc-networks--id)
           (put new-face 'erc-nicks--key key)
-          (face-spec-set new-face `((t :foreground ,color)) 'face-defface-spec)
+          (face-spec-set new-face `((t :foreground ,color
+                                       :inherit ,erc-nicks-backing-face))
+                         'face-defface-spec)
           (set-face-documentation
            new-face (format "Internal face for %s on %s." nick (erc-network)))
           (puthash nick new-face table)))))
@@ -503,12 +520,8 @@ Abandon search after examining LIMIT faces."
              ((not (and base-face
                         (erc-nicks--skip-p base-face erc-nicks-skip-faces
                                            erc-nicks--max-skip-search))))
-             (key (erc-nicks--gen-key-from-format-spec trimmed))
-             (out (erc-nicks--get-face trimmed key)))
-    (if (or (null erc-nicks-backing-face)
-            (eq base-face erc-nicks-backing-face))
-        out
-      (cons out (erc-list erc-nicks-backing-face)))))
+             (key (erc-nicks--gen-key-from-format-spec trimmed)))
+    (erc-nicks--get-face trimmed key)))
 
 (defun erc-nicks--highlight-button (nick-object)
   "Possibly add face to `erc-button--nick-user' NICK-OBJECT."
@@ -518,7 +531,12 @@ Abandon search after examining LIMIT faces."
                                 'font-lock-face))
        (nick (erc-server-user-nickname (erc-button--nick-user nick-object)))
        (out (erc-nicks--highlight nick face)))
-    (setf (erc-button--nick-nickname-face nick-object) out))
+    (setf (erc-button--nick-nickname-face nick-object) out
+          ;;
+          (erc-button--nick-face-cache nick-object)
+          (and erc-nicks-track-faces
+               (bound-and-true-p erc-track--normal-faces)
+               #'erc-nicks--remember-face-for-track)))
   nick-object)
 
 (define-erc-module nicks nil
@@ -561,6 +579,8 @@ Abandon search after examining LIMIT faces."
        erc-nicks--face-table (make-hash-table :test #'equal)))
    (setf (alist-get "Edit face" erc-button--nick-popup-alist nil nil #'equal)
          #'erc-nicks-customize-face)
+   (erc-nicks--setup-track-integration)
+   (add-hook 'erc-track-mode #'erc-nicks--setup-track-integration 50 t)
    (advice-add 'widget-create-child-and-convert :filter-args
                #'erc-nicks--redirect-face-widget-link))
   ((kill-local-variable 'erc-nicks--face-table)
@@ -572,8 +592,12 @@ Abandon search after examining LIMIT faces."
    (kill-local-variable 'erc-nicks--downcased-skip-nicks)
    (when (fboundp 'erc-button--phantom-users-mode)
      (erc-button--phantom-users-mode -1))
+   (remove-function (local 'erc-track--face-reject-function)
+                    #'erc-nicks--reject-uninterned-faces)
    (remove-function (local 'erc-button--modify-nick-function)
                     #'erc-nicks--highlight-button)
+   (remove-function (local 'erc-track--alt-normals-function)
+                    #'erc-nicks--check-normals)
    (setf (alist-get "Edit face"
                     erc-button--nick-popup-alist nil 'remove #'equal)
          nil)
@@ -693,6 +717,58 @@ Expect PREFIX to be something like \"ansi-color-\" or 
\"font-lock-\"."
                  (color (face-foreground face)))
         (push color out)))))
 
+(defun erc-nicks--reject-uninterned-faces (candidate)
+  "Remove own faces from CANDIDATE if it's a combination of faces."
+  (while-let ((next (car-safe candidate))
+              ((facep next))
+              ((not (intern-soft next))))
+    (setq candidate (cdr candidate)))
+  (if (and (consp candidate) (not (cdr candidate))) (car candidate) candidate))
+
+(define-inline erc-nicks--oursp (face)
+  (inline-quote
+   (and-let* ((sym (car-safe ,face))
+              ((symbolp sym))
+              ((get sym 'erc-nicks--key)))
+     sym)))
+
+(defun erc-nicks--check-normals (current contender contenders normals)
+  "Return a viable `nicks'-owned face from NORMALS in CONTENDERS.
+But only do so if the CURRENT face is also one of ours and in
+NORMALS and if the highest ranked CONTENDER among new faces is
+`erc-default-face', the lowest ranking default priority face."
+  (and-let* (((eq contender 'erc-default-face))
+             ((or (null current) (gethash current normals)))
+             (spkr (or (null current) (erc-nicks--oursp current))))
+    (catch 'contender
+      (dolist (candidate (cdr contenders) contender)
+        (when-let (((not (equal candidate current)))
+                   ((gethash candidate normals))
+                   (s (erc-nicks--oursp candidate))
+                   ((not (eq s spkr))))
+          (throw 'contender candidate))))))
+
+(defun erc-nicks--setup-track-integration ()
+  "Restore traditional \"alternating normal\" face functionality to mode-line."
+  (when (bound-and-true-p erc-track-mode)
+    (pcase erc-nicks-track-faces
+      ;; Variant `defer' is handled elsewhere.
+      ('prioritize
+       (add-function :override (local 'erc-track--alt-normals-function)
+                     #'erc-nicks--check-normals))
+      ('nil
+       (add-function :override (local 'erc-track--face-reject-function)
+                     #'erc-nicks--reject-uninterned-faces)))))
+
+(defun erc-nicks--remember-face-for-track (face)
+  "Add FACE to local hash table maintained by `track' module."
+  (or (gethash face erc-track--normal-faces)
+      (if-let ((sym (or (car-safe face) face))
+               ((symbolp sym))
+               ((get sym 'erc-nicks--key)))
+          (puthash face face erc-track--normal-faces)
+        face)))
+
 (provide 'erc-nicks)
 
 ;;; erc-nicks.el ends here
diff --git a/lisp/erc/erc-notify.el b/lisp/erc/erc-notify.el
index cf7ffbb40d7..45b0fb12c43 100644
--- a/lisp/erc/erc-notify.el
+++ b/lisp/erc/erc-notify.el
@@ -1,6 +1,6 @@
 ;;; erc-notify.el --- Online status change notification  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@lexx.delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -30,7 +30,6 @@
 ;;; Code:
 
 (require 'erc)
-(require 'erc-networks)
 (eval-when-compile (require 'pcomplete))
 
 ;;;; Customizable variables
@@ -78,12 +77,14 @@ strings."
 ;;;; Setup
 
 (defun erc-notify-install-message-catalogs ()
-  (erc-define-catalog
-   'english
-   '((notify_current . "Notified people online: %l")
-     (notify_list    . "Current notify list: %l")
-     (notify_on      . "Detected %n on IRC network %m")
-     (notify_off     . "%n has left IRC network %m"))))
+  (declare (obsolete "defined at top level in erc-notify.el" "30.1"))
+  (with-suppressed-warnings ((obsolete erc-define-catalog))
+    (erc-define-catalog
+     'english
+     '((notify-current . "Notified people online: %l")
+       (notify-list    . "Current notify list: %l")
+       (notify-on      . "Detected %n on IRC network %m")
+       (notify-off     . "%n has left IRC network %m")))))
 
 ;;;###autoload(autoload 'erc-notify-mode "erc-notify" nil t)
 (define-erc-module notify nil
@@ -119,14 +120,14 @@ changes."
             (run-hook-with-args 'erc-notify-signon-hook server (car new-list))
             (erc-display-message
              parsed 'notice proc
-             'notify_on ?n (car new-list) ?m (erc-network-name)))
+              'notify-on ?n (car new-list) ?m (erc-network-name)))
           (setq new-list (cdr new-list)))
         (while old-list
           (when (not (erc-member-ignore-case (car old-list) ison-list))
             (run-hook-with-args 'erc-notify-signoff-hook server (car old-list))
             (erc-display-message
              parsed 'notice proc
-             'notify_off ?n (car old-list) ?m (erc-network-name)))
+              'notify-off ?n (car old-list) ?m (erc-network-name)))
           (setq old-list (cdr old-list)))
         (setq erc-last-ison ison-list)
         t)))
@@ -136,8 +137,8 @@ changes."
 
 (defun erc-notify-JOIN (proc parsed)
   "Check if channel joiner is on `erc-notify-list' and not on `erc-last-ison'.
-If this condition is satisfied, produce a notify_on message and add the nick
-to `erc-last-ison' to prevent any further notifications."
+When that's the case, produce a `notify-on' message and add the
+nick to `erc-last-ison' to prevent any further notifications."
   (let ((nick (erc-extract-nick (erc-response.sender parsed))))
     (when (and (erc-member-ignore-case nick erc-notify-list)
               (not (erc-member-ignore-case nick erc-last-ison)))
@@ -147,13 +148,13 @@ to `erc-last-ison' to prevent any further notifications."
                          nick)
       (erc-display-message
        parsed 'notice proc
-       'notify_on ?n nick ?m (erc-network-name)))
+       'notify-on ?n nick ?m (erc-network-name)))
     nil))
 
 (defun erc-notify-NICK (proc parsed)
   "Check if new nick is on `erc-notify-list' and not on `erc-last-ison'.
-If this condition is satisfied, produce a notify_on message and add the nick
-to `erc-last-ison' to prevent any further notifications."
+When that's the case, produce a `notify-on' message and add the
+nick to `erc-last-ison' to prevent any further notifications."
   (let ((nick (erc-response.contents parsed)))
     (when (and (erc-member-ignore-case nick erc-notify-list)
               (not (erc-member-ignore-case nick erc-last-ison)))
@@ -163,13 +164,13 @@ to `erc-last-ison' to prevent any further notifications."
                          nick)
       (erc-display-message
        parsed 'notice proc
-       'notify_on ?n nick ?m (erc-network-name)))
+       'notify-on ?n nick ?m (erc-network-name)))
     nil))
 
 (defun erc-notify-QUIT (proc parsed)
   "Check if quitter is on `erc-notify-list' and on `erc-last-ison'.
-If this condition is satisfied, produce a notify_off message and remove the
-nick from `erc-last-ison' to prevent any further notifications."
+When that's the case, insert a `notify-off' message and remove
+the nick from `erc-last-ison' to prevent further notifications."
   (let ((nick (erc-extract-nick (erc-response.sender parsed))))
     (when (and (erc-member-ignore-case nick erc-notify-list)
               (erc-member-ignore-case nick erc-last-ison))
@@ -183,7 +184,7 @@ nick from `erc-last-ison' to prevent any further 
notifications."
                          nick)
       (erc-display-message
        parsed 'notice proc
-       'notify_off ?n nick ?m (erc-network-name)))
+       'notify-off ?n nick ?m (erc-network-name)))
     nil))
 
 ;;;; User level command
@@ -193,6 +194,12 @@ nick from `erc-last-ison' to prevent any further 
notifications."
   "Change `erc-notify-list' or list current notify-list members online.
 Without args, list the current list of notified people online,
 with args, toggle notify status of people."
+  (unless erc-notify-mode
+    (erc-notify-mode +1)
+    (erc-button--display-error-notice-with-keys
+     (current-buffer)
+     "Command /NOTIFY requires the `notify' module. Enabling now. Add `notify'"
+     " to `erc-modules' before next starting ERC to silence this message."))
   (cond
    ((null args)
     ;; Print current notified people (online)
@@ -202,11 +209,12 @@ with args, toggle notify status of people."
           nil 'notice 'active "No ison-list yet!")
        (erc-display-message
         nil 'notice 'active
-        'notify_current ?l ison))))
+         'notify-current ?l ison))))
    ((string= (car args) "-l")
-    (erc-display-message nil 'notice 'active
-                        'notify_list ?l (mapconcat #'identity erc-notify-list
-                                                   " ")))
+    (let ((list (if erc-notify-list
+                    (mapconcat #'identity erc-notify-list " ")
+                  "(empty)")))
+      (erc-display-message nil 'notice 'active 'notify-list ?l list)))
    (t
     (while args
       (if (erc-member-ignore-case (car args) erc-notify-list)
@@ -225,23 +233,34 @@ with args, toggle notify status of people."
        (setq erc-notify-list (cons (erc-string-no-properties (car args))
                                    erc-notify-list)))
       (setq args (cdr args)))
-    (erc-display-message
-     nil 'notice 'active
-     'notify_list ?l (mapconcat #'identity erc-notify-list " "))))
+    (erc-cmd-NOTIFY "-l")))
   t)
 
-(autoload 'pcomplete-erc-all-nicks "erc-pcomplete")
-
 ;; "--" is not a typo.
 (declare-function pcomplete--here "pcomplete"
                  (&optional form stub paring form-only))
+(declare-function pcomplete-erc-all-nicks "erc-pcomplete"
+                  (&optional postfix))
 
 ;;;###autoload
 (defun pcomplete/erc-mode/NOTIFY ()
-  (require 'pcomplete)
-  (pcomplete-here (pcomplete-erc-all-nicks)))
-
-(erc-notify-install-message-catalogs)
+  (require 'erc-pcomplete)
+  (pcomplete-here (append erc-notify-list (pcomplete-erc-all-nicks))))
+
+(define-obsolete-variable-alias 'erc-message-english-notify_on
+  'erc-message-english-notify-on "30.1")
+(define-obsolete-variable-alias 'erc-message-english-notify_off
+  'erc-message-english-notify-off "30.1")
+(define-obsolete-variable-alias 'erc-message-english-notify_list
+  'erc-message-english-notify-list "30.1")
+(define-obsolete-variable-alias 'erc-message-english-notify_current
+  'erc-message-english-notify-current "30.1")
+
+(erc-define-message-format-catalog english
+  (notify-current . "Notified people online: %l")
+  (notify-list . "Current notify list: %l")
+  (notify-on . "Detected %n on IRC network %m")
+  (notify-off . "%n has left IRC network %m"))
 
 (provide 'erc-notify)
 
diff --git a/lisp/erc/erc-page.el b/lisp/erc/erc-page.el
index a94678e5132..7e777adfaf9 100644
--- a/lisp/erc/erc-page.el
+++ b/lisp/erc/erc-page.el
@@ -1,6 +1,6 @@
 ;;; erc-page.el --- CTCP PAGE support for ERC  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002, 2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
 
@@ -42,7 +42,8 @@
   "Process CTCP PAGE requests from IRC."
   nil nil)
 
-(erc-define-catalog-entry 'english 'CTCP-PAGE "Page from %n (%u@%h): %m")
+(defvar erc-message-english-CTCP-PAGE "Page from %n (%u@%h): %m"
+  "English template for a CTCP PAGE message.")
 
 (defcustom erc-page-function nil
   "A function to process a \"page\" request.
diff --git a/lisp/erc/erc-pcomplete.el b/lisp/erc/erc-pcomplete.el
index 7eb7431fb91..05cbaf3872f 100644
--- a/lisp/erc/erc-pcomplete.el
+++ b/lisp/erc/erc-pcomplete.el
@@ -1,6 +1,6 @@
 ;;; erc-pcomplete.el --- Provides programmable completion for ERC  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Sacha Chua <sacha@free.net.ph>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -58,7 +58,9 @@ add this string to nicks completed."
 
 ;;;###autoload(put 'Completion 'erc--module 'completion)
 ;;;###autoload(put 'pcomplete 'erc--module 'completion)
+;;;###autoload(put 'completion 'erc--feature 'erc-pcomplete)
 ;;;###autoload(autoload 'erc-completion-mode "erc-pcomplete" nil t)
+(put 'completion 'erc-group 'erc-pcomplete)
 (define-erc-module pcomplete Completion
   "In ERC Completion mode, the TAB key does completion whenever possible."
   ((add-hook 'erc-mode-hook #'pcomplete-erc-setup)
diff --git a/lisp/erc/erc-replace.el b/lisp/erc/erc-replace.el
index 8c1c35b46d7..6374a8773d3 100644
--- a/lisp/erc/erc-replace.el
+++ b/lisp/erc/erc-replace.el
@@ -1,6 +1,6 @@
 ;;; erc-replace.el --- wash and massage messages inserted into the buffer  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Andreas Fuchs <asf@void.at>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-ring.el b/lisp/erc/erc-ring.el
index 4534e913204..d05d44044ea 100644
--- a/lisp/erc/erc-ring.el
+++ b/lisp/erc/erc-ring.el
@@ -1,6 +1,6 @@
 ;;; erc-ring.el --- Command history handling for erc using ring.el  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <alex@gnu.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-sasl.el b/lisp/erc/erc-sasl.el
index c6922b1b26b..f1cc68e2620 100644
--- a/lisp/erc/erc-sasl.el
+++ b/lisp/erc/erc-sasl.el
@@ -1,6 +1,6 @@
 ;;; erc-sasl.el --- SASL for ERC -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 ;;
 ;; This file is part of GNU Emacs.
 ;;
@@ -305,9 +305,8 @@ If necessary, pass PROMPT to `read-passwd'."
                        (| eot ",")))
                   (downcase offered)))
 
-(erc-define-catalog
- 'english
- '((s902 . "ERR_NICKLOCKED nick %n unavailable: %s")
+(erc--define-catalog english
+  ((s902 . "ERR_NICKLOCKED nick %n unavailable: %s")
    (s904 . "ERR_SASLFAIL (authentication failed) %s")
    (s905 . "ERR SASLTOOLONG (credentials too long) %s")
    (s906 . "ERR_SASLABORTED (authentication aborted) %s")
@@ -333,8 +332,8 @@ This doesn't solicit or validate a suite of supported 
mechanisms."
             (client (erc-sasl--create-client mech)))
        (unless client
          (erc-display-error-notice
-          nil (format "Unknown or unsupported SASL mechanism: %s" mech))
-         (erc-error "Unknown or unsupported SASL mechanism: %s" mech))
+          nil (format "Unknown or unsupported SASL mechanism: `%s'" mech))
+         (error "Unknown or unsupported SASL mechanism: `%s'" mech))
        (setf (erc-sasl--state-client erc-sasl--state) client))))
   ((kill-local-variable 'erc-sasl--state)
    (kill-local-variable 'erc-sasl--options))
@@ -371,9 +370,10 @@ This doesn't solicit or validate a suite of supported 
mechanisms."
           (setq data (concat (substring data end) (and (= end 400) "+"))))))))
 
 (defun erc-sasl--destroy (proc)
-  (run-hook-with-args 'erc-quit-hook proc)
+  "Destroy process PROC and warn user that their settings are likely faulty."
   (delete-process proc)
-  (erc-error "Disconnected from %s; please review SASL settings" proc))
+  (erc--lwarn 'erc-sasl :error
+              "Disconnected from %s; please review SASL settings" proc))
 
 (define-erc-response-handler (902)
   "Handle an ERR_NICKLOCKED response." nil
diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el
index 47c59f76b5c..92cb9075b5e 100644
--- a/lisp/erc/erc-services.el
+++ b/lisp/erc/erc-services.el
@@ -1,6 +1,6 @@
 ;;; erc-services.el --- Identify to NickServ  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
 ;; URL: https://www.emacswiki.org/emacs/ErcNickserv
@@ -169,7 +169,7 @@ You can also use \\[erc-nickserv-identify-mode] to change 
modes."
   :type 'boolean)
 
 (defcustom erc-use-auth-source-for-nickserv-password nil
-  "Query auth-source for a password when identifiying to NickServ.
+  "Query auth-source for a password when identifying to NickServ.
 Passwords from `erc-nickserv-passwords' take precedence.  See
 function `erc-nickserv-get-password'."
   :version "28.1"
diff --git a/lisp/erc/erc-sound.el b/lisp/erc/erc-sound.el
index 083d72805df..f1c6601427f 100644
--- a/lisp/erc/erc-sound.el
+++ b/lisp/erc/erc-sound.el
@@ -1,6 +1,6 @@
 ;;; erc-sound.el --- CTCP SOUND support for ERC  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2002-2003, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2006-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
 ;; URL: https://www.emacswiki.org/emacs/ErcSound
@@ -63,7 +63,8 @@ and play sound files as requested."
   ((remove-hook 'erc-ctcp-query-SOUND-hook #'erc-ctcp-query-SOUND)
    (define-key erc-mode-map "\C-c\C-s" #'undefined)))
 
-(erc-define-catalog-entry 'english 'CTCP-SOUND "%n (%u@%h) plays %s:%m")
+(defvar erc-message-english-CTCP-SOUND "%n (%u@%h) plays %s:%m"
+  "English template for a CTCP SOUND message.")
 
 (defcustom erc-play-sound t
   "Play sounds when you receive CTCP SOUND requests."
diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
index 93be7b9f074..e3d28aa60dd 100644
--- a/lisp/erc/erc-speedbar.el
+++ b/lisp/erc/erc-speedbar.el
@@ -1,6 +1,6 @@
 ;;; erc-speedbar.el --- Speedbar support for ERC  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Contributor: Eric M. Ludlam <zappo@gnu.org>
@@ -319,9 +319,9 @@ a list of four items: the userhost, the GECOS, the current
         (info (erc-server-user-info user))
         (login (erc-server-user-login user))
         (name (erc-server-user-full-name user))
-        (voice (and cuser (erc-channel-user-voice cuser)))
-        (op (and cuser (erc-channel-user-op cuser)))
-        (nick-str (concat (if op "@" "") (if voice "+" "") nick))
+         (nick-str (concat (with-current-buffer (or buffer (current-buffer))
+                             (erc-get-channel-membership-prefix cuser))
+                           nick))
         (finger (concat login (when (or login host) "@") host))
          (sbtoken (list finger name info (buffer-name buffer))))
     (if (or login host name info) ; we want to be expandable
@@ -455,10 +455,7 @@ The INDENT level is ignored."
          `(display-buffer-in-side-window
            . ((side . right)
               (window-width . ,erc-speedbar-nicknames-window-width)))))
-    (erc-status-sidebar-set-window-preserve-size)
-    (when-let ((window (get-buffer-window speedbar-buffer)))
-      (set-window-parameter window 'no-other-window nil)
-      (internal-show-cursor window t))))
+    (erc-status-sidebar-set-window-preserve-size)))
 
 (defun erc-speedbar--status-sidebar-mode--unhook ()
   "Remove hooks installed by `erc-status-sidebar-mode'."
@@ -506,7 +503,8 @@ The INDENT level is ignored."
                   (speedbar-set-mode-line-format)))
             (when (or (not force) (>= arg 0))
               (with-selected-frame speedbar-frame
-                (erc-speedbar--emulate-sidebar-set-window-preserve-size)))))
+                (erc-speedbar--emulate-sidebar-set-window-preserve-size)
+                (erc-speedbar-toggle-nicknames-window-lock -1)))))
       (when-let (((or (not force) (>= arg 0)))
                  (speedbar-frame-parameters (backquote-list*
                                              '(visibility . nil)
@@ -524,7 +522,8 @@ The INDENT level is ignored."
         ;; Emacs in the meantime.
         (make-frame-invisible speedbar-frame)
         (select-frame (setq speedbar-frame (previous-frame)))
-        (erc-speedbar--emulate-sidebar-set-window-preserve-size))))
+        (erc-speedbar--emulate-sidebar-set-window-preserve-size)
+        (erc-speedbar-toggle-nicknames-window-lock -1))))
   (cl-assert (not (cdr (erc-speedbar--get-timers))) t))
 
 (defun erc-speedbar--ensure (&optional force)
@@ -546,6 +545,29 @@ The INDENT level is ignored."
       (speedbar-set-mode-line-format))))
 
 (defvar erc-speedbar--shutting-down-p nil)
+(defvar erc-speedbar--force-update-interval-secs 5 "Speedbar update period.")
+
+(defvar-local erc-speedbar--last-ran nil
+  "When non-nil, a lisp timestamp updated when the speedbar timer runs.")
+
+(defun erc-speedbar--run-timer-on-post-insert ()
+  "Refresh speedbar if idle for `erc-speedbar--force-update-interval-secs'."
+  (when speedbar-buffer
+    (with-current-buffer speedbar-buffer
+      (when-let
+          ((dframe-timer)
+           ((erc--check-msg-prop 'erc--cmd 'PRIVMSG))
+           (interval erc-speedbar--force-update-interval-secs)
+           ((or (null erc-speedbar--last-ran)
+                (time-less-p erc-speedbar--last-ran
+                             (time-subtract (current-time) interval)))))
+        (run-at-time 0 nil #'dframe-timer-fn)))))
+
+(defun erc-speedbar--reset-last-ran-on-timer ()
+  "Reset `erc-speedbar--last-ran'."
+  (when speedbar-buffer
+    (setf (buffer-local-value 'erc-speedbar--last-ran speedbar-buffer)
+          (current-time))))
 
 ;;;###autoload(autoload 'erc-nickbar-mode "erc-speedbar" nil t)
 (define-erc-module nickbar nil
@@ -560,18 +582,20 @@ raising of frames or the stealing of input focus.  If you 
witness
 such a thing and can reproduce it, please file a bug report with
 \\[erc-bug]."
   ((add-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
+   (add-hook 'erc-insert-post-hook #'erc-speedbar--run-timer-on-post-insert)
+   (add-hook 'speedbar-timer-hook #'erc-speedbar--reset-last-ran-on-timer)
    (erc-speedbar--ensure)
    (unless (or erc--updating-modules-p
                (and-let* ((speedbar-buffer)
                           (win (get-buffer-window speedbar-buffer 'all-frames))
                           ((eq speedbar-frame (window-frame win))))))
-     (if speedbar-buffer
-         (erc-speedbar--ensure 'force)
-       (setq erc-nickbar-mode nil)
-       (when (derived-mode-p 'erc-mode)
-         (erc-error "Not initializing `erc-nickbar-mode' in %s"
-                    (current-buffer))))))
+     (when-let ((buf (or (and (derived-mode-p 'erc-mode) (current-buffer))
+                         (car (erc-buffer-filter #'erc--server-buffer-p)))))
+       (with-current-buffer buf
+         (erc-speedbar--ensure 'force)))))
   ((remove-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
+   (remove-hook 'erc-insert-post-hook #'erc-speedbar--run-timer-on-post-insert)
+   (remove-hook 'speedbar-timer-hook #'erc-speedbar--reset-last-ran-on-timer)
    (when erc-track-mode
      (setq erc-track--switch-fallback-blockers
            (remove '(derived-mode . speedbar-mode)
@@ -611,15 +635,21 @@ such a thing and can reproduce it, please file a bug 
report with
     ;; erc-speedbar.el resets this to nil.
     (setq speedbar-buffer nil)))
 
-(defun erc-speedbar-toggle-nicknames-window-lock ()
-  "Toggle whether nicknames window is selectable with \\[other-window]."
-  (interactive)
+(defun erc-speedbar-toggle-nicknames-window-lock (arg)
+  "Toggle whether nicknames window is selectable with \\[other-window].
+When arg is a number, lock the window if non-negative, otherwise
+unlock."
+  (interactive "P")
   (unless erc-nickbar-mode
     (user-error "`erc-nickbar-mode' inactive"))
   (when-let ((window (get-buffer-window speedbar-buffer)))
-    (let ((val (window-parameter window 'no-other-window)))
-      (set-window-parameter window 'no-other-window (not val))
-      (message "nick-window: %s" (if val "selectable" "protected")))))
+    (let ((val (cond ((natnump arg) t)
+                     ((integerp arg) nil)
+                     (t (not (window-parameter window
+                                               'no-other-window))))))
+      (set-window-parameter window 'no-other-window val)
+      (unless (numberp arg)
+        (message "nick-window: %s" (if val "protected" "selectable"))))))
 
 
 ;;;; Nicks integration
diff --git a/lisp/erc/erc-spelling.el b/lisp/erc/erc-spelling.el
index 83eb849f1b4..b2f565d71bf 100644
--- a/lisp/erc/erc-spelling.el
+++ b/lisp/erc/erc-spelling.el
@@ -1,6 +1,6 @@
 ;;; erc-spelling.el --- use flyspell in ERC  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Jorgen Schaefer <forcer@forcix.cx>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el
index e6a8f36c332..a11739a4195 100644
--- a/lisp/erc/erc-stamp.el
+++ b/lisp/erc/erc-stamp.el
@@ -1,6 +1,6 @@
 ;;; erc-stamp.el --- Timestamping for ERC messages  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -182,9 +182,9 @@ from entering them and instead jump over them."
    (add-hook 'erc-insert-modify-hook #'erc-add-timestamp 70)
    (add-hook 'erc-send-modify-hook #'erc-add-timestamp 70)
    (add-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect)
-   (add-hook 'erc--pre-clear-functions #'erc-stamp--reset-on-clear)
+   (add-hook 'erc--pre-clear-functions #'erc-stamp--reset-on-clear 40)
    (unless erc--updating-modules-p (erc-buffer-do #'erc-stamp--setup)))
-  ((remove-hook 'erc-mode-hook #'erc-munge-invisibility-spec)
+  ((remove-hook 'erc-mode-hook #'erc-stamp--setup)
    (remove-hook 'erc-insert-modify-hook #'erc-add-timestamp)
    (remove-hook 'erc-send-modify-hook #'erc-add-timestamp)
    (remove-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect)
@@ -198,6 +198,7 @@ from entering them and instead jump over them."
   "Escape hatch for omitting stamps when first char is invisible.")
 
 (defun erc-stamp--recover-on-reconnect ()
+  "Attempt to restore \"last-inserted\" snapshots from prior session."
   (when-let ((priors (or erc--server-reconnecting erc--target-priors)))
     (dolist (var '(erc-timestamp-last-inserted
                    erc-timestamp-last-inserted-left
@@ -212,7 +213,7 @@ the stamp passed to `erc-insert-timestamp-function'.")
 
 (cl-defgeneric erc-stamp--current-time ()
   "Return a lisp time object to associate with an IRC message.
-This becomes the message's `erc-ts' text property."
+This becomes the message's `erc--ts' text property."
   (erc-compat--current-lisp-time))
 
 (cl-defmethod erc-stamp--current-time :around ()
@@ -249,10 +250,10 @@ or `erc-send-modify-hook'."
             ;; FIXME on major version bump, make this `erc-' prefixed.
             (if invisible `(timestamp ,@(ensure-list invisible)) 'timestamp))
            (skipp (or (and erc-stamp--skip-when-invisible invisible)
-                      (erc--check-msg-prop 'erc-ephemeral)))
+                      (erc--check-msg-prop 'erc--ephemeral)))
            (erc-stamp--current-time ct))
       (when erc--msg-props
-        (puthash 'erc-ts ct erc--msg-props))
+        (puthash 'erc--ts ct erc--msg-props))
       (unless skipp
         (funcall erc-insert-timestamp-function
                  (erc-format-timestamp ct erc-timestamp-format)))
@@ -270,7 +271,7 @@ or `erc-send-modify-hook'."
                           ;; be different on different entries (bug#22700).
                           (list 'cursor-sensor-functions
                                  ;; Regions are no longer contiguous ^
-                                 '(erc--echo-ts-csf) 'erc-ts ct))))))
+                                 '(erc--echo-ts-csf) 'erc--ts ct))))))
 
 (defvar-local erc-timestamp-last-window-width nil
   "The width of the last window that showed the current buffer.
@@ -403,7 +404,7 @@ non-nil."
                    ;; Skip a line that's just a timestamp.
                    ((> beg (point))))
           (delete-region beg (1+ end)))
-        (when-let (time (erc--get-inserted-msg-prop 'erc-ts))
+        (when-let (time (erc--get-inserted-msg-prop 'erc--ts))
           (insert (format-time-string "[%H:%M:%S] " time)))
         (zerop (forward-line))))
   "")
@@ -660,8 +661,7 @@ truncating `erc-timestamp-format-left' prior to rendering.  
A
 value of t means the option's value doesn't require trimming.")
 
 (defun erc-stamp--propertize-left-date-stamp ()
-  (add-text-properties (point-min) (1- (point-max))
-                       '(field erc-timestamp erc-stamp-type date-left))
+  (add-text-properties (point-min) (1- (point-max)) '(field erc-timestamp))
   (erc--hide-message 'timestamp)
   (run-hooks 'erc-stamp--insert-date-hook))
 
@@ -679,6 +679,13 @@ value of t means the option's value doesn't require 
trimming.")
                                             0 erc-stamp--date-format-end)
                                erc-timestamp-format-left))))
 
+(defun erc-stamp-inserting-date-stamp-p ()
+  "Return non-nil if the narrowed buffer contains a date stamp.
+Expect to be called by members of `erc-insert-modify-hook' and
+`erc-insert-post-hook' to detect whether the message being
+inserted is a date stamp."
+  (erc--check-msg-prop 'erc--msg 'datestamp))
+
 ;; Calling `erc-display-message' from within a hook it's currently
 ;; running is roundabout, but it's a definite means of ensuring hooks
 ;; can act on the date stamp as a standalone message to do things like
@@ -711,8 +718,8 @@ value of t means the option's value doesn't require 
trimming.")
         (setq erc-timestamp-last-inserted-left nil)
         (let* ((aligned (erc-stamp--time-as-day ct))
                (erc-stamp--current-time aligned)
-               ;; Forget current `erc-cmd', etc.
-               (erc--msg-props (map-into `((erc-msg . datestamp))
+               ;; Forget current `erc--cmd', etc.
+               (erc--msg-props (map-into `((erc--msg . datestamp))
                                          'hash-table))
                (erc-timestamp-last-inserted-left rendered)
                erc-timestamp-format erc-away-timestamp-format)
@@ -848,12 +855,20 @@ Return the empty string if FORMAT is nil."
 
 (defvar-local erc-stamp--csf-props-updated-p nil)
 
-;; This function is used to munge `buffer-invisibility-spec' to an
-;; appropriate value. Currently, it only handles timestamps, thus its
-;; location.  If you add other features which affect invisibility,
-;; please modify this function and move it to a more appropriate
-;; location.
-(defun erc-munge-invisibility-spec ()
+(define-obsolete-function-alias 'erc-munge-invisibility-spec
+  #'erc-stamp--manage-local-options-state "30.1"
+  "Perform setup and teardown of `stamp'-owned options.
+
+Note that this function's role in practice has long defied its
+stated mandate as claimed in a now deleted comment, which
+envisioned it as evolving into a central toggle for modifying
+`buffer-invisibility-spec' on behalf of options and features
+ERC-wide.")
+(defun erc-stamp--manage-local-options-state ()
+  "Perform local setup and teardown for `stamp'-owned options.
+For `erc-timestamp-intangible', toggle `cursor-intangible-mode'.
+For `erc-echo-timestamps', integrate with `cursor-sensor-mode'.
+For `erc-hide-timestamps, modify `buffer-invisibility-spec'."
   (if erc-timestamp-intangible
       (cursor-intangible-mode +1) ; idempotent
     (when (bound-and-true-p cursor-intangible-mode)
@@ -863,11 +878,13 @@ Return the empty string if FORMAT is nil."
         (unless erc-stamp--permanent-cursor-sensor-functions
           (dolist (hook '(erc-insert-post-hook erc-send-post-hook))
             (add-hook hook #'erc-stamp--add-csf-on-post-modify nil t))
-          (erc--restore-initialize-priors erc-stamp-mode
-            erc-stamp--csf-props-updated-p nil)
+          (setq erc-stamp--csf-props-updated-p
+                (alist-get 'erc-stamp--csf-props-updated-p
+                           (or erc--server-reconnecting erc--target-priors)))
           (unless erc-stamp--csf-props-updated-p
             (setq erc-stamp--csf-props-updated-p t)
-            (let ((erc--msg-props (map-into '((erc-ts . t)) 'hash-table)))
+            ;; Spoof `erc--ts' as being non-nil.
+            (let ((erc--msg-props (map-into '((erc--ts . t)) 'hash-table)))
               (with-silent-modifications
                 (erc--traverse-inserted
                  (point-min) erc-insert-marker
@@ -889,16 +906,16 @@ Return the empty string if FORMAT is nil."
 
 (defun erc-stamp--add-csf-on-post-modify ()
   "Add `cursor-sensor-functions' to narrowed buffer."
-  (when (erc--check-msg-prop 'erc-ts)
+  (when (erc--check-msg-prop 'erc--ts)
     (put-text-property (point-min) (1- (point-max))
                        'cursor-sensor-functions '(erc--echo-ts-csf))))
 
 (defun erc-stamp--setup ()
   "Enable or disable buffer-local `erc-stamp-mode' modifications."
   (if erc-stamp-mode
-      (erc-munge-invisibility-spec)
+      (erc-stamp--manage-local-options-state)
     (let (erc-echo-timestamps erc-hide-timestamps erc-timestamp-intangible)
-      (erc-munge-invisibility-spec))
+      (erc-stamp--manage-local-options-state))
     ;; Undo local mods from `erc-insert-timestamp-left-and-right'.
     (erc-stamp--date-mode -1) ; kills `erc-timestamp-last-inserted-left'
     (kill-local-variable 'erc-stamp--last-stamp)
@@ -910,7 +927,7 @@ Return the empty string if FORMAT is nil."
   "Hide timestamp information from display."
   (interactive)
   (setq erc-hide-timestamps t)
-  (erc-munge-invisibility-spec))
+  (erc-stamp--manage-local-options-state))
 
 (defun erc-show-timestamps ()
   "Show timestamp information on display.
@@ -918,7 +935,7 @@ This function only works if `erc-timestamp-format' was 
previously
 set, and timestamping is already active."
   (interactive)
   (setq erc-hide-timestamps nil)
-  (erc-munge-invisibility-spec))
+  (erc-stamp--manage-local-options-state))
 
 (defun erc-toggle-timestamps ()
   "Hide or show timestamps in ERC buffers.
@@ -932,7 +949,7 @@ enabled when the message was inserted."
     (setq erc-hide-timestamps t))
   (mapc (lambda (buffer)
          (with-current-buffer buffer
-           (erc-munge-invisibility-spec)))
+            (erc-stamp--manage-local-options-state)))
        (erc-buffer-list)))
 
 (defvar-local erc-stamp--last-stamp nil)
@@ -940,7 +957,7 @@ enabled when the message was inserted."
 (defun erc-stamp--on-clear-message (&rest _)
   "Return `dont-clear-message' when operating inside the same stamp."
   (and erc-stamp--last-stamp erc-echo-timestamps
-       (eq (erc--get-inserted-msg-prop 'erc-ts) erc-stamp--last-stamp)
+       (eq (erc--get-inserted-msg-prop 'erc--ts) erc-stamp--last-stamp)
        'dont-clear-message))
 
 (defun erc-echo-timestamp (dir stamp &optional zone)
@@ -950,7 +967,7 @@ hours (or seconds, if its abs value is larger than 14), and
 interpret a \"raw\" prefix as UTC.  To specify a zone for use
 with the option `erc-echo-timestamps', see the companion option
 `erc-echo-timestamp-zone'."
-  (interactive (list nil (erc--get-inserted-msg-prop 'erc-ts)
+  (interactive (list nil (erc--get-inserted-msg-prop 'erc--ts)
                      (pcase current-prefix-arg
                        ((and (pred numberp) v)
                         (if (<= (abs v) 14) (* v 3600) v))
@@ -964,7 +981,7 @@ with the option `erc-echo-timestamps', see the companion 
option
       (setq erc-stamp--last-stamp nil))))
 
 (defun erc--echo-ts-csf (_window _before dir)
-  (erc-echo-timestamp dir (erc--get-inserted-msg-prop 'erc-ts)))
+  (erc-echo-timestamp dir (erc--get-inserted-msg-prop 'erc--ts)))
 
 (defun erc-stamp--update-saved-position (&rest _)
   (remove-hook 'erc-stamp--insert-date-hook
@@ -974,8 +991,9 @@ with the option `erc-echo-timestamps', see the companion 
option
 (defun erc-stamp--reset-on-clear (pos)
   "Forget last-inserted stamps when POS is at insert marker."
   (when (= pos (1- erc-insert-marker))
-    (add-hook 'erc-stamp--insert-date-hook
-              #'erc-stamp--update-saved-position 0 t)
+    (when erc-stamp--date-mode
+      (add-hook 'erc-stamp--insert-date-hook
+                #'erc-stamp--update-saved-position 0 t))
     (setq erc-timestamp-last-inserted nil
           erc-timestamp-last-inserted-left nil
           erc-timestamp-last-inserted-right nil)))
diff --git a/lisp/erc/erc-status-sidebar.el b/lisp/erc/erc-status-sidebar.el
index d2ecce94bcd..b7695651e4c 100644
--- a/lisp/erc/erc-status-sidebar.el
+++ b/lisp/erc/erc-status-sidebar.el
@@ -1,6 +1,6 @@
 ;;; erc-status-sidebar.el --- HexChat-like activity overview for ERC  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2017, 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017, 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrew Barbarello
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -130,7 +130,7 @@ buffers, using the functions
   `erc-status-sidebar-pad-hierarchy'
 
 for the above-mentioned purposes.  ERC also accepts a list of
-functions to preform these roles a la carte.  Since the members
+functions to perform these roles a la carte.  Since the members
 of the above sets aren't really interoperable, we don't offer
 them here as customization choices, but you can still specify
 them manually.  See doc strings for a description of their
@@ -257,12 +257,13 @@ current frame only."
          " Add `track' to `erc-modules' to silence this message."))
      (erc-track-mode +1))
    (add-hook 'erc--setup-buffer-hook #'erc-status-sidebar--open)
-   (unless erc--updating-modules-p
-     (if (erc-with-server-buffer erc-server-connected)
-         (erc-status-sidebar--open)
-       (when (derived-mode-p 'erc-mode)
-         (erc-error "Not initializing `erc-bufbar-mode' in %s"
-                    (current-buffer))))))
+   ;; Preserve side-window dimensions after `custom-buffer-done'.
+   (when-let (((not erc--updating-modules-p))
+              (buf (or (and (derived-mode-p 'erc-mode) (current-buffer))
+                       (car (erc-buffer-filter
+                             (lambda () erc-server-connected))))))
+     (with-current-buffer buf
+       (erc-status-sidebar--open))))
   ((remove-hook 'erc--setup-buffer-hook #'erc-status-sidebar--open)
    (erc-status-sidebar-close 'all-frames)
    (when-let ((arg erc--module-toggle-prefix-arg)
diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el
index a36b781e04d..04ee76a9349 100644
--- a/lisp/erc/erc-track.el
+++ b/lisp/erc/erc-track.el
@@ -1,6 +1,6 @@
 ;;; erc-track.el --- Track modified channel buffers  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -161,23 +161,39 @@ The faces used are the same as used for text in the 
buffers.
 \(e.g. `erc-pal-face' is used if a pal sent a message to that channel.)"
   :type 'boolean)
 
+(defun erc-track--massage-nick-button-faces (sym val &optional set-fn)
+  "Transform VAL of face-list option SYM to have new defaults.
+Use `set'-compatible SET-FN when given.  If an update was
+performed, set the symbol property `erc-track--obsolete-faces' of
+SYM to t."
+  (let* ((changedp nil)
+         (new (mapcar
+               (lambda (f)
+                 (if (and (eq (car-safe f) 'erc-nick-default-face)
+                          (equal f '(erc-nick-default-face erc-default-face)))
+                     (progn
+                       (setq changedp t)
+                       (put sym 'erc-track--obsolete-faces t)
+                       (cons 'erc-button-nick-default-face (cdr f)))
+                   f))
+               val)))
+    (if set-fn
+        (funcall set-fn sym (if changedp new val))
+      (set-default sym (if changedp new val)))))
+
 (defcustom erc-track-faces-priority-list
   '(erc-error-face
-    (erc-nick-default-face erc-current-nick-face)
     erc-current-nick-face
     erc-keyword-face
-    (erc-nick-default-face erc-pal-face)
     erc-pal-face
     erc-nick-msg-face
     erc-direct-msg-face
     (erc-button erc-default-face)
-    (erc-nick-default-face erc-dangerous-host-face)
     erc-dangerous-host-face
     erc-nick-default-face
-    (erc-nick-default-face erc-default-face)
+    (erc-button-nick-default-face erc-default-face)
     erc-default-face
     erc-action-face
-    (erc-nick-default-face erc-fool-face)
     erc-fool-face
     erc-notice-face
     erc-input-face
@@ -188,6 +204,8 @@ be highlighted using that face.  The first matching face is 
used.
 
 Note that ERC prioritizes certain faces reserved for critical
 messages regardless of this option's value."
+  :package-version '(ERC . "5.6")
+  :set #'erc-track--massage-nick-button-faces
   :type (erc--with-dependent-type-match
          (repeat (choice face (repeat :tag "Combination" face)))
          erc-button))
@@ -209,10 +227,9 @@ setting this variable might not be very useful."
 
 (defcustom erc-track-faces-normal-list
   '((erc-button erc-default-face)
-    (erc-nick-default-face erc-dangerous-host-face)
     erc-dangerous-host-face
     erc-nick-default-face
-    (erc-nick-default-face erc-default-face)
+    (erc-button-nick-default-face erc-default-face)
     erc-default-face
     erc-action-face)
   "A list of faces considered to be part of normal conversations.
@@ -224,9 +241,26 @@ the buffer name will be highlighted using the face from the
 message.  This gives a rough indication that active conversations
 are occurring in these channels.
 
+Note that ERC makes a copy of this option when initializing the
+module.  To see your changes reflected mid-session, cycle
+\\[erc-track-mode].
+
 The effect may be disabled by setting this variable to nil."
-  :type '(repeat (choice face
-                        (repeat :tag "Combination" face))))
+  :package-version '(ERC . "5.6")
+  :set #'erc-track--massage-nick-button-faces
+  :type (erc--with-dependent-type-match
+         (repeat (choice face (repeat :tag "Combination" face)))
+         erc-button))
+
+(defvar erc-track-ignore-normal-contenders-p nil
+  "Compatibility flag to promote only exclusively new \"normal\" faces.
+When non-nil, revert to pre-5.6 behavior in which only a current
+mode-line face that both outranks and is absent from the current
+message is eligible for replacement by a fellow face from
+`erc-track-faces-normal-list' that does appear in the message.
+By extension, when enabled, never replace the current, reigning
+mode-line face if it's present in the current message.  May be
+incompatible with modules introduced after ERC 5.5.")
 
 (defcustom erc-track-position-in-mode-line 'before-modes
   "Where to show modified channel information in the mode-line.
@@ -344,6 +378,37 @@ See `erc-track-position-in-mode-line' for possible values."
 
 ;;; Shortening of names
 
+(defvar erc-track--shortened-names nil
+  "A cons of the last novel name-shortening params and the result.
+The CAR is a hash of environmental inputs such as options and
+parameters passed to `erc-track-shorten-function'.  Its effect is
+only really noticeable during batch processing.")
+
+(defvar erc-track--shortened-names-current-hash nil)
+
+(defun erc-track--shortened-names-set (_ shortened)
+  "Remember SHORTENED names with hash of contextual params."
+  (cl-assert erc-track--shortened-names-current-hash)
+  (setq erc-track--shortened-names
+        (cons erc-track--shortened-names-current-hash shortened)))
+
+(defun erc-track--shortened-names-get (channel-names)
+  "Cache CHANNEL-NAMES with various contextual parameters.
+For now, omit relevant options like `erc-track-shorten-start' and
+friends, even though they do affect the outcome, because they
+likely change too infrequently to matter over sub-second
+intervals and are unlikely to be let-bound or set locally."
+  (when-let ((hash (setq erc-track--shortened-names-current-hash
+                         (sxhash-equal (list channel-names
+                                             (buffer-list)
+                                             erc-track-shorten-function))))
+             (erc-track--shortened-names)
+             ((= hash (car erc-track--shortened-names))))
+    (cdr erc-track--shortened-names)))
+
+(gv-define-simple-setter erc-track--shortened-names-get
+                         erc-track--shortened-names-set)
+
 (defun erc-track-shorten-names (channel-names)
   "Call `erc-unique-channel-names' with the correct parameters.
 This function is a good value for `erc-track-shorten-function'.
@@ -518,6 +583,9 @@ keybindings will not do anything useful."
         (progn
           (add-hook 'window-configuration-change-hook #'erc-user-is-active)
           (add-hook 'erc-send-completed-hook #'erc-user-is-active)
+           ;; FIXME find out why this uses `erc-server-001-functions'.
+           ;; `erc-user-is-active' runs when `erc-server-connected' is
+           ;; non-nil.  But this hook usually only runs when it's nil.
           (add-hook 'erc-server-001-functions #'erc-user-is-active))
        (erc-track-add-to-mode-line erc-track-position-in-mode-line)
        (erc-update-mode-line)
@@ -528,6 +596,8 @@ keybindings will not do anything useful."
      ;; enable the tracking keybindings
      (add-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe)
      (erc-track-minor-mode-maybe))
+   (add-hook 'erc-mode-hook #'erc-track--setup)
+   (unless erc--updating-modules-p (erc-buffer-do #'erc-track--setup))
    (add-hook 'erc-networks--copy-server-buffer-functions
              #'erc-track--replace-killed-buffer))
   ;; Disable:
@@ -539,6 +609,7 @@ keybindings will not do anything useful."
                        #'erc-user-is-active)
           (remove-hook 'erc-send-completed-hook #'erc-user-is-active)
           (remove-hook 'erc-server-001-functions #'erc-user-is-active)
+           ;; FIXME remove this if unused.
           (remove-hook 'erc-timer-hook #'erc-user-is-active))
        (remove-hook 'window-configuration-change-hook
                    #'erc-window-configuration-change)
@@ -548,9 +619,12 @@ keybindings will not do anything useful."
      (remove-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe)
      (when erc-track-minor-mode
        (erc-track-minor-mode -1)))
+   (remove-hook 'erc-mode-hook #'erc-track--setup)
+   (erc-buffer-do #'erc-track--setup)
    (remove-hook 'erc-networks--copy-server-buffer-functions
                 #'erc-track--replace-killed-buffer)))
 
+;; FIXME move this above the module definition.
 (defcustom erc-track-when-inactive nil
   "Enable channel tracking even for visible buffers, if you are inactive."
   :type 'boolean
@@ -562,6 +636,51 @@ keybindings will not do anything useful."
               (erc-track-enable))
           (set sym val))))
 
+(defvar-local erc-track--normal-faces nil
+  "Local copy of `erc-track-faces-normal-list' as a hash table.")
+
+(defun erc-track--setup ()
+  "Initialize a buffer for use with the `track' module.
+If this is a server buffer or `erc-track-faces-normal-list' is
+locally bound, create a new `erc-track--normal-faces' for the
+current buffer.  Otherwise, set the local value to the server
+buffer's."
+  (if erc-track-mode
+      (let ((existing (erc-with-server-buffer erc-track--normal-faces))
+            (localp (and erc--target
+                         (local-variable-p 'erc-track-faces-normal-list)))
+            (opts '(erc-track-faces-normal-list erc-track-faces-priority-list))
+            warnp table)
+        ;; Don't bother warning users who've disabled `button'.
+        (unless (or erc--target (not (or (bound-and-true-p erc-button-mode)
+                                         (memq 'button erc-modules))))
+          (when (or localp (local-variable-p 'erc-track-faces-priority-list))
+            (dolist (opt opts)
+              (erc-track--massage-nick-button-faces opt (symbol-value opt)
+                                                    #'set)))
+          (dolist (opt opts)
+            (when (get opt 'erc-track--obsolete-faces)
+              (push opt warnp)
+              (put opt 'erc-track--obsolete-faces nil)))
+          (when warnp
+            (erc--warn-once-before-connect 'erc-track-mode
+              (if (cdr warnp) "Options " "Option ")
+              (mapconcat (lambda (o) (format "`%S'" o)) warnp " and ")
+              (if (cdr warnp) " contain" " contains")
+              " an obsolete item, %S, intended to match buttonized nicknames."
+              " ERC has changed it to %S for the current session."
+              " Please save the current value to silence this message."
+              '(erc-nick-default-face erc-default-face)
+              '(erc-button-nick-default-face erc-default-face))))
+        (when (or (null existing) localp)
+          (setq table (map-into (mapcar (lambda (f) (cons f f))
+                                        erc-track-faces-normal-list)
+                                '(hash-table :test equal :weakness value))))
+        (setq erc-track--normal-faces (or table existing))
+        (unless (or localp existing)
+          (erc-with-server-buffer (setq erc-track--normal-faces table))))
+    (kill-local-variable 'erc-track--normal-faces)))
+
 ;;; Visibility
 
 (defvar erc-buffer-activity nil
@@ -705,10 +824,13 @@ Use `erc-make-mode-line-buffer-name' to create buttons."
                                            (or (buffer-name buf)
                                                ""))
                                         buffers))
-                    (short-names (if (functionp erc-track-shorten-function)
-                                     (funcall erc-track-shorten-function
-                                              long-names)
-                                   long-names))
+                     (erc-track--shortened-names-current-hash nil)
+                     (short-names
+                      (if (functionp erc-track-shorten-function)
+                          (with-memoization
+                              (erc-track--shortened-names-get long-names)
+                            (funcall erc-track-shorten-function long-names))
+                        long-names))
                     strings)
                (while buffers
                  (when (car short-names)
@@ -766,7 +888,12 @@ instead.  This has the effect of allowing the current mode 
line
 face, if a member of `erc-track-faces-normal-list', to be
 replaced with another with lower priority face from NEW-FACES, if
 that face with highest priority in NEW-FACES is also a member of
-`erc-track-faces-normal-list'."
+`erc-track-faces-normal-list'.
+
+To put it another way, when CUR-FACE outranks all NEW-FACES and
+doesn't appear among them, it's eligible to be replaced with a
+fellow \"normal\" from NEW-FACES.  But if it does appear among
+them, it can't be replaced."
   (let ((choice (catch 'face
                   (dolist (candidate erc-track-faces-priority-list)
                     (when (or (equal candidate cur-face)
@@ -785,8 +912,55 @@ that face with highest priority in NEW-FACES is also a 
member of
               choice))
         choice))))
 
+(defvar erc-track--alt-normals-function nil
+  "A function to possibly elect a \"normal\" face.
+Called with the current incumbent and the worthiest new contender
+followed by all new contending faces and so-called \"normal\"
+faces.  See `erc-track--select-mode-line-face' for their meanings
+and expected types.  This function should return a face or nil.")
+
+(defun erc-track--select-mode-line-face (cur-face new-faces ranks normals)
+  "Return CUR-FACE or a replacement for displaying in the mode-line, or nil.
+Expect RANKS to be a list of faces and both NORMALS and the car
+of NEW-FACES to be hash tables mapping faces to non-nil values.
+Assume the latter's makeup and that of RANKS to resemble
+`erc-track-faces-normal-list' and `erc-track-faces-priority-list'.
+If NEW-FACES has a cdr, expect it to be its car's contents
+ordered from most recently seen (later in the buffer) to
+earliest.  In general, act like `erc-track-select-mode-line-face'
+except appeal to `erc-track--alt-normals-function' if it's
+non-nil, falling back on reconsidering NEW-FACES when CUR-FACE
+outranks all its members.  That is, choose the first among RANKS
+in NEW-FACES not equal to CUR-FACE.  Failing that, choose the
+first face in NEW-FACES that's also in NORMALS, assuming
+NEW-FACES has a cdr."
+  (cl-check-type erc-track-ignore-normal-contenders-p null)
+  (cl-check-type new-faces cons)
+  (when-let ((choice (catch 'face
+                       (dolist (candidate ranks)
+                         (when (or (equal candidate cur-face)
+                                   (gethash candidate (car new-faces)))
+                           (throw 'face candidate))))))
+    (or (and erc-track--alt-normals-function
+             (funcall erc-track--alt-normals-function
+                      cur-face choice new-faces normals))
+        (and (equal choice cur-face)
+             (gethash choice normals)
+             (catch 'face
+               (progn
+                 (dolist (candidate ranks)
+                   (when (and (not (equal candidate choice))
+                              (gethash candidate (car new-faces))
+                              (gethash choice normals))
+                     (throw 'face candidate)))
+                 (dolist (candidate (cdr new-faces))
+                   (when (and (not (equal candidate choice))
+                              (gethash candidate normals))
+                     (throw 'face candidate))))))
+        choice)))
+
 (defvar erc-track--skipped-msgs '(datestamp)
-  "Values of `erc-msg' text prop to ignore.")
+  "Values of `erc--msg' text prop to ignore.")
 
 (defun erc-track-modified-channels ()
   "Hook function for `erc-insert-post-hook'.
@@ -806,7 +980,7 @@ the current buffer is in `erc-mode'."
                                                  erc-track-exclude-types)
                         ;; Skip certain non-server-sent messages.
                         (and (not parsed)
-                             (erc--check-msg-prop 'erc-msg
+                             (erc--check-msg-prop 'erc--msg
                                                   erc-track--skipped-msgs))))))
        ;; If the active buffer is not visible (not shown in a
        ;; window), and not to be excluded, determine the kinds of
@@ -819,31 +993,43 @@ the current buffer is in `erc-mode'."
        ;; (in the car), change its face attribute (in the cddr) if
        ;; necessary.  See `erc-modified-channels-alist' for the
        ;; exact data structure used.
-        (let ((faces (erc-faces-in (buffer-string)))
-              (erc-track-faces-priority-list
-               `(,@erc-track--attn-faces ,@erc-track-faces-priority-list)))
-         (unless (and
-                  (or (eq erc-track-priority-faces-only 'all)
-                      (member this-channel erc-track-priority-faces-only))
-                  (not (catch 'found
-                         (dolist (f faces)
-                           (when (member f erc-track-faces-priority-list)
-                             (throw 'found t))))))
+        (when-let
+            ((faces (if erc-track-ignore-normal-contenders-p
+                        (erc-faces-in (buffer-string))
+                      (erc-track--get-faces-in-current-message)))
+             (normals erc-track--normal-faces)
+             (erc-track-faces-priority-list
+              `(,@erc-track--attn-faces ,@erc-track-faces-priority-list))
+             (ranks erc-track-faces-priority-list)
+             ((not (and
+                    (or (eq erc-track-priority-faces-only 'all)
+                        (member this-channel erc-track-priority-faces-only))
+                    (not (catch 'found
+                           (dolist (f ranks)
+                             (when (gethash f (or (car-safe faces) faces))
+                               (throw 'found t)))))))))
+          (progn ; FIXME remove `progn' on next major edit
            (if (not (assq (current-buffer) erc-modified-channels-alist))
                ;; Add buffer, faces and counts
                (setq erc-modified-channels-alist
                      (cons (cons (current-buffer)
                                  (cons
-                                   1 (erc-track-select-mode-line-face
-                                      nil faces)))
+                                   1 (if erc-track-ignore-normal-contenders-p
+                                         (erc-track-select-mode-line-face
+                                          nil faces)
+                                       (erc-track--select-mode-line-face
+                                        nil faces ranks normals))))
                            erc-modified-channels-alist))
              ;; Else modify the face for the buffer, if necessary.
              (when faces
                (let* ((cell (assq (current-buffer)
                                   erc-modified-channels-alist))
                       (old-face (cddr cell))
-                      (new-face (erc-track-select-mode-line-face
-                                  old-face faces)))
+                       (new-face (if erc-track-ignore-normal-contenders-p
+                                     (erc-track-select-mode-line-face
+                                      old-face faces)
+                                   (erc-track--select-mode-line-face
+                                    old-face faces ranks normals))))
                  (setcdr cell (cons (1+ (cadr cell)) new-face)))))
            ;; And display it
            (erc-modified-channels-display)))
@@ -872,6 +1058,30 @@ the current buffer is in `erc-mode'."
           (push cur faces)))
     faces))
 
+(defvar erc-track--face-reject-function nil
+  "Function called with face in current buffer to massage or reject.")
+
+(defun erc-track--get-faces-in-current-message ()
+  "Collect all faces in the narrowed buffer.
+Return a cons of a hash table and a list ordered from most
+recently seen to earliest seen."
+  (let ((i (text-property-not-all (point-min) (point-max) 'font-lock-face nil))
+        (seen (make-hash-table :test #'equal))
+        ;;
+        (rfaces ())
+        (faces (make-hash-table :test #'equal)))
+    (while-let ((i)
+                (cur (get-text-property i 'face)))
+      (unless (gethash cur seen)
+        (puthash cur t seen)
+        (when erc-track--face-reject-function
+          (setq cur (funcall erc-track--face-reject-function cur)))
+        (when cur
+          (push cur rfaces)
+          (puthash cur t faces)))
+      (setq i (next-single-property-change i 'font-lock-face)))
+    (cons faces rfaces)))
+
 ;;; Buffer switching
 
 (defvar erc-track-last-non-erc-buffer nil
diff --git a/lisp/erc/erc-truncate.el b/lisp/erc/erc-truncate.el
index 3350cbd13b7..4b602074ebb 100644
--- a/lisp/erc/erc-truncate.el
+++ b/lisp/erc/erc-truncate.el
@@ -1,6 +1,6 @@
 ;;; erc-truncate.el --- Functions for truncating ERC buffers  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Andreas Fuchs <asf@void.at>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -102,7 +102,7 @@ present in `erc-modules'."
           ;; Truncate at message boundary (formerly line boundary
           ;; before 5.6).
          (goto-char end)
-          (goto-char (or (erc--get-inserted-msg-bounds 'beg)
+          (goto-char (or (erc--get-inserted-msg-beg end)
                          (pos-bol)))
          (setq end (point))
          ;; try to save the current buffer using
diff --git a/lisp/erc/erc-xdcc.el b/lisp/erc/erc-xdcc.el
index 3dc08de4d10..b592c84e346 100644
--- a/lisp/erc/erc-xdcc.el
+++ b/lisp/erc/erc-xdcc.el
@@ -1,6 +1,6 @@
 ;;; erc-xdcc.el --- XDCC file-server support for ERC  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2003-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 616129bf780..ef047201251 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -1,6 +1,6 @@
 ;;; erc.el --- An Emacs Internet Relay Chat client  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Alexander L. Belikoff <alexander@belikoff.net>
 ;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -13,7 +13,7 @@
 ;;               Michael Olson (mwolson@gnu.org)
 ;;               Kelvin White (kwhite@gnu.org)
 ;; Version: 5.6-git
-;; Package-Requires: ((emacs "27.1") (compat "29.1.4.3"))
+;; Package-Requires: ((emacs "27.1") (compat "29.1.4.4"))
 ;; Keywords: IRC, chat, client, Internet
 ;; URL: https://www.gnu.org/software/emacs/erc.html
 
@@ -154,26 +154,27 @@ visiting and editing inserted messages.  Modules should 
align
 their markers accordingly.  The following properties have meaning
 as of ERC 5.6:
 
- - `erc-msg': a symbol, guaranteed present; values include:
-   `msg', signifying a `PRIVMSG' or an incoming `NOTICE';
-   `unknown', a fallback for `erc-display-message'; a catalog
-    key, such as `s401' or `finished'; an `erc-display-message'
-    TYPE parameter, like `notice'
+ - `erc--msg': a symbol, guaranteed present; possible values
+    include `unknown', a fallback used by `erc-display-message'; a
+    catalog key, such as `s401' or `finished'; an
+   `erc-display-message' TYPE parameter, like `notice'
 
- - `erc-cmd': a message's associated IRC command, as read by
+ - `erc--cmd': a message's associated IRC command, as read by
    `erc--get-eq-comparable-cmd'; currently either a symbol, like
    `PRIVMSG', or a number, like 5, which represents the numeric
     \"005\"; absent on \"local\" messages, such as simple warnings
     and help text, and on outgoing messages unless echoed back by
     the server (assuming future support)
 
- - `erc-ctcp': a CTCP command, like `ACTION'
+ - `erc--spkr': a string, the nick of the person speaking
 
- - `erc-ts': a timestamp, possibly provided by the server; as of
+ - `erc--ctcp': a CTCP command, like `ACTION'
+
+ - `erc--ts': a timestamp, possibly provided by the server; as of
     5.6, a ticks/hertz pair on Emacs 29 and above, and a \"list\"
     type otherwise; managed by the `stamp' module
 
- - `erc-ephemeral': a symbol prefixed by or matching a module
+ - `erc--ephemeral': a symbol prefixed by or matching a module
     name; indicates to other modules and members of modification
     hooks that the current message should not affect stateful
     operations, such as recording a channel's most recent speaker
@@ -191,10 +192,6 @@ front shadow any that follow.  Ignored when 
`erc--msg-props' is
 already non-nil.")
 
 ;; Forward declarations
-(defvar tabbar--local-hlf)
-(defvar motif-version-string)
-(defvar gtk-version-string)
-
 (declare-function decoded-time-period "time-date" (time))
 (declare-function iso8601-parse-duration "iso8601" (string))
 (declare-function word-at-point "thingatpt" (&optional no-properties))
@@ -389,6 +386,16 @@ If nil, only \"> \" will be shown."
           (const "PART")
           (const "QUIT")
           (const "MODE")
+          (const :tag "Away notices (RPL_AWAY 301)" "301")
+          (const :tag "Self back notice (REP_UNAWAY 305)" "305")
+          (const :tag "Self away notice (REP_NOWAWAY 306)" "306")
+          (const :tag "Channel modes on join (RPL_CHANNELMODEIS 324)" "324")
+          (const :tag "Channel creation time (RPL_CREATIONTIME 329)" "329")
+          (const :tag "Channel no-topic on join (RPL_NOTOPIC 331)" "331")
+          (const :tag "Channel topic on join (RPL_TOPIC 332)" "332")
+          (const :tag "Topic author and time on join (RPL_TOPICWHOTIME 333)" 
"333")
+          (const :tag "Invitation success notice (RPL_INVITING 341)" "341")
+          (const :tag "Channel member names (353 RPL_NAMEREPLY)" "353")
           (repeat :inline t :tag "Others" (string :tag "IRC Message Type"))))
 
 (defcustom erc-hide-list nil
@@ -477,13 +484,14 @@ Functions are passed a buffer as the first argument."
   :group 'erc-hooks
   :type 'hook)
 
-
-(defvar-local erc-channel-users nil
+(defvaralias 'erc-channel-users 'erc-channel-members)
+(defvar-local erc-channel-members nil
   "Hash table of members in the current channel.
-It associates nicknames with cons cells of the form:
-\(USER . MEMBER-DATA) where USER is a pointer to an
-erc-server-user struct, and MEMBER-DATA is a pointer to an
-erc-channel-user struct.")
+It associates nicknames with cons cells of the form
+\(SERVER-USER . MEMBER-DATA), where SERVER-USER is a
+`erc-server-user' object and MEMBER-DATA is a `erc-channel-user'
+object.  Convenient abbreviations for these two components are
+`susr' and `cusr', along with `cmem' for the pair.")
 
 (defvar-local erc-server-users nil
   "Hash table of users on the current server.
@@ -600,6 +608,53 @@ Removes all users in the current channel.  This is called 
by
              erc-channel-users)
     (clrhash erc-channel-users)))
 
+(defmacro erc--define-channel-user-status-compat-getter (name c d)
+  "Define a gv getter for historical `erc-channel-user' status slot NAME.
+Expect NAME to be a string, C to be its traditionally associated
+letter, and D to be its fallback power-of-2 integer for non-ERC
+buffers."
+  `(defun ,(intern (concat "erc-channel-user-" name)) (u)
+     ,(format "Get equivalent of pre-5.6 `%s' slot for `erc-channel-user'."
+              name)
+     (declare (gv-setter (lambda (v)
+                           (macroexp-let2 nil v v
+                             (,'\`(let ((val (erc-channel-user-status ,',u))
+                                        (n (or (erc--get-prefix-flag ,c) ,d)))
+                                    (setf (erc-channel-user-status ,',u)
+                                          (if ,',v
+                                              (logior val n)
+                                            (logand val (lognot n))))
+                                    ,',v))))))
+     (let ((n (or (erc--get-prefix-flag ,c) ,d)))
+       (= n (logand n (erc-channel-user-status u))))))
+
+(erc--define-channel-user-status-compat-getter "voice"  ?v 1)
+(erc--define-channel-user-status-compat-getter "halfop" ?h 2)
+(erc--define-channel-user-status-compat-getter "op"     ?o 4)
+(erc--define-channel-user-status-compat-getter "admin"  ?a 8)
+(erc--define-channel-user-status-compat-getter "owner"  ?q 16)
+
+;; This is a generalized version of the compat-oriented getters above.
+(defun erc--cusr-status-p (nick-or-cusr letter)
+  "Return non-nil if NICK-OR-CUSR has channel membership status LETTER."
+  (and-let* ((cusr (or (and (erc-channel-user-p nick-or-cusr) nick-or-cusr)
+                       (cdr (erc-get-channel-member nick-or-cusr))))
+             (n (erc--get-prefix-flag letter)))
+    (= n (logand n (erc-channel-user-status cusr)))))
+
+(defun erc--cusr-change-status (nick-or-cusr letter enablep &optional resetp)
+  "Add or remove membership status associated with LETTER for NICK-OR-CUSR.
+With RESETP, clear the user's status info completely.  If ENABLEP
+is non-nil, add the status value associated with LETTER."
+  (when-let ((cusr (or (and (erc-channel-user-p nick-or-cusr) nick-or-cusr)
+                       (cdr (erc-get-channel-member nick-or-cusr))))
+             (n (erc--get-prefix-flag letter)))
+    (cl-callf (lambda (v)
+                (if resetp
+                    (if enablep n 0)
+                  (if enablep (logior v n) (logand v (lognot n)))))
+        (erc-channel-user-status cusr))))
+
 (defun erc-channel-user-owner-p (nick)
   "Return non-nil if NICK is an owner of the current channel."
   (and nick
@@ -1138,7 +1193,13 @@ user after \"/PART\"."
 ;; Hooks
 
 (defgroup erc-hooks nil
-  "Hook variables for fancy customizations of ERC."
+  "Hooks for ERC.
+Users of the interactive client should be aware that many of
+these hooks have names predating the modern convention of
+conveying abnormality via the \"-function\" suffix.  Users should
+likewise be aware that built-in and third-party modules use these
+hooks as well, and some of their variables may be buffer-local in
+particular sessions and/or `let'-bound for spells."
   :group 'erc)
 
 (defcustom erc-mode-hook nil
@@ -1148,9 +1209,8 @@ user after \"/PART\"."
   :options '(erc-add-scroll-to-bottom))
 
 (defcustom erc-timer-hook nil
-  "Put functions which should get called more or less periodically here.
-The idea is that servers always play ping pong with the client, and so there
-is no need for any idle-timer games with Emacs."
+  "Abnormal hook run after each response handler.
+Called with a float returned from `erc-current-time'."
   :group 'erc-hooks
   :type 'hook)
 
@@ -1185,25 +1245,30 @@ anyway."
 (make-obsolete-variable 'erc-send-pre-hook 'erc-pre-send-functions "27.1")
 
 (defcustom erc-pre-send-functions nil
-  "Special hook run to possibly alter the string that is sent.
-The functions are called with one argument, an `erc-input' struct,
-and should alter that struct.
+  "Special hook to possibly alter the string to send and insert.
+ERC calls the member functions with one argument, an `erc-input'
+struct instance to modify as needed.
 
-The struct has three slots:
+The struct has five slots:
 
-  `string': The current input string.
-  `insertp': Whether the string should be inserted into the erc buffer.
-  `sendp': Whether the string should be sent to the irc server.
-  `refoldp': Whether the string should be re-split per protocol limits.
+  `string': String to send, originally from prompt input.
+  `insertp': Whether a string should be inserted in the buffer.
+  `sendp': Whether `string' should be sent to the IRC server.
+  `substxt': String to display (but not send) instead of `string'.
+  `refoldp': Whether to re-split `string' per protocol limits.
 
 This hook runs after protocol line splitting has taken place, so
-the value of `string' is originally \"pre-filled\".  If you need
-ERC to refill the entire payload before sending it, set the
-`refoldp' slot to a non-nil value.  Preformatted text and encoded
-subprotocols should probably be handled manually."
-  :group 'erc
-  :type 'hook
-  :version "27.1")
+the value of `string' comes \"pre-split\" according to the option
+`erc-split-line-length'.  If you need ERC to refill the entire
+payload before sending it, set the `refoldp' slot to a non-nil
+value.  Note that this refilling is only a convenience, and
+modules with special needs, such as preserving \"preformatted\"
+text or encoding for subprotocol \"tunneling\", should handle
+splitting manually and possibly also specify replacement text to
+display via the `substxt' slot."
+  :package-version '(ERC . "5.3")
+  :group 'erc-hooks
+  :type 'hook)
 
 (define-obsolete-variable-alias 'erc--pre-send-split-functions
   'erc--input-review-functions "30.1")
@@ -1247,8 +1312,8 @@ of `erc-insert-this' is t.
 
 ERC runs this hook with the buffer narrowed to the bounds of the
 inserted message plus a trailing newline.  Built-in modules place
-their hook members at depths between 20 and 80, with those from
-the stamp module always running last.  Use the functions
+their hook members in two depth ranges: the first between -80 and
+-20 and the second between 20 and 80.  Use the functions
 `erc-find-parsed-property' and `erc-get-parsed-vector' to locate
 and extract the `erc-response' object for the inserted message."
   :group 'erc-hooks
@@ -1450,9 +1515,8 @@ See also `erc-show-my-nick'."
 
 ;; Debugging support
 
-(defvar erc-log-p nil
-  "When set to t, generate debug messages in a separate debug buffer.")
-
+;; FIXME if this variable plays some role, indicate that here.
+;; Otherwise, deprecate.
 (defvar erc-debug-log-file (expand-file-name "ERC.debug")
   "Debug log file name.")
 
@@ -1467,7 +1531,7 @@ Bound to local variables from an existing (logical) 
session's
 buffer during local-module setup and `erc-mode-hook' activation.")
 
 (defmacro erc--restore-initialize-priors (mode &rest vars)
-  "Restore local VARS for MODE from a previous session."
+  "Restore local VARS for local minor MODE from a previous session."
   (declare (indent 1))
   (let ((priors (make-symbol "priors"))
         (initp (make-symbol "initp"))
@@ -1477,6 +1541,8 @@ buffer during local-module setup and `erc-mode-hook' 
activation.")
       (push `(,k (if ,initp (alist-get ',k ,priors) ,(pop vars))) forms))
     `(let* ((,priors (or erc--server-reconnecting erc--target-priors))
             (,initp (and ,priors (alist-get ',mode ,priors))))
+       (unless (local-variable-if-set-p ',mode)
+         (error "Not a local minor mode var: %s" ',mode))
        (setq ,@(mapcan #'identity (nreverse forms))))))
 
 (defun erc--target-from-string (string)
@@ -1661,7 +1727,7 @@ Defaults to the server buffer."
 (defconst erc-default-server "irc.libera.chat"
   "IRC server to use if it cannot be detected otherwise.")
 
-(defconst erc-default-port 6667
+(defvar erc-default-port 6667
   "IRC port to use if it cannot be detected otherwise.")
 
 (defconst erc-default-port-tls 6697
@@ -2119,13 +2185,17 @@ buffer rather than a server buffer.")
       (cl-pushnew mod (if (get mod 'erc--module) built-in third-party)))
     `(,@(sort built-in #'string-lessp) ,@(nreverse third-party))))
 
+;;;###autoload(custom-autoload 'erc-modules "erc")
+
 (defcustom erc-modules '( autojoin button completion fill imenu irccontrols
                           list match menu move-to-prompt netsplit
                           networks readonly ring stamp track)
-  "A list of modules which ERC should enable.
-If you set the value of this without using `customize' remember to call
-\(erc-update-modules) after you change it.  When using `customize', modules
-removed from the list will be disabled."
+  "Modules to enable while connecting.
+When modifying this option in lisp code, use a Custom-friendly
+facilitator, like `setopt', or call `erc-update-modules'
+afterward.  This ensures a consistent ordering and disables
+removed modules.  It also gives packages access to the hook
+`erc-before-connect'."
   :get (lambda (sym)
          ;; replace outdated names with their newer equivalents
          (erc-migrate-modules (symbol-value sym)))
@@ -2189,7 +2259,7 @@ removed from the list will be disabled."
            move-to-prompt)
     (const :tag "netsplit: Detect netsplits" netsplit)
     (const :tag "networks: Provide data about IRC networks" networks)
-    (const :tag "nickbar: Show nicknames in a dyamic side window" nickbar)
+    (const :tag "nickbar: Show nicknames in a dynamic side window" nickbar)
     (const :tag "nicks: Uniquely colorize nicknames in target buffers" nicks)
     (const :tag "noncommands: Deprecated. See module `command-indicator'."
            noncommands)
@@ -2512,8 +2582,8 @@ Returns the buffer for the given server or channel."
           (when erc-log-p
             (get-buffer-create (concat "*ERC-DEBUG: " server "*"))))
 
-    (erc-determine-parameters server port nick full-name user passwd)
     (erc--initialize-markers old-point continued-session)
+    (erc-determine-parameters server port nick full-name user passwd)
     (save-excursion (run-mode-hooks)
                     (dolist (mod (car delayed-modules)) (funcall mod +1))
                     (dolist (var (cdr delayed-modules)) (set var nil)))
@@ -2607,12 +2677,15 @@ typically the same as that reported by 
`erc-current-nick'."
 
 ;;;###autoload
 (defun erc-select-read-args ()
-  "Prompt the user for values of nick, server, port, and password.
-With prefix arg, also prompt for user and full name."
+  "Prompt for connection parameters and return them in a plist.
+By default, collect `:server', `:port', `:nickname', and
+`:password'.  With a non-nil prefix argument, also prompt for
+`:user' and `:full-name'.  Also return various environmental
+properties needed by entry-point commands, like `erc-tls'."
   (let* ((input (let ((d (erc-compute-server)))
                   (if erc--prompt-for-server-function
                       (funcall erc--prompt-for-server-function)
-                    (read-string (format "Server or URL (default is %S): " d)
+                    (read-string (format-prompt "Server or URL" d)
                                  nil 'erc-server-history-list d))))
          ;; For legacy reasons, also accept a URL without a scheme.
          (url (url-generic-parse-url (erc--ensure-url input)))
@@ -2621,27 +2694,27 @@ With prefix arg, also prompt for user and full name."
          (port (or (url-portspec url)
                    (erc-compute-port
                     (let ((d (erc-compute-port sp))) ; may be a string
-                      (read-string (format "Port (default is %s): " d)
+                      (read-string (format-prompt "Port" d)
                                    nil nil d)))))
          ;; Trust the user not to connect twice accidentally.  We
          ;; can't use `erc-already-logged-in' to check for an existing
          ;; connection without modifying it to consider USER and PASS.
          (nick (or (url-user url)
                    (let ((d (erc-compute-nick)))
-                     (read-string (format "Nickname (default is %S): " d)
+                     (read-string (format-prompt "Nickname" d)
                                   nil 'erc-nick-history-list d))))
          (user (and current-prefix-arg
                     (let ((d (erc-compute-user (url-user url))))
-                      (read-string (format "User (default is %S): " d)
+                      (read-string (format-prompt "User" d)
                                    nil nil d))))
          (full (and current-prefix-arg
                     (let ((d (erc-compute-full-name (url-user url))))
-                      (read-string (format "Full name (default is %S): " d)
+                      (read-string (format-prompt "Full name" d)
                                    nil nil d))))
          (passwd (let* ((p (with-suppressed-warnings ((obsolete erc-password))
                              (or (url-password url) erc-password)))
                         (m (if p
-                               (format "Server password (default is %S): " p)
+                               (format-prompt "Server password" p)
                              "Server password (optional): ")))
                    (if erc-prompt-for-password (read-passwd m nil p) p)))
          (opener (and (or sp (eql port erc-default-port-tls)
@@ -2662,7 +2735,7 @@ With prefix arg, also prompt for user and full name."
       (setq passwd nil))
     `( :server ,server :port ,port :nick ,nick ,@(and user `(:user ,user))
        ,@(and passwd `(:password ,passwd)) ,@(and full `(:full-name ,full))
-       ,@(and env `(&interactive-env ,env)))))
+       ,@(and env `(--interactive-env-- ,env)))))
 
 (defmacro erc--with-entrypoint-environment (env &rest body)
   "Run BODY with bindings from ENV alist."
@@ -2691,30 +2764,40 @@ With prefix arg, also prompt for user and full name."
                     (full-name (erc-compute-full-name))
                     id
                     ;; Used by interactive form
-                    ((&interactive-env --interactive-env--)))
-  "ERC is a powerful, modular, and extensible IRC client.
-This function is the main entry point for ERC.
-
-It allows selecting connection parameters, and then starts ERC.
-
-Non-interactively, it takes the keyword arguments
-   (server (erc-compute-server))
-   (port   (erc-compute-port))
-   (nick   (erc-compute-nick))
-   (user   (erc-compute-user))
-   password
-   (full-name (erc-compute-full-name))
-   id
-
-That is, if called with
+                    ((--interactive-env-- --interactive-env--)))
+  "Connect to an Internet Relay Chat SERVER on a non-TLS PORT.
+Use NICK and USER, when non-nil, to inform the IRC commands of
+the same name, possibly factoring in a non-nil FULL-NAME as well.
+When PASSWORD is non-nil, also send an opening server password
+via the \"PASS\" command.  Interactively, prompt for SERVER,
+PORT, NICK, and PASSWORD, along with USER and FULL-NAME when
+given a prefix argument.  Non-interactively, expect the rarely
+needed ID parameter, when non-nil, to be a symbol or a string for
+naming the server buffer and identifying the connection
+unequivocally.  (See Info node `(erc) Connecting' for details
+about all mentioned parameters.)
+
+Together with `erc-tls', this command serves as the main entry
+point for ERC, the powerful, modular, and extensible IRC client.
+Non-interactively, both commands accept the following keyword
+arguments, with their defaults supplied by the indicated
+\"compute\" functions:
+
+  :server    `erc-compute-server'
+  :port      `erc-compute-port'
+  :nick      `erc-compute-nick'
+  :user      `erc-compute-user'
+  :password   N/A
+  :full-name `erc-compute-full-name'
+  :id'        N/A
+
+For example, when called in the following manner
 
    (erc :server \"irc.libera.chat\" :full-name \"J. Random Hacker\")
 
-then the server and full-name will be set to those values,
-whereas `erc-compute-port' and `erc-compute-nick' will be invoked
-for the values of the other parameters.
-
-See `erc-tls' for the meaning of ID.
+ERC assigns SERVER and FULL-NAME the associated keyword values
+and defers to `erc-compute-port', `erc-compute-user', and
+`erc-compute-nick' for those respective parameters.
 
 \(fn &key SERVER PORT NICK USER PASSWORD FULL-NAME ID)"
   (interactive (let ((erc--display-context `((erc-interactive-display . erc)
@@ -2740,51 +2823,26 @@ See `erc-tls' for the meaning of ID.
                         client-certificate
                         id
                         ;; Used by interactive form
-                        ((&interactive-env --interactive-env--)))
-  "ERC is a powerful, modular, and extensible IRC client.
-This function is the main entry point for ERC over TLS.
-
-It allows selecting connection parameters, and then starts ERC
-over TLS.
-
-Non-interactively, it takes the keyword arguments
-   (server (erc-compute-server))
-   (port   (erc-compute-port))
-   (nick   (erc-compute-nick))
-   (user   (erc-compute-user))
-   password
-   (full-name (erc-compute-full-name))
-   client-certificate
-   id
-
-That is, if called with
-
-   (erc-tls :server \"irc.libera.chat\" :full-name \"J. Random Hacker\")
-
-then the server and full-name will be set to those values,
-whereas `erc-compute-port' and `erc-compute-nick' will be invoked
-for the values of their respective parameters.
-
-CLIENT-CERTIFICATE, if non-nil, should either be a list where the
-first element is the certificate key file name, and the second
-element is the certificate file name itself, or t, which means
-that `auth-source' will be queried for the key and the
-certificate.  Authenticating using a TLS client certificate is
-also referred to as \"CertFP\" (Certificate Fingerprint)
-authentication by various IRC networks.
-
-Example usage:
+                        ((--interactive-env-- --interactive-env--)))
+  "Connect to an IRC server over a TLS-encrypted connection.
+Interactively, prompt for SERVER, PORT, NICK, and PASSWORD, along
+with USER and FULL-NAME when given a prefix argument.
+Non-interactively, also accept a CLIENT-CERTIFICATE, which should
+be a list containing the file name of the certificate's key
+followed by that of the certificate itself.  Alternatively,
+accept a value of t instead of a list, to tell ERC to query
+`auth-source' for the certificate's details.
+
+Example client certificate (CertFP) usage:
 
     (erc-tls :server \"irc.libera.chat\" :port 6697
              :client-certificate
              \\='(\"/home/bandali/my-cert.key\"
                \"/home/bandali/my-cert.crt\"))
 
-When present, ID should be a symbol or a string to use for naming
-the server buffer and identifying the connection unequivocally.
-See Info node `(erc) Network Identifier' for details.  Like
-CLIENT-CERTIFICATE, this parameter cannot be specified
-interactively.
+See the alternative entry-point command `erc' as well as Info
+node `(erc) Connecting' for a fuller description of the various
+parameters, like ID.
 
 \(fn &key SERVER PORT NICK USER PASSWORD FULL-NAME CLIENT-CERTIFICATE ID)"
   (interactive
@@ -2822,12 +2880,15 @@ PARAMETERS should be a sequence of keywords and values, 
per
 
 (defun erc-open-socks-tls-stream (name buffer host service &rest parameters)
   "Connect to an IRC server via SOCKS proxy over TLS.
-Bind `erc-server-connect-function' to this function around calls
-to `erc-tls'.  See `erc-open-network-stream' for the meaning of
-NAME and BUFFER.  HOST should be a \".onion\" URL, SERVICE a TLS
-port number, and PARAMETERS a sequence of key/value pairs, per
-`open-network-stream'.  See Info node `(erc) SOCKS' for more
-info."
+Defer to the `socks' and `gnutls' libraries to make the actual
+connection and perform TLS negotiation.  Expect SERVICE to be a
+TLS port number and that the plist PARAMETERS contains a
+`:client-certificate' pair when necessary.  Otherwise, assume the
+arguments NAME, BUFFER, and HOST to be acceptable to
+`open-network-stream' and that users know to check out
+`erc-server-connect-function' and Info node `(erc) SOCKS' for
+more info, including an important example of how to \"wrap\" this
+function with SOCKS credentials."
   (require 'gnutls)
   (require 'socks)
   (let ((proc (socks-open-network-stream name buffer host service))
@@ -2847,6 +2908,15 @@ message instead, to make debugging easier."
     (apply #'message args)
     (beep)))
 
+(defvar erc--warnings-buffer-name nil
+  "Name of possibly existing alternate warnings buffer for unit tests.")
+
+(defun erc--lwarn (type level format-string &rest args)
+  "Issue a warning of TYPE and LEVEL with FORMAT-STRING and ARGS."
+  (let ((message (substitute-command-keys
+                  (apply #'format-message format-string args))))
+    (display-warning type message level erc--warnings-buffer-name)))
+
 ;;; Debugging the protocol
 
 (defvar erc-debug-irc-protocol-time-format "%FT%T.%6N%z "
@@ -3004,23 +3074,40 @@ target, and an `erc-server-send' FORCE flag.")
 ;; Sending and displaying are provided separately to afford modules
 ;; more flexibility, e.g., to forgo displaying on the way out when
 ;; expecting the server to echo messages back and/or to associate
-;; outgoing messages with IDs generated for `erc-ephemeral'
+;; outgoing messages with IDs generated for `erc--ephemeral'
 ;; placeholders.
 (defun erc--send-action-perform-ctcp (target string force)
   "Send STRING to TARGET, possibly immediately, with FORCE."
   (erc-send-ctcp-message target (format "ACTION %s" string) force))
 
+(defvar erc--use-language-catalog-for-ctcp-action-p nil
+  "When non-nil, use `ACTION' entry from language catalog for /ME's.
+Otherwise, use `ctcp-action' or `ctcp-action-input' from the
+internal `-speaker' catalog.  This is an escape hatch to restore
+pre-5.6 behavior for the `font-lock-face' property of incoming
+and outgoing \"CTCP ACTION\" messages, whose pre-buttonized state
+was a single interval of `erc-input-face' or `erc-action-face'.
+Newer modules, like `fill-wrap' and `nicks', are incompatible with
+this format style.  If you use this, please ask ERC to expose it
+as a public variable via \\[erc-bug] or similar.")
+
 (defun erc--send-action-display (string)
-  "Display STRING as an outgoing \"CTCP ACTION\" message."
+  "Display STRING as an outgoing \"CTCP ACTION\" message.
+Propertize the message according to the compatibility flag
+`erc--use-language-catalog-for-ctcp-action-p'."
   ;; Allow hooks acting on inserted PRIVMSG and NOTICES to process us.
-  (let ((erc--msg-prop-overrides `((erc-msg . msg)
-                                   (erc-ctcp . ACTION)
+  (let ((erc--msg-prop-overrides `((erc--ctcp . ACTION)
                                    ,@erc--msg-prop-overrides))
         (nick (erc-current-nick)))
-    (setq nick (propertize nick 'erc-speaker nick
-                           'font-lock-face 'erc-my-nick-face))
-    (erc-display-message nil '(t action input) (current-buffer)
-                         'ACTION ?n nick ?a string ?u "" ?h "")))
+    (if erc--use-language-catalog-for-ctcp-action-p
+        (progn (erc--ensure-spkr-prop nick)
+               (erc-display-message nil 'input (current-buffer) 'ACTION
+                                    ?n (propertize nick 'erc--speaker nick)
+                                    ?a string ?u "" ?h ""))
+      (let ((erc-current-message-catalog erc--message-speaker-catalog))
+        (erc-display-message nil nil (current-buffer) 'ctcp-action-input
+                             ?p (erc-get-channel-membership-prefix nick)
+                             ?n (erc--speakerize-nick nick) ?m string)))))
 
 (defun erc--send-action (target string force)
   "Display STRING, then send to TARGET as a \"CTCP ACTION\" message."
@@ -3029,6 +3116,21 @@ target, and an `erc-server-send' FORCE flag.")
 
 ;; Display interface
 
+(defun erc--ensure-spkr-prop (nick &optional overrides)
+  "Add NICK as `erc--spkr' to the current \"msg props\" environment.
+Prefer `erc--msg-props' over `erc--msg-prop-overrides' when both
+are available.  Also include any members of the alist OVERRIDES,
+when present.  Assume NICK itself to be free of any text props,
+and return it."
+  (cond (erc--msg-props
+         (puthash 'erc--spkr nick erc--msg-props)
+         (dolist (entry overrides)
+           (puthash (car entry) (cdr entry) erc--msg-props)))
+        (erc--msg-prop-overrides
+         (setq erc--msg-prop-overrides
+               `((erc--spkr . ,nick) ,@overrides ,@erc--msg-prop-overrides))))
+  nick)
+
 (defun erc-string-invisible-p (string)
   "Check whether STRING is invisible or not.
 I.e. any char in it has the `invisible' property set."
@@ -3136,34 +3238,45 @@ stored value.  Otherwise, return the stored value."
              (v (gethash prop erc--msg-props)))
     (if (consp val) (memq v val) (if val (eq v val) v))))
 
-(defmacro erc--get-inserted-msg-bounds (&optional only point)
-  "Return the bounds of a message in an ERC buffer.
-Return ONLY one side when the first arg is `end' or `beg'.  With
-POINT, search from POINT instead of `point'."
-  ;; TODO add edebug spec.
-  `(let* ((point ,(or point '(point)))
-          (at-start-p (get-text-property point 'erc-msg)))
-     (and-let*
-         (,@(and (member only '(nil beg 'beg))
-                 '((b (or (and at-start-p point)
-                          (and-let*
-                              ((p (previous-single-property-change point
-                                                                   'erc-msg)))
-                            (if (= p (1- point))
-                                (if (get-text-property p 'erc-msg) p (1- p))
-                              (1- p)))))))
-          ,@(and (member only '(nil end 'end))
-                 '((e (1- (next-single-property-change
-                           (if at-start-p (1+ point) point)
-                           'erc-msg nil erc-insert-marker))))))
-       ,(pcase only
-          ('(quote beg) 'b)
-          ('(quote end) 'e)
-          (_ '(cons b e))))))
+(defmacro erc--get-inserted-msg-beg-at (point at-start-p)
+  (macroexp-let2* nil ((point point)
+                       (at-start-p at-start-p))
+    `(or (and ,at-start-p ,point)
+         (and-let* ((p (previous-single-property-change ,point 'erc--msg)))
+           (if (and (= p (1- ,point)) (get-text-property p 'erc--msg))
+               p
+             (1- p))))))
+
+(defmacro erc--get-inserted-msg-end-at (point at-start-p)
+  (macroexp-let2 nil point point
+    `(1- (next-single-property-change (if ,at-start-p (1+ ,point) ,point)
+                                      'erc--msg nil erc-insert-marker))))
+
+(defun erc--get-inserted-msg-beg (&optional point)
+  "Maybe return the start of message in an ERC buffer."
+  (erc--get-inserted-msg-beg-at (or point (setq point (point)))
+                                (get-text-property point 'erc--msg)))
+
+(defun erc--get-inserted-msg-end (&optional point)
+  "Return the end of message in an ERC buffer.
+Include any trailing white space before final newline.  Expect
+POINT to be less than `erc-insert-marker', and don't bother
+considering `erc--insert-marker', for now."
+  (erc--get-inserted-msg-end-at (or point (setq point (point)))
+                                (get-text-property point 'erc--msg)))
+
+(defun erc--get-inserted-msg-bounds (&optional point)
+  "Return bounds of message at POINT in an ERC buffer when found.
+Search from POINT, when non-nil, instead of `point'.  Return nil
+if not found."
+  (let ((at-start-p (get-text-property (or point (setq point (point)))
+                                       'erc--msg)))
+    (and-let* ((b (erc--get-inserted-msg-beg-at point at-start-p)))
+      (cons b (erc--get-inserted-msg-end-at point at-start-p)))))
 
 (defun erc--get-inserted-msg-prop (prop)
   "Return the value of text property PROP for some message at point."
-  (and-let* ((stack-pos (erc--get-inserted-msg-bounds 'beg)))
+  (and-let* ((stack-pos (erc--get-inserted-msg-beg (point))))
     (get-text-property stack-pos prop)))
 
 (defmacro erc--with-inserted-msg (&rest body)
@@ -3184,12 +3297,12 @@ If END is a marker, possibly update its position."
     (set-marker end (min erc-insert-marker end)))
   (save-excursion
     (goto-char beg)
-    (let ((b (if (get-text-property (point) 'erc-msg)
+    (let ((b (if (get-text-property (point) 'erc--msg)
                  (point)
-               (next-single-property-change (point) 'erc-msg nil end))))
+               (next-single-property-change (point) 'erc--msg nil end))))
       (while-let ((b)
                   ((< b end))
-                  (e (next-single-property-change (1+ b) 'erc-msg nil end)))
+                  (e (next-single-property-change (1+ b) 'erc--msg nil end)))
         (save-restriction
           (narrow-to-region b e)
           (funcall fn))
@@ -3197,6 +3310,21 @@ If END is a marker, possibly update its position."
   (unless (eq end erc-insert-marker)
     (set-marker end nil)))
 
+(defvar erc--insert-invisible-as-intangible-p nil
+  "When non-nil, ensure certain invisible messages are also intangible.
+That is, single out any message inserted via `erc-insert-line'
+that lacks a trailing newline but has a t-valued `invisible'
+property anywhere along its length, and ensure it's both
+`invisible' t and `intangible' t throughout.  Note that this is
+merely an escape hatch for accessing aberrant pre-5.6 behavior
+that ERC considers a bug because it applies a practice described
+as obsolete in the manual, and it does so heavy-handedly.  That
+the old behavior only acted when the input lacked a trailing
+newline was likely accidental but is ultimately incidental.  See
+info node `(elisp) Special Properties' for specifics.  Beware
+that this flag and the behavior it restores may disappear at any
+time, so if you need them, please let ERC know with \\[erc-bug].")
+
 (defvar erc--insert-line-function nil
   "When non-nil, an alterntive to `insert' for inserting messages.")
 
@@ -3225,13 +3353,15 @@ preformatted or anticipated by third-party members of 
the various
 modification hooks)."
   (when string
     (with-current-buffer (or buffer (process-buffer erc-server-process))
-      (let ((insert-position (marker-position erc-insert-marker)))
-        (let ((string string) ;; FIXME! Can this be removed?
-              (buffer-undo-list t)
+      (let (insert-position)
+        ;; Initialize ^ below to thwart rogue `erc-insert-pre-hook'
+        ;; members that dare to modify the buffer's length.
+        (let ((buffer-undo-list t)
               (inhibit-read-only t))
-          (unless (string-match "\n$" string)
+          (unless (string-suffix-p "\n" string)
             (setq string (concat string "\n"))
-            (when (erc-string-invisible-p string)
+            (when (and erc--insert-invisible-as-intangible-p
+                       (erc-string-invisible-p string))
               (erc-put-text-properties 0 (length string)
                                        '(invisible intangible) string)))
           (erc-log (concat "erc-display-message: " string
@@ -3267,7 +3397,7 @@ modification hooks)."
                   (let ((props (if erc--msg-props
                                    (erc--order-text-properties-from-hash
                                     erc--msg-props)
-                                 '(erc-msg unknown))))
+                                 '(erc--msg unknown))))
                     (add-text-properties (point-min) (1+ (point-min)) props)))
                 (erc--refresh-prompt)))))
         (run-hooks 'erc-insert-done-hook)
@@ -3340,8 +3470,8 @@ the old pattern (erc-display-line (erc-make-notice) 
my-buffer) as
 being equivalent to a `erc-display-message' TYPE of `notice'."
   (let ((erc--msg-prop-overrides erc--msg-prop-overrides))
     (when (eq 'erc-notice-face (get-text-property 0 'font-lock-face string))
-      (unless (assq 'erc-msg erc--msg-prop-overrides)
-        (push '(erc-msg . notice) erc--msg-prop-overrides)))
+      (unless (assq 'erc--msg erc--msg-prop-overrides)
+        (push '(erc--msg . notice) erc--msg-prop-overrides)))
     (erc-display-message nil nil buffer string)))
 
 (defvar erc--merge-text-properties-p nil
@@ -3351,12 +3481,14 @@ being equivalent to a `erc-display-message' TYPE of 
`notice'."
 ;; values and optionally dispense archetypal constants in their place
 ;; in order to ensure all occurrences of some list (a b) across all
 ;; text-properties in all ERC buffers are actually the same object.
-(defun erc--merge-prop (from to prop val &optional object)
+(defun erc--merge-prop (from to prop val &optional object cache-fn)
   "Combine existing PROP values with VAL between FROM and TO in OBJECT.
 For spans where PROP is non-nil, cons VAL onto the existing
 value, ensuring a proper list.  Otherwise, just set PROP to VAL.
 When VAL is itself a list, prepend its members onto an existing
-value.  See also `erc-button-add-face'."
+value.  Call CACHE-FN, when given, with the new value for prop.
+It must return a suitable replacement or the same value.  See
+also `erc-button-add-face'."
   (let ((old (get-text-property from prop object))
         (pos from)
         (end (next-single-property-change from prop object to))
@@ -3370,6 +3502,8 @@ value.  See also `erc-button-add-face'."
                           (append val (ensure-list old))
                         (cons val (ensure-list old))))
                   val))
+      (when cache-fn
+        (setq new (funcall cache-fn new)))
       (put-text-property pos end prop new object)
       (setq pos end
             old (get-text-property pos prop object)
@@ -3447,7 +3581,7 @@ subsequent message."
     (save-restriction
       (widen)
       (unless end
-        (setq end (erc--get-inserted-msg-bounds nil beg-or-point)
+        (setq end (erc--get-inserted-msg-bounds beg-or-point)
               beg (pop end)))
       (with-silent-modifications
         (if erc-legacy-invisible-bounds-p
@@ -3458,7 +3592,8 @@ subsequent message."
              (substring (delete-and-extract-region (1- (point)) (1+ end))
                         -1))))))))
 
-(defvar erc--ranked-properties '(erc-msg erc-ts erc-cmd))
+(defvar erc--ranked-properties
+  '(erc--msg erc--spkr erc--ts erc--cmd erc--ctcp erc--ephemeral))
 
 (defun erc--order-text-properties-from-hash (table)
   "Return a plist of text props from items in TABLE.
@@ -3699,14 +3834,14 @@ TYPE, when non-nil, to be a symbol handled by
 string MSG).  Expect BUFFER to be among the sort accepted by the
 function `erc-display-line'.
 
-Expect BUFFER to be a live `erc-mode' buffer, a list of such
-buffers, or the symbols `all' or `active'.  If `all', insert
-STRING in all buffers for the current session.  If `active',
-defer to the function `erc-active-buffer', which may return the
-session's server buffer if the previously active buffer has been
-killed.  If BUFFER is nil or a network process, pretend it's set
-to the appropriate server buffer.  Otherwise, use the current
-buffer.
+When non-nil, expect BUFFER to be a live `erc-mode' buffer, a
+list of such buffers, or the symbols `all' or `active'.  If
+`all', insert STRING in all buffers for the current session.  If
+`active', defer to the function `erc-active-buffer', which may
+return the session's server buffer if the previously active
+buffer has been killed.  If BUFFER is nil or a network process,
+pretend it's set to the appropriate server buffer.  Otherwise,
+use the current buffer.
 
 When TYPE is a list of symbols, call handlers from left to right
 without influencing how they behave when encountering existing
@@ -3719,37 +3854,33 @@ being (erc-error-face erc-notice-face) throughout MSG 
when
 `erc-notice-highlight-type' is left at its default, `all'.
 
 As of ERC 5.6, assume third-party code will use this function
-instead of lower-level ones, like `erc-insert-line', when needing
-ERC to process arbitrary informative messages as if they'd been
-sent from a server.  That is, guarantee \"local\" messages, for
-which PARSED is typically nil, will be subject to buttonizing,
-filling, and other effects."
-  (let ((string (if (symbolp msg)
-                    (apply #'erc-format-message msg args)
-                  msg))
-        (erc--msg-props
-         (or erc--msg-props
-             (let ((table (make-hash-table :size 5))
-                   (cmd (and parsed (erc--get-eq-comparable-cmd
-                                     (erc-response.command parsed)))))
-               (puthash 'erc-msg
-                        (cond ((and msg (symbolp msg)) msg)
-                              ((and cmd (memq cmd '(PRIVMSG NOTICE)) 'msg))
-                              (type (pcase type
-                                      ((pred symbolp) type)
-                                      ((pred listp)
-                                       (intern (mapconcat #'prin1-to-string
-                                                          type "-")))
-                                      (_ 'unknown)))
-                              (t 'unknown))
-                        table)
-               (when cmd
-                 (puthash 'erc-cmd cmd table))
-               (and-let* ((ovs erc--msg-prop-overrides))
-                 (pcase-dolist (`(,k . ,v) (reverse ovs))
-                   (puthash k v table)))
-               table)))
-        (erc-message-parsed parsed))
+instead of lower-level ones, like `erc-insert-line', to insert
+arbitrary informative messages as if sent by the server.  That
+is, tell modules to treat a \"local\" message for which PARSED is
+nil like any other server-sent message."
+  (let* ((erc--msg-props
+          (or erc--msg-props
+              (let ((table (make-hash-table))
+                    (cmd (and parsed (erc--get-eq-comparable-cmd
+                                      (erc-response.command parsed)))))
+                (puthash 'erc--msg
+                         (cond ((and msg (symbolp msg)) msg)
+                               (type (pcase type
+                                       ((pred symbolp) type)
+                                       ((pred listp)
+                                        (intern (mapconcat #'prin1-to-string
+                                                           type "-")))
+                                       (_ 'unknown)))
+                               (t 'unknown))
+                         table)
+                (when cmd
+                  (puthash 'erc--cmd cmd table))
+                (when erc--msg-prop-overrides
+                  (pcase-dolist (`(,k . ,v) (reverse erc--msg-prop-overrides))
+                    (when v (puthash k v table))))
+                table)))
+         (erc-message-parsed parsed)
+         (string (if (symbolp msg) (apply #'erc-format-message msg args) msg)))
     (setq string
           (cond
            ((null type)
@@ -3808,6 +3939,10 @@ for other purposes.")
 
 (defun erc-send-input-line (target line &optional force)
   "Send LINE to TARGET."
+  (when-let ((target)
+             (cmem (erc-get-channel-member (erc-current-nick))))
+    (setf (erc-channel-user-last-message-time (cdr cmem))
+          (erc-compat--current-lisp-time)))
   (when (and (not erc--allow-empty-outgoing-lines-p) (string= line "\n"))
     (setq line " \n"))
   (erc-message "PRIVMSG" (concat target " " line) force))
@@ -4084,12 +4219,16 @@ If no USER argument is specified, list the contents of 
`erc-ignore-list'."
 Called with position indicating boundary of interval to be excised.")
 
 (defun erc-cmd-CLEAR ()
-  "Clear the window content."
-  (let ((inhibit-read-only t))
-    (run-hook-with-args 'erc--pre-clear-functions (1- erc-insert-marker))
-    ;; Ostensibly, `line-beginning-position' is for use in lisp code.
-    (delete-region (point-min) (min (line-beginning-position)
-                                    (1- erc-insert-marker))))
+  "Clear messages in current buffer after informing active modules.
+Expect modules to perform housekeeping tasks to withstand the
+disruption.  When called from lisp code, only clear messages up
+to but not including the one occupying the current line."
+  (with-silent-modifications
+    (let ((max (if (>= (point) erc-insert-marker)
+                   (1- erc-insert-marker)
+                 (or (erc--get-inserted-msg-beg (point)) (pos-bol)))))
+      (run-hook-with-args 'erc--pre-clear-functions max)
+      (delete-region (point-min) max)))
   t)
 (put 'erc-cmd-CLEAR 'process-not-needed t)
 
@@ -4320,11 +4459,22 @@ the one with host foo would win."
       (plist-get (car sorted) :secret))))
 
 (defun erc-auth-source-search (&rest plist)
-  "Call `auth-source-search', possibly with keyword params in PLIST."
+  "Call `auth-source-search', possibly with keyword params in PLIST.
+If the search signals an error before returning, `warn' the user
+and ask whether to continue connecting anyway."
   ;; These exist as separate helpers in case folks should find them
   ;; useful.  If that's you, please request that they be exported.
-  (apply #'erc--auth-source-search
-         (apply #'erc--auth-source-determine-params-merge plist)))
+  (condition-case err
+      (apply #'erc--auth-source-search
+             (apply #'erc--auth-source-determine-params-merge plist))
+    (error
+     (erc--lwarn '(erc auth-source) :error
+                 "Problem querying `auth-source': %S. See %S for more."
+                 (error-message-string err)
+                 '(info "(erc) auth-source Troubleshooting"))
+     (when (or noninteractive
+               (not (y-or-n-p "Ignore auth-source error and continue? ")))
+       (signal (car err) (cdr err))))))
 
 (defun erc-server-join-channel (server channel &optional secret)
   "Join CHANNEL, optionally with SECRET.
@@ -4646,11 +4796,25 @@ See also `erc-message' and `erc-display-line'."
     (erc--send-message-external line force)))
 
 (defun erc--send-message-external (line force)
-  (erc-message "PRIVMSG" (concat (erc-default-target) " " line) force)
-  (erc-display-line
-   (concat (erc-format-my-nick) line)
-   (current-buffer))
+  "Send a \"PRIVMSG\" to the default target with optional FORCE.
+Expect caller to bind `erc-default-recipients' if needing to
+specify a status-prefixed target."
+  ;; Almost like an echoed message, but without the `erc--cmd'.
+  (let* ((erc-current-message-catalog erc--message-speaker-catalog)
+         (target (erc-default-target))
+         (erc--msg-prop-overrides `((erc--tmp) ,@erc--msg-prop-overrides))
+         ;; This util sets the `erc--spkr' property in ^.
+         (trimmed (erc--statusmsg-target target))
+         (stmsgindc (and trimmed (substring target 0 1)))
+         (queryp (and erc--target (not (erc--target-channel-p erc--target))))
+         (args (erc--determine-speaker-message-format-args
+                (erc-current-nick) line queryp 'privmsgp 'inputp
+                stmsgindc 'prefix)))
+    (erc-message "PRIVMSG" (concat target " " line) force)
+    (push (cons 'erc--msg (car args)) erc--msg-prop-overrides)
+    (apply #'erc-display-message nil nil (current-buffer) args))
   ;; FIXME - treat multiline, run hooks, or remove me?
+  ;; FIXME explain this ^ in more detail or remove.
   t)
 
 (defun erc--send-message-nested (input-line force)
@@ -4689,7 +4853,7 @@ A list of valid mode strings for Libera.Chat may be found 
at
    ((string-match "^\\s-\\(.*\\)$" line)
     (let ((s (match-string 1 line)))
       (erc-log (format "cmd: MODE: %s" s))
-      (erc-server-send (concat "MODE " line)))
+      (erc-server-send (concat "MODE " s)))
     t)
    (t nil)))
 (put 'erc-cmd-MODE 'do-not-parse-args t)
@@ -4951,6 +5115,8 @@ connection or, with -A, all applicable connections.
 
 (put 'erc-cmd-RECONNECT 'process-not-needed t)
 
+;; FIXME use less speculative error message or lose `condition-case',
+;; since most connection failures don't signal anything.
 (defun erc-cmd-SERVER (server)
   "Connect to SERVER, leaving existing connection intact."
   (erc-log (format "cmd: SERVER: %s" server))
@@ -4969,9 +5135,11 @@ connection or, with -A, all applicable connections.
                             system-configuration
                             (concat
                              (cond ((featurep 'motif)
+                                    (defvar motif-version-string)
                                     (concat ", " (substring
                                                   motif-version-string 4)))
                                    ((featurep 'gtk)
+                                    (defvar gtk-version-string)
                                     (concat ", GTK+ Version "
                                             gtk-version-string))
                                    ((featurep 'x-toolkit) ", X toolkit")
@@ -5256,12 +5424,13 @@ Eventually add a # in front of it, if that turns it 
into a valid channel name."
     (concat "#" channel)))
 
 (defvar erc--own-property-names
-  '( tags erc-speaker erc-parsed display ; core
+  `( tags erc--speaker erc-parsed display ; core
+     ;; `erc--msg-props'
+     ,@erc--ranked-properties
      ;; `erc-display-prompt'
      rear-nonsticky erc-prompt field front-sticky read-only
      ;; stamp
      cursor-intangible cursor-sensor-functions isearch-open-invisible
-     erc-stamp-type
      ;; match
      invisible intangible
      ;; button
@@ -5605,7 +5774,9 @@ manner implied above, which was lost sometime before ERC 
5.4."
   :package-version '(ERC . "5.6") ; revived
   :group 'erc-buffers
   :group 'erc-query
-  :type 'boolean)
+  :type '(choice boolean
+                 (choice :tag "Create pseudo queries for STATUSMSGs"
+                         status)))
 
 (defcustom erc-format-query-as-channel-p t
   "If non-nil, format text from others in a query buffer like in a channel.
@@ -5740,12 +5911,12 @@ and as second argument the event parsed as a vector."
        (not (string-match "^\C-aACTION.*\C-a$" message))))
 
 (defun erc--get-speaker-bounds ()
-  "Return the bounds of `erc-speaker' text property when present.
+  "Return the bounds of `erc--speaker' text property when present.
 Assume buffer is narrowed to the confines of an inserted message."
-  (and-let* (((erc--check-msg-prop 'erc-msg 'msg))
+  (and-let* (((erc--check-msg-prop 'erc--spkr))
              (beg (text-property-not-all (point-min) (point-max)
-                                         'erc-speaker nil)))
-    (cons beg (next-single-property-change beg 'erc-speaker))))
+                                         'erc--speaker nil)))
+    (cons beg (next-single-property-change beg 'erc--speaker))))
 
 (defvar erc--cmem-from-nick-function #'erc--cmem-get-existing
   "Function maybe returning a \"channel member\" cons from a nick.
@@ -5770,53 +5941,287 @@ NUH, and the current `erc-response' object.")
                                                 nick-prefix-face nick))
                          0))
          (msg-face (if privp 'erc-direct-msg-face 'erc-default-face)))
+    (erc--ensure-spkr-prop nick)
     ;; add text properties to text before the nick, the nick and after the nick
     (erc-put-text-property 0 (length mark-s) 'font-lock-face msg-face str)
     (erc-put-text-properties (+ (length mark-s) prefix-len)
                              (+ (length mark-s) (length nick))
-                             '(font-lock-face erc-speaker) str
+                             '(font-lock-face erc--speaker) str
                              (list nick-face
                                    (substring-no-properties nick prefix-len)))
     (erc-put-text-property (+ (length mark-s) (length nick)) (length str)
                            'font-lock-face msg-face str)
     str))
 
-(defcustom erc-format-nick-function 'erc-format-nick
-  "Function to format a nickname for message display."
+;; The format strings in the following `-speaker' catalog shouldn't
+;; contain any non-protocol words, so they make sense in any language.
+
+(defvar erc--message-speaker-statusmsg
+  #("(%p%n%s) %m"
+    0 1 (font-lock-face erc-default-face)
+    1 3 (font-lock-face erc-nick-prefix-face)
+    3 5 (font-lock-face erc-nick-default-face)
+    5 7 (font-lock-face erc-notice-face)
+    7 11 (font-lock-face erc-default-face))
+  "Message template for in-channel status messages.")
+
+(defvar erc--message-speaker-statusmsg-input
+  #("(%p%n%s) %m"
+    0 1 (font-lock-face erc-default-face)
+    1 3 (font-lock-face erc-my-nick-prefix-face)
+    3 5 (font-lock-face erc-my-nick-face)
+    5 7 (font-lock-face erc-notice-face)
+    7 8 (font-lock-face erc-default-face)
+    8 11 (font-lock-face erc-input-face))
+  "Message template for echoed status messages.")
+
+(defvar erc--message-speaker-input-chan-privmsg
+  #("<%p%n> %m"
+    0 1 (font-lock-face erc-default-face)
+    1 3 (font-lock-face erc-my-nick-prefix-face)
+    3 5 (font-lock-face erc-my-nick-face)
+    5 7 (font-lock-face erc-default-face)
+    7 9 (font-lock-face erc-input-face))
+  "Message template for prompt input or echoed PRIVMSG from own nick.")
+
+(defvar erc--message-speaker-input-query-privmsg
+  #("*%n* %m"
+    0 1 (font-lock-face erc-direct-msg-face)
+    1 3 (font-lock-face erc-my-nick-face)
+    3 5 (font-lock-face erc-direct-msg-face)
+    5 7 (font-lock-face erc-input-face))
+  "Message template for prompt input or echoed PRIVMSG query from own nick.")
+
+(defvar erc--message-speaker-input-query-notice
+  #("-%n- %m"
+    0 1 (font-lock-face erc-direct-msg-face)
+    1 3 (font-lock-face erc-my-nick-face)
+    3 5 (font-lock-face erc-direct-msg-face)
+    5 7 (font-lock-face erc-input-face))
+  "Message template for echoed or spoofed query NOTICE from own nick.")
+
+(defvar erc--message-speaker-input-chan-notice
+  #("-%p%n- %m"
+    0 1 (font-lock-face erc-default-face)
+    1 3 (font-lock-face erc-my-nick-prefix-face)
+    3 5 (font-lock-face erc-my-nick-face)
+    5 7 (font-lock-face erc-default-face)
+    7 9 (font-lock-face erc-input-face))
+  "Message template for prompt input or echoed NOTICE from own nick.")
+
+(defvar erc--message-speaker-chan-privmsg
+  #("<%p%n> %m"
+    0 1 (font-lock-face erc-default-face)
+    1 3 (font-lock-face erc-nick-prefix-face)
+    3 5 (font-lock-face erc-nick-default-face)
+    5 9 (font-lock-face erc-default-face))
+  "Message template for a PRIVMSG in a channel.")
+
+(defvar erc--message-speaker-query-privmsg
+  #("*%n* %m"
+    0 1 (font-lock-face erc-direct-msg-face)
+    1 3 (font-lock-face erc-nick-msg-face)
+    3 7 (font-lock-face erc-direct-msg-face))
+  "Message template for a PRIVMSG in query buffer.")
+
+(defvar erc--message-speaker-chan-notice
+  #("-%p%n- %m"
+    0 1 (font-lock-face erc-default-face)
+    1 3 (font-lock-face erc-nick-prefix-face)
+    3 5 (font-lock-face erc-nick-default-face)
+    5 9 (font-lock-face erc-default-face))
+  "Message template for a NOTICE in a channel.")
+
+(defvar erc--message-speaker-query-notice
+  #("-%n- %m"
+    0 1 (font-lock-face erc-direct-msg-face)
+    1 3 (font-lock-face erc-nick-msg-face)
+    3 7 (font-lock-face erc-direct-msg-face))
+  "Message template for a NOTICE in a query buffer.")
+
+(defvar erc--message-speaker-ctcp-action
+  #("* %p%n %m"
+    0 2 (font-lock-face erc-action-face)
+    2 4 (font-lock-face (erc-nick-prefix-face erc-action-face))
+    4 9 (font-lock-face erc-action-face))
+  "Message template for a CTCP ACTION from another user.")
+
+(defvar erc--message-speaker-ctcp-action-input
+  #("* %p%n %m"
+    0 2 (font-lock-face #1=(erc-input-face erc-action-face))
+    2 4 (font-lock-face (erc-my-nick-prefix-face . #1#))
+    4 6 (font-lock-face (erc-my-nick-face . #1#))
+    6 9 (font-lock-face #1#))
+  "Message template for a CTCP ACTION from current client.")
+
+(defvar erc--message-speaker-ctcp-action-statusmsg
+  #("* (%p%n%s) %m"
+    0 3 (font-lock-face erc-action-face)
+    3 5 (font-lock-face (erc-nick-prefix-face erc-action-face))
+    5 7 (font-lock-face erc-action-face)
+    7 9 (font-lock-face (erc-notice-face erc-action-face))
+    9 13 (font-lock-face erc-action-face))
+  "Template for a CTCP ACTION status message from another chan op.")
+
+(defvar erc--message-speaker-ctcp-action-statusmsg-input
+  #("* (%p%n%s) %m"
+    0 3 (font-lock-face #1=(erc-input-face erc-action-face))
+    3 5 (font-lock-face (erc-my-nick-prefix-face . #1#))
+    5 7 (font-lock-face (erc-my-nick-face . #1#))
+    7 9 (font-lock-face (erc-notice-face . #1#))
+    9 13 (font-lock-face #1#))
+  "Template for a CTCP ACTION status message from current client.")
+
+(defun erc--speakerize-nick (nick &optional disp)
+  "Propertize NICK with `erc--speaker' if not already present.
+Do so to DISP instead if it's non-nil.  In either case, assign
+NICK, sans properties, as the `erc--speaker' value.  As a side
+effect, pair the latter string (the same `eq'-able object) with
+the symbol `erc--spkr' in the \"msg prop\" environment for any
+imminent `erc-display-message' invocations.  While doing so,
+include any overrides defined in `erc--message-speaker-catalog'."
+  (let ((plain-nick (substring-no-properties nick)))
+    (erc--ensure-spkr-prop plain-nick (get erc--message-speaker-catalog
+                                           'erc--msg-prop-overrides))
+    (if (text-property-not-all 0 (length (or disp nick))
+                               'erc--speaker nil (or disp nick))
+        (or disp nick)
+      (propertize (or disp nick) 'erc--speaker plain-nick))))
+
+(defun erc--determine-speaker-message-format-args
+    (nick message queryp privmsgp inputp &optional statusmsg prefix disp-nick)
+  "Return a list consisting of a \"speaker\"-template key and spec args.
+Consider the three flags QUERYP, PRIVMSGP, and INPUTP, as well as
+the possibly null STATUSMSG string.  (Combined, these describe
+the context of a newly arrived \"PRIVMSG\" or, when PRIVMSGP is
+nil, a \"NOTICE\").  Interpret QUERYP to mean that MESSAGE is
+directed at the ERC client itself (a direct message), and INPUTP
+to mean MESSAGE is an outgoing or echoed message originating from
+or meant to simulate prompt input.  Interpret a non-nil STATUSMSG
+to mean MESSAGE should be formatted as a special channel message
+intended for privileged members of the same or greater status.
+
+After deciding on the template key for the current \"speaker\"
+catalog, use the remaining arguments, possibly along with
+STATUSMSG, to construct the appropriate spec-args plist forming
+the returned list's tail.  In this plist, pair the char ?n with
+NICK, the nickname of the speaker and ?m with MESSAGE, the
+message body.  When non-nil, assume DISP-NICK to be a possibly
+phony display name to take the place of NICK for ?n.  When PREFIX
+is non-nil, look up NICK's channel-membership status, possibly
+using PREFIX itself if it's an `erc-channel-user' object, which
+it must be when called outside of a channel buffer.  Pair the
+result with the ?p specifier.  When STATUSMSG is non-nil, pair it
+with the ?s specifier.  Ensure unused spec values are the empty
+string rather than nil."
+  (when prefix
+    (setq prefix (erc-get-channel-membership-prefix
+                  (if (erc-channel-user-p prefix) prefix nick))))
+  (when (and queryp erc--target erc-format-query-as-channel-p
+             (not (erc--target-channel-p erc--target)))
+    (setq queryp nil))
+  (list (cond (statusmsg (if inputp 'statusmsg-input 'statusmsg))
+              (privmsgp (if queryp
+                            (if inputp 'input-query-privmsg 'query-privmsg)
+                          (if inputp 'input-chan-privmsg 'chan-privmsg)))
+              (t (if queryp
+                     (if inputp 'input-query-notice 'query-notice)
+                   (if inputp 'input-chan-notice 'chan-notice))))
+        ?p (or prefix "") ?n (erc--speakerize-nick nick disp-nick)
+        ?s (or statusmsg "") ?m message))
+
+(defcustom erc-show-speaker-membership-status nil
+  "Whether to prefix speakers with their channel status.
+For example, when this option is non-nil and some nick \"Alice\"
+has operator status in the current channel, ERC displays their
+leading \"speaker\" label as <@Alice> instead of <Alice>."
+  :package-version '(ERC . "5.6")
   :group 'erc-display
-  :type 'function)
+  :type 'boolean)
 
-(defun erc-format-nick (&optional user _channel-data)
-  "Return the nickname of USER.
-See also `erc-format-nick-function'."
-  (when user (erc-server-user-nickname user)))
+(define-obsolete-variable-alias 'erc-format-nick-function
+  'erc-speaker-from-channel-member-function "30.1")
+(defcustom erc-speaker-from-channel-member-function
+  #'erc-determine-speaker-from-user
+  "Function to determine a message's displayed \"speaker\" label.
+Called with an `erc-server-user' object and an `erc-channel-user'
+object, both possibly nil.  Use this option to do things like
+provide localized display names.  To ask ERC to prepend
+channel-membership \"status\" prefixes, like \"@\", to the
+returned name, see `erc-show-speaker-membership-status'."
+  :package-version '(ERC . "5.6")
+  :group 'erc-display
+  :type '(choice (function-item erc-determine-speaker-from-user) function))
 
-(defun erc-get-user-mode-prefix (user)
-  (when user
-    (cond ((erc-channel-user-owner-p user)
-           (propertize "~" 'help-echo "owner"))
-          ((erc-channel-user-admin-p user)
-           (propertize "&" 'help-echo "admin"))
-          ((erc-channel-user-op-p user)
-           (propertize "@" 'help-echo "operator"))
-          ((erc-channel-user-halfop-p user)
-           (propertize "%" 'help-echo "half-op"))
-          ((erc-channel-user-voice-p user)
-           (propertize "+" 'help-echo "voice"))
-          (t ""))))
+(define-obsolete-function-alias 'erc-format-nick
+  #'erc-determine-speaker-from-user "30.1")
+(defun erc-determine-speaker-from-user (&optional user _channel-data)
+  "Return nickname slot of `erc-server-user' USER, when non-nil."
+  (when user (erc-server-user-nickname user)))
 
-(defun erc-format-@nick (&optional user _channel-data)
+(define-obsolete-function-alias 'erc-get-user-mode-prefix
+  #'erc-get-channel-membership-prefix "30.1")
+(defun erc-get-channel-membership-prefix (nick-or-cusr)
+  "Return channel membership prefix for NICK-OR-CUSR as a string.
+Ensure returned string has a `help-echo' text property with the
+corresponding verbose membership type, like \"voice\", as its
+value.  Expect NICK-OR-CUSR to be an `erc-channel-user' object or
+a string nickname, not necessarily downcased.  When called in a
+logically connected ERC buffer, use advertised prefix mappings.
+For compatibility reasons, don't error when NICK-OR-CUSR is null,
+but return nil instead of the empty string.  Otherwise, always
+return a possibly empty string."
+  (when nick-or-cusr
+    (when (stringp nick-or-cusr)
+      (setq nick-or-cusr (and erc-channel-members
+                              (cdr (erc-get-channel-member nick-or-cusr)))))
+    (cond
+     ((null nick-or-cusr) "")
+     ;; Special-case most common value.
+     ((zerop (erc-channel-user-status nick-or-cusr)) "")
+     ;; For compatibility, first check whether a parsed prefix exists.
+     ((and-let* ((pfx-obj (erc--parsed-prefix)))
+        (catch 'done
+          (pcase-dolist (`(,letter . ,pfx)
+                         (erc--parsed-prefix-alist pfx-obj))
+            (when (erc--cusr-status-p nick-or-cusr letter)
+              (throw 'done
+                     (pcase letter
+                       (?q (propertize (string pfx) 'help-echo "owner"))
+                       (?a (propertize (string pfx) 'help-echo "admin"))
+                       (?o (propertize (string pfx) 'help-echo "operator"))
+                       (?h (propertize (string pfx) 'help-echo "half-op"))
+                       (?v (propertize (string pfx) 'help-echo "voice"))
+                       (_ (string pfx))))))
+          "")))
+     (t
+      (cond ((erc-channel-user-owner nick-or-cusr)
+             (propertize "~" 'help-echo "owner"))
+            ((erc-channel-user-admin nick-or-cusr)
+             (propertize "&" 'help-echo "admin"))
+            ((erc-channel-user-op nick-or-cusr)
+             (propertize "@" 'help-echo "operator"))
+            ((erc-channel-user-halfop nick-or-cusr)
+             (propertize "%" 'help-echo "half-op"))
+            ((erc-channel-user-voice nick-or-cusr)
+             (propertize "+" 'help-echo "voice"))
+            (t ""))))))
+
+(defun erc-format-@nick (&optional user channel-data)
   "Format the nickname of USER showing if USER has a voice, is an
 operator, half-op, admin or owner.  Owners have \"~\", admins have
 \"&\", operators have \"@\" and users with voice have \"+\" as a
-prefix.  Use CHANNEL-DATA to determine op and voice status.  See
-also `erc-format-nick-function'."
+prefix.  Use CHANNEL-DATA to determine op and voice status."
+  (declare (obsolete "see option `erc-show-speaker-membership-status'" "30.1"))
   (when user
     (let ((nick (erc-server-user-nickname user)))
-      (concat (propertize
-               (erc-get-user-mode-prefix nick)
-               'font-lock-face 'erc-nick-prefix-face)
-             nick))))
+      (if (not erc--speaker-status-prefix-wanted-p)
+          (prog1 nick
+            (setq erc--speaker-status-prefix-wanted-p 'erc-format-@nick))
+        (concat (propertize
+                 (erc-get-channel-membership-prefix channel-data)
+                 'font-lock-face 'erc-nick-prefix-face)
+                nick)))))
 
 (defun erc-format-my-nick ()
   "Return the beginning of this user's message, correctly propertized."
@@ -5824,15 +6229,42 @@ also `erc-format-nick-function'."
       (let* ((open "<")
              (close "> ")
              (nick (erc-current-nick))
-             (mode (erc-get-user-mode-prefix nick)))
+             (mode (erc-get-channel-membership-prefix nick)))
+        (erc--ensure-spkr-prop nick)
         (concat
          (propertize open 'font-lock-face 'erc-default-face)
          (propertize mode 'font-lock-face 'erc-my-nick-prefix-face)
-         (propertize nick 'font-lock-face 'erc-my-nick-face 'erc-speaker nick)
+         (propertize nick 'erc--speaker nick 'font-lock-face 'erc-my-nick-face)
          (propertize close 'font-lock-face 'erc-default-face)))
     (let ((prefix "> "))
       (propertize prefix 'font-lock-face 'erc-default-face))))
 
+(defun erc--format-speaker-input-message (message)
+  "Assemble outgoing MESSAGE entered at the prompt for insertion.
+Intend \"input\" to refer to interactive prompt input as well as
+the group of associated message-format templates from the
+\"speaker\" catalog.  Format the speaker portion in a manner
+similar to that performed by `erc-format-my-nick', but use either
+`erc--message-speaker-input-chan-privmsg' or
+`erc--message-speaker-input-query-privmsg' as a formatting
+template, with MESSAGE being the actual message body.  Return a
+copy with possibly shared text-property values."
+  (if-let ((erc-show-my-nick)
+           (nick (erc-current-nick))
+           (pfx (erc-get-channel-membership-prefix nick))
+           (erc-current-message-catalog erc--message-speaker-catalog)
+           (key (if (or erc-format-query-as-channel-p
+                        (erc--target-channel-p erc--target))
+                    'input-chan-privmsg
+                  'input-query-privmsg)))
+      (progn
+        (cond (erc--msg-props (puthash 'erc--msg key erc--msg-props))
+              (erc--msg-prop-overrides (push (cons 'erc--msg key)
+                                             erc--msg-prop-overrides)))
+        (erc-format-message key ?p pfx ?n (erc--speakerize-nick nick)
+                            ?m message))
+    (propertize (concat "> " message) 'font-lock-face 'erc-input-face)))
+
 (defun erc-echo-notice-in-default-buffer (s parsed buffer _sender)
   "Echo a private notice in the default buffer, namely the
 target buffer specified by BUFFER, or there is no target buffer,
@@ -6072,8 +6504,7 @@ See also `erc-display-message'."
         (while queries
           (let* ((type (upcase (car (split-string (car queries)))))
                  (hook (intern-soft (concat "erc-ctcp-query-" type "-hook")))
-                 (erc--msg-prop-overrides `((erc-msg . msg)
-                                            (erc-ctcp . ,(intern type))
+                 (erc--msg-prop-overrides `((erc--ctcp . ,(intern type))
                                             ,@erc--msg-prop-overrides)))
             (if (and hook (boundp hook))
                 (if (string-equal type "ACTION")
@@ -6108,11 +6539,31 @@ See also `erc-display-message'."
     (let ((s (match-string 1 msg))
           (buf (or (erc-get-buffer to proc)
                    (erc-get-buffer nick proc)
-                   (process-buffer proc))))
-      (setq nick (propertize nick 'erc-speaker nick))
-      (erc-display-message
-       parsed 'action buf
-       'ACTION ?n nick ?u login ?h host ?a s))))
+                   (process-buffer proc)))
+          (selfp (erc-current-nick-p nick)))
+      (if erc--use-language-catalog-for-ctcp-action-p
+          (progn
+            (erc--ensure-spkr-prop nick)
+            (setq nick (propertize nick 'erc--speaker nick))
+            (erc-display-message parsed (if selfp 'input 'action) buf
+                                 'ACTION ?n nick ?u login ?h host ?a s))
+        (let* ((obj (and (erc--ctcp-response-p parsed) parsed))
+               (buffer (and obj (erc--ctcp-response-buffer obj)))
+               (stsmsg (and obj (erc--ctcp-response-statusmsg obj)))
+               (prefix (and obj (erc--ctcp-response-prefix obj)))
+               (dispnm (and obj (erc--ctcp-response-dispname obj)))
+               (erc-current-message-catalog erc--message-speaker-catalog))
+          (erc-display-message
+           parsed nil (or buffer buf)
+           (if selfp
+               (if stsmsg 'ctcp-action-statusmsg-input 'ctcp-action-input)
+             (if stsmsg 'ctcp-action-statusmsg 'ctcp-action))
+           ?s (or stsmsg to)
+           ?p (or (and (erc-channel-user-p prefix)
+                       (erc-get-channel-membership-prefix prefix))
+                  "")
+           ?n (erc--speakerize-nick nick dispnm)
+           ?m s))))))
 
 (defvar erc-ctcp-query-CLIENTINFO-hook '(erc-ctcp-query-CLIENTINFO))
 
@@ -6186,8 +6637,14 @@ See also `erc-display-message'."
 (defun erc-process-ctcp-reply (proc parsed nick login host msg)
   "Process MSG as a CTCP reply."
   (let* ((type (car (split-string msg)))
-         (hook (intern (concat "erc-ctcp-reply-" type "-hook"))))
-    (if (boundp hook)
+         (hook (intern-soft (concat "erc-ctcp-reply-" type "-hook")))
+         ;; Help `erc-display-message' by ensuring subsequent
+         ;; insertions retain the necessary props.
+         (cmd (erc--get-eq-comparable-cmd (erc-response.command parsed)))
+         (erc--msg-prop-overrides `((erc--ctcp . ,(and hook (intern type)))
+                                    (erc--cmd . ,cmd)
+                                    ,@erc--msg-prop-overrides)))
+    (if (and hook (boundp hook))
         (run-hook-with-args-until-success
          hook proc nick login host
          (car (erc-response.command-args parsed)) msg)
@@ -6347,12 +6804,52 @@ parameter advertised by the current server, with the 
original
 ordering intact.  If no such parameter has yet arrived, return a
 stand-in from the fallback value \"(qaohv)~&@%+\"."
   (erc--with-isupport-data PREFIX erc--parsed-prefix
-    (let ((alist (nreverse (erc-parse-prefix))))
+    (let ((alist (erc-parse-prefix)))
       (make-erc--parsed-prefix
        :key key
        :letters (apply #'string (map-keys alist))
        :statuses (apply #'string (map-values alist))
-       :alist alist))))
+       :alist (nreverse alist)))))
+
+(defun erc--get-prefix-flag (char &optional parsed-prefix from-prefix-p)
+  "Return numeric rank for CHAR or nil if unknown.
+For example, given letters \"qaohv\" return 1 for ?v, 2 for ?h,
+and 4 for ?o, etc.  If given, expect PARSED-PREFIX to be a
+`erc--parse-prefix' object.  With FROM-PREFIX-P, expect CHAR to
+be a prefix instead."
+  (and-let* ((obj (or parsed-prefix (erc--parsed-prefix)))
+             (pos (erc--strpos char (if from-prefix-p
+                                        (erc--parsed-prefix-statuses obj)
+                                      (erc--parsed-prefix-letters obj)))))
+    (ash 1 pos)))
+
+(defun erc--init-cusr-fallback-status (voice halfop op admin owner)
+  "Return channel-membership based on traditional status semantics.
+Massage boolean switches VOICE, HALFOP, OP, ADMIN, and OWNER into
+an internal numeric value suitable for the `status' slot of a new
+`erc-channel-user' object."
+  (let ((pfx (erc--parsed-prefix)))
+    (+ (if voice  (if pfx (or (erc--get-prefix-flag ?v pfx) 0)  1) 0)
+       (if halfop (if pfx (or (erc--get-prefix-flag ?h pfx) 0)  2) 0)
+       (if op     (if pfx (or (erc--get-prefix-flag ?o pfx) 0)  4) 0)
+       (if admin  (if pfx (or (erc--get-prefix-flag ?a pfx) 0)  8) 0)
+       (if owner  (if pfx (or (erc--get-prefix-flag ?q pfx) 0) 16) 0))))
+
+(defun erc--compute-cusr-fallback-status (current v h o a q)
+  "Return current channel membership after toggling V H O A Q as requested.
+Assume `erc--parsed-prefix' is non-nil in the current buffer.
+Expect status switches V, H, O, A, Q, when non-nil, to be the
+symbol `on' or `off'.  Return an internal numeric value suitable
+for the `status' slot of an `erc-channel-user' object."
+  (let (on off)
+    (when v (push (or (erc--get-prefix-flag ?v) 0) (if (eq v 'on) on off)))
+    (when h (push (or (erc--get-prefix-flag ?h) 0) (if (eq h 'on) on off)))
+    (when o (push (or (erc--get-prefix-flag ?o) 0) (if (eq o 'on) on off)))
+    (when a (push (or (erc--get-prefix-flag ?a) 0) (if (eq a 'on) on off)))
+    (when q (push (or (erc--get-prefix-flag ?q) 0) (if (eq q 'on) on off)))
+    (when on (setq current (apply #'logior current on)))
+    (when off (setq current (apply #'logand current (mapcar #'lognot off)))))
+  current)
 
 (defcustom erc-channel-members-changed-hook nil
   "This hook is called every time the variable `channel-members' changes.
@@ -6360,48 +6857,40 @@ The buffer where the change happened is current while 
this hook is called."
   :group 'erc-hooks
   :type 'hook)
 
-(defun erc-channel-receive-names (names-string)
-  "This function is for internal use only.
+(defun erc--partition-prefixed-names (name)
+  "From NAME, return a list of (STATUS NICK LOGIN HOST).
+Expect NAME to be a prefixed name, like @bob."
+  (unless (string-empty-p name)
+    (let* ((status (erc--get-prefix-flag (aref name 0) nil 'from-prefix-p))
+           (nick (if status (substring name 1) name)))
+      (unless (string-empty-p nick)
+        (list status nick nil nil)))))
 
-Update `erc-channel-users' according to NAMES-STRING.
-NAMES-STRING is a string listing some of the names on the
-channel."
-  (let* ((prefix (erc--parsed-prefix-alist (erc--parsed-prefix)))
-         (voice-ch (cdr (assq ?v prefix)))
-         (op-ch (cdr (assq ?o prefix)))
-         (hop-ch (cdr (assq ?h prefix)))
-         (adm-ch (cdr (assq ?a prefix)))
-         (own-ch (cdr (assq ?q prefix)))
-         (names (delete "" (split-string names-string)))
-        name op voice halfop admin owner)
-    (let ((erc-channel-members-changed-hook nil))
-      (dolist (item names)
-        (let ((updatep t)
-             (ch (aref item 0)))
-          (setq name item op 'off voice 'off halfop 'off admin 'off owner 'off)
-          (if (rassq ch prefix)
-              (if (= (length item) 1)
-                 (setq updatep nil)
-               (setq name (substring item 1))
-               (setf (pcase ch
-                       ((pred (eq voice-ch)) voice)
-                       ((pred (eq hop-ch))   halfop)
-                       ((pred (eq op-ch))    op)
-                       ((pred (eq adm-ch))   admin)
-                       ((pred (eq own-ch))   owner)
-                       (_ (message "Unknown prefix char `%S'" ch) voice))
-                     'on)))
-          (when updatep
+(defun erc-channel-receive-names (names-string)
+  "Update `erc-channel-members' from NAMES-STRING.
+Expect NAMES-STRING to resemble the trailing argument of a 353
+RPL_NAMREPLY.  Call internal handlers for parsing individual
+names, whose expected composition may differ depending on enabled
+extensions."
+  (let ((names (delete "" (split-string names-string)))
+        (erc-channel-members-changed-hook nil))
+    (dolist (name names)
+      (when-let ((args (erc--partition-prefixed-names name)))
+        (pcase-let* ((`(,status ,nick ,login ,host) args)
+                     (cmem (erc-get-channel-user nick)))
+          (progn
            ;; If we didn't issue the NAMES request (consider two clients
            ;; talking to an IRC proxy), `erc-channel-begin-receiving-names'
            ;; will not have been called, so we have to do it here.
            (unless erc-channel-new-member-names
              (erc-channel-begin-receiving-names))
-            (puthash (erc-downcase name) t
-                     erc-channel-new-member-names)
-            (erc-update-current-channel-member
-             name name t voice halfop op admin owner)))))
-    (run-hooks 'erc-channel-members-changed-hook)))
+            (puthash (erc-downcase nick) t erc-channel-new-member-names)
+            (if cmem
+                (erc--update-current-channel-member cmem status nil
+                                                    nick host login)
+              (erc--create-current-channel-member nick status nil
+                                                  nick host login)))))))
+  (run-hooks 'erc-channel-members-changed-hook))
 
 (defun erc-update-user-nick (nick &optional new-nick
                                   host login full-name info)
@@ -6453,111 +6942,114 @@ which USER is a member, and t is returned."
                   (run-hooks 'erc-channel-members-changed-hook))))))
     changed))
 
-(defun erc-update-current-channel-member
-  (nick new-nick &optional add voice halfop op admin owner host login 
full-name info
-        update-message-time)
-  "Update the stored user information for the user with nickname NICK.
-`erc-update-user' is called to handle changes to nickname,
-HOST, LOGIN, FULL-NAME, and INFO.  If VOICE HALFOP OP ADMIN or OWNER
-are non-nil, they must be equal to either `on' or `off', in which
-case the status of the user in the current channel is changed accordingly.
-If UPDATE-MESSAGE-TIME is non-nil, the last-message-time of the user
- in the current channel is set to (current-time).
-
-If ADD is non-nil, the user will be added with the specified
-information if it is not already present in the user or channel
-lists.
-
-If, and only if, changes are made, or the user is added,
-`erc-channel-members-changed-hook' is run, and t is returned.
-
-See also: `erc-update-user' and `erc-update-channel-member'."
-  (let* (changed user-changed
-                 (channel-data (erc-get-channel-user nick))
-                 (cuser (cdr channel-data))
-                 (user (if channel-data (car channel-data)
-                         (erc-get-server-user nick))))
-    (if cuser
+(defun erc--create-current-channel-member
+    (nick status timep &optional new-nick host login full-name info)
+  "Add an `erc-channel-member' entry for NICK.
+Create a new `erc-server-users' entry if necessary, and ensure
+`erc-channel-members-changed-hook' runs exactly once, regardless.
+Pass STATUS to the `erc-channel-user' constructor.  With TIMEP,
+assume NICK has just spoken, and initialize `last-message-time'.
+Pass NEW-NICK, HOST, LOGIN, FULL-NAME, and INFO to
+`erc-update-user' if a server user exists and otherwise to the
+`erc-server-user' constructor."
+  (cl-assert (null (erc-get-channel-member nick)))
+  (let* ((user-changed-p nil)
+         (down (erc-downcase nick))
+         (user (gethash down (erc-with-server-buffer erc-server-users))))
+    (if user
         (progn
-          (erc-log (format "update-member: user = %S, cuser = %S" user cuser))
-          (when (and voice
-                     (not (eq (erc-channel-user-voice cuser) voice)))
-            (setq changed t)
-            (setf (erc-channel-user-voice cuser)
-                  (cond ((eq voice 'on) t)
-                        ((eq voice 'off) nil)
-                        (t voice))))
-          (when (and halfop
-                     (not (eq (erc-channel-user-halfop cuser) halfop)))
-            (setq changed t)
-            (setf (erc-channel-user-halfop cuser)
-                  (cond ((eq halfop 'on) t)
-                        ((eq halfop 'off) nil)
-                        (t halfop))))
-          (when (and op
-                     (not (eq (erc-channel-user-op cuser) op)))
-            (setq changed t)
-            (setf (erc-channel-user-op cuser)
-                  (cond ((eq op 'on) t)
-                        ((eq op 'off) nil)
-                        (t op))))
-          (when (and admin
-                     (not (eq (erc-channel-user-admin cuser) admin)))
-            (setq changed t)
-            (setf (erc-channel-user-admin cuser)
-                  (cond ((eq admin 'on) t)
-                        ((eq admin 'off) nil)
-                        (t admin))))
-          (when (and owner
-                     (not (eq (erc-channel-user-owner cuser) owner)))
-            (setq changed t)
-            (setf (erc-channel-user-owner cuser)
-                  (cond ((eq owner 'on) t)
-                        ((eq owner 'off) nil)
-                        (t owner))))
-          (when update-message-time
-            (setf (erc-channel-user-last-message-time cuser) (current-time)))
-          (setq user-changed
-                (erc-update-user user new-nick
-                                 host login full-name info)))
-      (when add
-        (if (null user)
-            (progn
-              (setq user (make-erc-server-user
-                          :nickname nick
-                          :host host
-                          :full-name full-name
-                          :login login
-                          :info info
-                          :buffers (list (current-buffer))))
-              (erc-add-server-user nick user))
-          (setf (erc-server-user-buffers user)
-                (cons (current-buffer)
-                      (erc-server-user-buffers user))))
-        (setq cuser (make-erc-channel-user
-                     :voice (cond ((eq voice 'on) t)
-                                  ((eq voice 'off) nil)
-                                  (t voice))
-                     :halfop (cond ((eq halfop 'on) t)
-                                ((eq halfop 'off) nil)
-                                (t halfop))
-                     :op (cond ((eq op 'on) t)
-                               ((eq op 'off) nil)
-                               (t op))
-                     :admin (cond ((eq admin 'on) t)
-                                  ((eq admin 'off) nil)
-                                  (t admin))
-                     :owner (cond ((eq owner 'on) t)
-                                  ((eq owner 'off) nil)
-                                  (t owner))
-                     :last-message-time
-                     (if update-message-time (current-time))))
-        (puthash (erc-downcase nick) (cons user cuser)
-                 erc-channel-users)
-        (setq changed t)))
-    (when (and changed (null user-changed))
+          (cl-pushnew (current-buffer) (erc-server-user-buffers user))
+          ;; Update *after* ^ so hook has chance to run.
+          (setf user-changed-p (erc-update-user user new-nick host login
+                                                full-name info)))
+      (erc-add-server-user nick
+                           (setq user (make-erc-server-user
+                                       :nickname (or new-nick nick)
+                                       :host host
+                                       :full-name full-name
+                                       :login login
+                                       :info nil
+                                       :buffers (list (current-buffer))))))
+    (let ((cusr (erc-channel-user--make
+                 :status (or status 0)
+                 :last-message-time (and timep
+                                         (erc-compat--current-lisp-time)))))
+      (puthash down (cons user cusr) erc-channel-users))
+    ;; An existing `cusr' was changed or a new one was added, and
+    ;; `user' was not updated, though possibly just created (since
+    ;; `erc-update-user' runs this same hook in all a user's buffers).
+    (unless user-changed-p
       (run-hooks 'erc-channel-members-changed-hook))
-    (or changed user-changed add)))
+    t))
+
+(defun erc--update-current-channel-member (cmem status timep &rest user-args)
+  "Update existing `erc-channel-member' entry.
+Set the `status' slot of the entry's `erc-channel-user' side to
+STATUS and, with TIMEP, update its `last-message-time'.  When
+actual changes are made, run `erc-channel-members-changed-hook',
+and return non-nil."
+  (cl-assert cmem)
+  (let ((cusr (cdr cmem))
+        (user (car cmem))
+        cusr-changed-p user-changed-p)
+    (when (and status (/= status (erc-channel-user-status cusr)))
+      (setf (erc-channel-user-status cusr) status
+            cusr-changed-p t))
+    (when timep
+      (setf (erc-channel-user-last-message-time cusr)
+            (erc-compat--current-lisp-time)))
+    ;; Ensure `erc-channel-members-changed-hook' runs on change.
+    (cl-assert (memq (current-buffer) (erc-server-user-buffers user)))
+    (setq user-changed-p (apply #'erc-update-user user user-args))
+    ;; An existing `cusr' was changed or a new one was added, and
+    ;; `user' was not updated, though possibly just created (since
+    ;; `erc-update-user' runs this same hook in all a user's buffers).
+    (when (and cusr-changed-p (null user-changed-p))
+      (run-hooks 'erc-channel-members-changed-hook))
+    (erc-log (format "update-member: user = %S, cusr = %S" user cusr))
+    (or cusr-changed-p user-changed-p)))
+
+(defun erc-update-current-channel-member
+    (nick new-nick &optional addp voice halfop op admin owner host login
+          full-name info update-message-time)
+  "Update or create entry for NICK in current `erc-channel-members' table.
+With ADDP, ensure an entry exists.  When an entry does exist or
+when ADDP is non-nil and an `erc-server-users' entry already
+exists, call `erc-update-user' with NEW-NICK, HOST, LOGIN,
+FULL-NAME, and INFO.  Expect any non-nil membership
+status switches among VOICE, HALFOP, OP, ADMIN, and OWNER to be
+the symbol `on' or `off' when needing to influence a new or
+existing `erc-channel-user' object's `status' slot.  Likewise,
+when UPDATE-MESSAGE-TIME is non-nil, update or initialize the
+`last-message-time' slot to the current-time.  If changes occur,
+including creation, run `erc-channel-members-changed-hook'.
+Return non-nil when meaningful changes, including creation, have
+occurred.
+
+Without ADDP, do nothing unless a `erc-channel-members' entry
+exists.  When it doesn't, assume the sender is a non-joined
+entity, like the server itself or a historical speaker, or assume
+the prior buffer for the channel was killed without parting."
+(let* ((cmem (erc-get-channel-member nick))
+       (status (and (or voice halfop op admin owner)
+                    (if cmem
+                        (erc--compute-cusr-fallback-status
+                         (erc-channel-user-status (cdr cmem))
+                         voice halfop op admin owner)
+                      (erc--init-cusr-fallback-status
+                       (and voice  (eq voice  'on))
+                       (and halfop (eq halfop 'on))
+                       (and op     (eq op     'on))
+                       (and admin  (eq admin  'on))
+                       (and owner  (eq owner  'on)))))))
+  (if cmem
+      (erc--update-current-channel-member cmem status update-message-time
+                                          new-nick host login
+                                          full-name info)
+    (when addp
+      (erc--create-current-channel-member nick status update-message-time
+                                          new-nick host login
+                                          full-name info)))))
 
 (defun erc-update-channel-member (channel nick new-nick
                                           &optional add voice halfop op admin 
owner host login
@@ -6747,16 +7239,6 @@ person who changed the modes."
           ;; nick modes - ignored at this point
           (t nil))))
 
-(defun erc--update-membership-prefix (nick letter state)
-  "Update status prefixes for NICK in current channel buffer.
-Expect LETTER to be a status char and STATE to be a boolean."
-  (erc-update-current-channel-member nick nil nil
-                                     (and (= letter ?v) state)
-                                     (and (= letter ?h) state)
-                                     (and (= letter ?o) state)
-                                     (and (= letter ?a) state)
-                                     (and (= letter ?q) state)))
-
 (defvar-local erc--channel-modes nil
   "When non-nil, a hash table of current channel modes.
 Keys are characters.  Values are either a string, for types A-C,
@@ -6779,7 +7261,7 @@ Use the getter of the same name to retrieve the current 
value.")
           (ct (make-char-table 'erc--channel-mode-types))
           (type ?a))
       (dolist (cs types)
-        (dolist (c (append cs nil))
+        (erc--doarray (c cs)
           (aset ct c type))
         (cl-incf type))
       (make-erc--channel-mode-types :key key
@@ -6798,21 +7280,20 @@ complement relevant letters in STRING."
          (table (erc--channel-mode-types-table obj))
          (fallbackp (erc--channel-mode-types-fallbackp obj))
          (+p t))
-    (dolist (c (append string nil))
-      (let ((letter (char-to-string c)))
-        (cond ((= ?+ c) (setq +p t))
-              ((= ?- c) (setq +p nil))
-              ((and status-letters (string-search letter status-letters))
-               (erc--update-membership-prefix (pop args) c (if +p 'on 'off)))
-              ((and-let* ((group (or (aref table c) (and fallbackp ?d))))
-                 (erc--handle-channel-mode group c +p
-                                           (and (/= group ?d)
-                                                (or (/= group ?c) +p)
-                                                (pop args)))
-                 t))
-              ((not fallbackp)
-               (erc-display-message nil '(notice error) (erc-server-buffer)
-                                    (format "Unknown channel mode: %S" c))))))
+    (erc--doarray (c string)
+      (cond ((= ?+ c) (setq +p t))
+            ((= ?- c) (setq +p nil))
+            ((and status-letters (string-search (string c) status-letters))
+             (erc--cusr-change-status (pop args) c +p))
+            ((and-let* ((group (or (aref table c) (and fallbackp ?d))))
+               (erc--handle-channel-mode group c +p
+                                         (and (/= group ?d)
+                                              (or (/= group ?c) +p)
+                                              (pop args)))
+               t))
+            ((not fallbackp)
+             (erc-display-message nil '(notice error) (erc-server-buffer)
+                                  (format "Unknown channel mode: %S" c)))))
     (setq erc-channel-modes (sort erc-channel-modes #'string<))
     (setq erc--mode-line-mode-string
           (concat "+" (erc--channel-modes erc--mode-line-chanmodes-arg-len)))
@@ -6892,9 +7373,7 @@ dropped were they not already absent."
   (let ((addp t)
         ;;
         redundant-add redundant-drop adding dropping)
-    ;; For short strings, `append' appears to be no slower than
-    ;; iteration var + `aref' or `mapc' + closure.
-    (dolist (c (append string nil))
+    (erc--doarray (c string)
       (pcase c
         (?+ (setq addp t))
         (?- (setq addp nil))
@@ -7087,9 +7566,9 @@ EmacsSpeak support."
 (defalias 'erc-list 'ensure-list)
 
 (defconst erc--parse-user-regexp-pedantic
-  (rx bot (group (* (not (any "!\r\n"))))
-      "!" (group (* nonl))
-      "@" (group (* nonl)) eot))
+  (rx bot (? (? (group (+ (not (any "!@\r\n"))))) "!")
+      (? (? (group (+ nonl))) "@")
+      (? (group (+ nonl))) eot))
 
 (defconst erc--parse-user-regexp-legacy
   "^\\([^!\n]*\\)!\\([^@\n]*\\)@\\(.*\\)$")
@@ -7113,6 +7592,26 @@ Return a list of the three separate tokens."
    (t
     (list string "" ""))))
 
+(defun erc--parse-nuh (string)
+  "Match STRING against `erc--parse-user-regexp-pedantic'.
+Return nil or matching groups representing nick, login, and host,
+any of which may be nil.  Expect STRING not to contain leading
+prefix chars.  Return an empty nick component to indicate further
+processing is required based on context.  Interpret a lone token
+lacking delimiters or one with only a leading \"!\" as a host.
+
+See associated unit test for precise behavior."
+  (when (string-match erc--parse-user-regexp-pedantic string)
+    (list (match-string 1 string)
+          (match-string 2 string)
+          (match-string 3 string))))
+
+(defun erc--shuffle-nuh-nickward (nick login host)
+  "Interpret results of `erc--parse-nuh', promoting loners to nicks."
+  (cond (nick (cl-assert (null login)) (list nick login host))
+        ((and (null login) host) (list host nil nil))
+        ((and login (null host)) (list login nil nil))))
+
 (defun erc-extract-nick (string)
   "Return the nick corresponding to a user specification STRING.
 
@@ -7285,11 +7784,20 @@ a separate message."
   (when (< (point) (erc-beg-of-input-line))
     "Point is not in the input area"))
 
+;; Originally, `erc-send-current-line' inhibited sends whenever a
+;; server buffer was missing.  In 2007, this was narrowed to
+;; occurrences involving process-dependent commands.  However, the
+;; accompanying error message, which was identical to that emitted by
+;; `erc-server-send', "ERC: No process running", was always inaccurate
+;; because a server buffer can be alive and its process dead.
 (defun erc--check-prompt-input-for-running-process (string _)
-  "Return non-nil unless in an active ERC server buffer."
-  (unless (or (erc-server-buffer-live-p)
-              (erc-command-no-process-p string))
-    "ERC: No process running"))
+  "Return non-nil if STRING is a slash command missing a process.
+Also do so when the server buffer has been killed."
+  ;; Even if the server buffer has been killed, the user should still
+  ;; be able to /reconnect and recall previous commands.
+  (and (not (erc-command-no-process-p string))
+       (or (and (not (erc-server-buffer-live-p)) "Server buffer missing")
+           (and (not (erc-server-process-alive)) "Process not running"))))
 
 (defun erc--check-prompt-input-for-multiline-command (line lines)
   "Return non-nil when non-blank lines follow a command line."
@@ -7402,7 +7910,7 @@ When all lines are empty, remove all but the first."
   "Partition non-command input into lines of protocol-compliant length."
   ;; Prior to ERC 5.6, line splitting used to be predicated on
   ;; `erc-flood-protect' being non-nil.
-  (unless (erc--input-split-cmdp state)
+  (unless (or (zerop erc-split-line-length) (erc--input-split-cmdp state))
     (setf (erc--input-split-lines state)
           (mapcan #'erc--split-line (erc--input-split-lines state)))))
 
@@ -7423,14 +7931,17 @@ queue.  Expect LINES-OBJ to be an `erc--input-split' 
object."
              (state (progn
                       ;; This may change `str' and `erc-*-this'.
                       (run-hook-with-args 'erc-send-pre-hook str)
-                      (make-erc-input :string str
-                                      :insertp erc-insert-this
-                                      :refoldp (erc--input-split-refoldp
-                                                lines-obj)
-                                      :sendp erc-send-this))))
+                      (make-erc-input
+                       :string str
+                       :insertp erc-insert-this
+                       :sendp erc-send-this
+                       :substxt (erc--input-split-substxt lines-obj)
+                       :refoldp (erc--input-split-refoldp lines-obj)))))
         (run-hook-with-args 'erc-pre-send-functions state)
         (setf (erc--input-split-sendp lines-obj) (erc-input-sendp state)
               (erc--input-split-insertp lines-obj) (erc-input-insertp state)
+              (erc--input-split-substxt lines-obj) (erc-input-substxt state)
+              (erc--input-split-refoldp lines-obj) (erc-input-refoldp state)
               ;; See note in test of same name re trailing newlines.
               (erc--input-split-lines lines-obj)
               (let ((lines (split-string (erc-input-string state)
@@ -7438,24 +7949,29 @@ queue.  Expect LINES-OBJ to be an `erc--input-split' 
object."
                 (if erc--allow-empty-outgoing-lines-p
                     lines
                   (cl-nsubst " " "" lines :test #'equal))))
-        (when (erc-input-refoldp state)
+        (when (erc--input-split-refoldp lines-obj)
           (erc--split-lines lines-obj)))))
   (when (and (erc--input-split-cmdp lines-obj)
              (cdr (erc--input-split-lines lines-obj)))
     (user-error "Multiline command detected" ))
   lines-obj)
 
-(cl-defmethod erc--send-input-lines (lines-obj)
+(defun erc--send-input-lines (lines-obj)
   "Send lines in `erc--input-split-lines' object LINES-OBJ."
   (when (erc--input-split-sendp lines-obj)
-    (dolist (line (erc--input-split-lines lines-obj))
-      (when (erc--input-split-insertp lines-obj)
-        (if (functionp (erc--input-split-insertp lines-obj))
-            (funcall (erc--input-split-insertp lines-obj) line)
-          (erc-display-msg line)))
-      (erc-process-input-line (concat line "\n")
-                              (null erc-flood-protect)
-                              (not (erc--input-split-cmdp lines-obj))))))
+    (let ((insertp (erc--input-split-insertp lines-obj))
+          (substxt (erc--input-split-substxt lines-obj)))
+      (when (and insertp substxt)
+        (setq insertp nil)
+        (if (functionp substxt)
+            (apply substxt (erc--input-split-lines lines-obj))
+          (erc-display-msg substxt)))
+      (dolist (line (erc--input-split-lines lines-obj))
+        (when insertp
+          (erc-display-msg line))
+        (erc-process-input-line (concat line "\n")
+                                (null erc-flood-protect)
+                                (not (erc--input-split-cmdp lines-obj)))))))
 
 (defun erc-send-input (input &optional skip-ws-chk)
   "Treat INPUT as typed in by the user.
@@ -7518,15 +8034,11 @@ as outgoing chat messages and echoed slash commands."
       (erc--assert-input-bounds)
       (let ((insert-position (marker-position (goto-char erc-insert-marker)))
             (erc--msg-props (or erc--msg-props
-                                (let ((ovs erc--msg-prop-overrides))
-                                  (map-into `((erc-msg . msg) ,@(reverse ovs))
-                                            'hash-table))))
-            beg)
-        (insert (erc-format-my-nick))
-        (setq beg (point))
-        (insert line)
-        (erc-put-text-property beg (point) 'font-lock-face 'erc-input-face)
-        (insert "\n")
+                                (let ((ovs (seq-filter
+                                            #'cdr erc--msg-prop-overrides)))
+                                  (map-into `((erc--msg . msg) ,@(reverse ovs))
+                                            'hash-table)))))
+        (insert (erc--format-speaker-input-message line) "\n")
         (save-restriction
           (narrow-to-region insert-position (point))
           (run-hooks 'erc-send-modify-hook)
@@ -7543,9 +8055,18 @@ as outgoing chat messages and echoed slash commands."
     (when (fboundp cmd) cmd)))
 
 (defun erc-extract-command-from-line (line)
-  "Extract command and args from the input LINE.
-If no command was given, return nil.  If command matches, return a
-list of the form: (command args) where both elements are strings."
+  "Extract a \"slash command\" and its args from a prompt-input LINE.
+If LINE doesn't start with a slash command, return nil.  If it
+does, meaning the pattern `erc-command-regexp' matches, return a
+list of the form (COMMAND ARGS), where COMMAND is either a symbol
+for a known handler function or `erc-cmd-default' if unknown.
+When COMMAND has the symbol property `do-not-parse-args', return
+a string in place of ARGS: that is, either LINE itself, when LINE
+consists of only whitespace, or LINE stripped of any trailing
+whitespace, including a final newline.  When COMMAND lacks the
+symbol property `do-not-parse-args', return a possibly empty list
+of non-whitespace tokens.  Do not perform any shell-style parsing
+of quoted or escaped substrings."
   (when (string-match erc-command-regexp line)
     (let* ((cmd (erc-command-symbol (match-string 1 line)))
            ;; note: return is nil, we apply this simply for side effects
@@ -7616,7 +8137,6 @@ See also `erc-downcase'."
 
 (defun erc--current-buffer-joined-p ()
   "Return non-nil if the current buffer is a channel and is joined."
-  (cl-assert erc--target)
   (and (erc--target-channel-p erc--target)
        (erc--target-channel-joined-p erc--target)
        t))
@@ -7671,6 +8191,8 @@ The previous default target of QUERY type gets removed."
         (setq erc-default-recipients d2)
       (error "Current target is not a QUERY"))))
 
+;; FIXME move all ignore-related functionality to its own module,
+;; required and enabled by default (until some major version change).
 (defun erc-ignored-user-p (spec)
   "Return non-nil if SPEC matches something in `erc-ignore-list'.
 
@@ -8288,8 +8810,13 @@ See `erc-mode-line-format' for which characters are can 
be used."
   :type '(choice (const :tag "Disabled" nil)
                  string))
 
+;; This should optionally support the built-in `tab-bar'.
 (defcustom erc-header-line-uses-tabbar-p nil
-  "Use tabbar mode instead of the header line to display the header."
+  "Use `tabbar-mode' integration instead of the header line.
+This concerns a historical integration with the external library
+`tabbar' <https://www.emacswiki.org/emacs/tabbar.el>, which
+shouldn't be confused with the built-in `tab-bar' described in
+Info node `(emacs) Tab Bars'."
   :group 'erc-mode-line-and-header
   :type 'boolean)
 
@@ -8425,7 +8952,7 @@ Currently only used by the option `erc-prompt-format'.")
 (defun erc--format-channel-status-prefix ()
   "Return the current channel membership prefix."
   (and (erc--target-channel-p erc--target)
-       (erc-get-user-mode-prefix (erc-current-nick))))
+       (erc-get-channel-membership-prefix (erc-current-nick))))
 
 (defun erc--format-modes (&optional no-query-p)
   "Return a string of channel modes in channels and user modes elsewhere.
@@ -8496,7 +9023,8 @@ buffers.  Also return nil when mode information is 
unavailable."
                         (format-spec erc-header-line-format spec)
                       nil)))
         (cond (erc-header-line-uses-tabbar-p
-               (setq-local tabbar--local-hlf header-line-format)
+               (when (boundp 'tabbar--local-hlf)
+                 (setq-local tabbar--local-hlf header-line-format))
                (kill-local-variable 'header-line-format))
               ((null header)
                (setq header-line-format nil))
@@ -8690,24 +9218,38 @@ All windows are opened in the current frame."
 
 ;;; Message catalog
 
+(define-inline erc--make-message-variable-name (catalog key softp)
+  "Return variable name conforming to ERC's message-catalog interface.
+Given a CATALOG symbol `mycat' and format-string KEY `mykey',
+also a symbol, return the symbol `erc-message-mycat-mykey'.  With
+SOFTP, only do so when defined as a variable."
+  (inline-quote
+   (let* ((catname (symbol-name ,catalog))
+          (prefix (if (eq ?- (aref catname 0)) "erc--message" "erc-message-"))
+          (name (concat prefix catname "-" (symbol-name ,key))))
+     (if ,softp
+         (and-let* ((s (intern-soft name)) ((boundp s))) s)
+       (intern name)))))
+
 (defun erc-make-message-variable-name (catalog entry)
   "Create a variable name corresponding to CATALOG's ENTRY."
-  (intern (concat "erc-message-"
-                  (symbol-name catalog) "-" (symbol-name entry))))
+  (erc--make-message-variable-name catalog entry nil))
 
 (defun erc-define-catalog-entry (catalog entry format-spec)
   "Set CATALOG's ENTRY to FORMAT-SPEC."
+  (declare (obsolete "define manually using `defvar' instead" "30.1"))
   (set (erc-make-message-variable-name catalog entry)
        format-spec))
 
 (defun erc-define-catalog (catalog entries)
   "Define a CATALOG according to ENTRIES."
-  (dolist (entry entries)
-    (erc-define-catalog-entry catalog (car entry) (cdr entry))))
+  (declare (obsolete erc-define-message-format-catalog "30.1"))
+  (with-suppressed-warnings ((obsolete erc-define-catalog-entry))
+    (dolist (entry entries)
+      (erc-define-catalog-entry catalog (car entry) (cdr entry)))))
 
-(erc-define-catalog
- 'english
- '((bad-ping-response . "Unexpected PING response from %n (time %t)")
+(erc--define-catalog english
+  ((bad-ping-response . "Unexpected PING response from %n (time %t)")
    (bad-syntax . "Error occurred - incorrect usage?\n%c %u\n%d")
    (incorrect-args . "Incorrect arguments. Usage:\n%c %u\n%d")
    (cannot-find-file . "Cannot find file %f")
@@ -8764,7 +9306,7 @@ All windows are opened in the current frame."
    (MODE-nick . "%n has changed mode for %t to %m")
    (NICK   . "%n (%u@%h) is now known as %N")
    (NICK-you . "Your new nickname is %N")
-   (PART   . erc-message-english-PART)
+   (PART   . #'erc-message-english-PART)
    (PING   . "PING from server (last: %s sec. ago)")
    (PONG   . "PONG from %h (%i second%s)")
    (QUIT   . "%n (%u@%h) has quit: %r")
@@ -8806,6 +9348,7 @@ All windows are opened in the current frame."
    (s368   . "Banlist of %c ends.")
    (s379   . "%c: Forwarded to %f")
    (s391   . "The time at %s is %t")
+   (s396   . "Your visible host has changed to %s")
    (s401   . "%n: No such nick/channel")
    (s402   . "%c: No such server")
    (s403   . "%c: No such channel")
@@ -8858,22 +9401,26 @@ functions."
                           (string-replace "%" "%%" reason))
                 "")))))
 
-
-(defvar-local erc-current-message-catalog 'english)
-
-(defun erc-retrieve-catalog-entry (entry &optional catalog)
-  "Retrieve ENTRY from CATALOG.
-
-If CATALOG is nil, `erc-current-message-catalog' is used.
-
-If ENTRY is nil in CATALOG, it is retrieved from the fallback,
-english, catalog."
+(defun erc-retrieve-catalog-entry (key &optional catalog)
+  "Retrieve `format-spec' entry for symbol KEY in CATALOG.
+Without symbol CATALOG, use `erc-current-message-catalog'.  If
+lookup fails, try the latter's `default-toplevel-value' if it's
+not the same as CATALOG.  Failing that, try the `english' catalog
+if yet untried."
   (unless catalog (setq catalog erc-current-message-catalog))
-  (let ((var (erc-make-message-variable-name catalog entry)))
-    (if (boundp var)
-        (symbol-value var)
-      (when (boundp (erc-make-message-variable-name 'english entry))
-        (symbol-value (erc-make-message-variable-name 'english entry))))))
+  (symbol-value
+   (or (erc--make-message-variable-name catalog key 'softp)
+       (let ((parent catalog)
+             last)
+         (while (and (setq parent (get parent 'erc--base-format-catalog))
+                     (not (setq last (erc--make-message-variable-name
+                                      parent key 'softp)))))
+         last)
+       (let ((default (default-toplevel-value 'erc-current-message-catalog)))
+         (or (and (not (eq default catalog))
+                  (erc--make-message-variable-name default key 'softp))
+             (and (not (memq 'english (list default catalog)))
+                  (erc--make-message-variable-name 'english key 'softp)))))))
 
 (defun erc-format-message (msg &rest args)
   "Format MSG according to ARGS.
diff --git a/lisp/eshell/em-alias.el b/lisp/eshell/em-alias.el
index 841982c3425..832e14418d0 100644
--- a/lisp/eshell/em-alias.el
+++ b/lisp/eshell/em-alias.el
@@ -1,6 +1,6 @@
 ;;; em-alias.el --- creation and management of command aliases  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/em-banner.el b/lisp/eshell/em-banner.el
index 2bee50b80a4..e6dcbb24475 100644
--- a/lisp/eshell/em-banner.el
+++ b/lisp/eshell/em-banner.el
@@ -1,6 +1,6 @@
 ;;; em-banner.el --- sample module that displays a login banner  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/em-basic.el b/lisp/eshell/em-basic.el
index 95d7d8f4ebe..6ec53ef9412 100644
--- a/lisp/eshell/em-basic.el
+++ b/lisp/eshell/em-basic.el
@@ -1,6 +1,6 @@
 ;;; em-basic.el --- basic shell builtin commands  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
@@ -160,6 +160,18 @@ or `eshell-printn' for display."
      :preserve-args
      :usage "[-S] [mode]")
    (cond
+    (args
+     (let* ((mask (car args))
+            (modes
+             (if (stringp mask)
+                 (if (string-match (rx bos (+ (any "0-7")) eos) mask)
+                     (- #o777 (string-to-number mask 8))
+                   (file-modes-symbolic-to-number
+                    mask (default-file-modes)))
+               (- #o777 mask))))
+       (set-default-file-modes modes)
+       (eshell-print
+        "Warning: umask changed for all new files created by Emacs.\n")))
     (symbolic-p
      (let ((mode (default-file-modes)))
        (eshell-printn
@@ -173,17 +185,9 @@ or `eshell-printn' for display."
                 (concat (and (= (logand mode 1) 1) "r")
                         (and (= (logand mode 2) 2) "w")
                         (and (= (logand mode 4) 4) "x"))))))
-    ((not args)
-     (eshell-printn (format "%03o" (logand (lognot (default-file-modes))
-                                           #o777))))
     (t
-     (when (stringp (car args))
-       (if (string-match "^[0-7]+$" (car args))
-           (setcar args (string-to-number (car args) 8))
-         (error "Setting umask symbolically is not yet implemented")))
-     (set-default-file-modes (- #o777 (car args)))
-     (eshell-print
-      "Warning: umask changed for all new files created by Emacs.\n")))
+     (eshell-printn (format "%03o" (logand (lognot (default-file-modes))
+                                           #o777)))))
    nil))
 
 (put 'eshell/umask 'eshell-no-numeric-conversions t)
diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el
index 0255da88dbd..201beb5071d 100644
--- a/lisp/eshell/em-cmpl.el
+++ b/lisp/eshell/em-cmpl.el
@@ -1,6 +1,6 @@
 ;;; em-cmpl.el --- completion using the TAB key  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el
index d62f36e56c2..07063afc286 100644
--- a/lisp/eshell/em-dirs.el
+++ b/lisp/eshell/em-dirs.el
@@ -1,6 +1,6 @@
 ;;; em-dirs.el --- directory navigation commands  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
@@ -262,6 +262,7 @@ Thus, this does not include the current directory.")
 (defun eshell-parse-user-reference ()
   "An argument beginning with ~ is a filename to be expanded."
   (when (and (not eshell-current-argument)
+             (not eshell-current-quoted)
              (eq (char-after) ?~))
     ;; Apply this modifier fairly early so it happens before things
     ;; like glob expansion.
@@ -316,7 +317,7 @@ Thus, this does not include the current directory.")
                    (`(boundaries . ,suffix)
                     `(boundaries 0 . ,(string-search "/" suffix))))))))))
 
-(defun eshell/pwd (&rest _args)
+(defun eshell/pwd ()
   "Change output from `pwd' to be cleaner."
   (let* ((path default-directory)
         (len (length path)))
diff --git a/lisp/eshell/em-elecslash.el b/lisp/eshell/em-elecslash.el
index 2b003f58dc7..93eadcfe1ff 100644
--- a/lisp/eshell/em-elecslash.el
+++ b/lisp/eshell/em-elecslash.el
@@ -1,6 +1,6 @@
 ;;; em-elecslash.el --- electric forward slashes  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Sean Whitton <spwhitton@spwhitton.name>
 
diff --git a/lisp/eshell/em-extpipe.el b/lisp/eshell/em-extpipe.el
index 0d5c217f5f0..057eead9297 100644
--- a/lisp/eshell/em-extpipe.el
+++ b/lisp/eshell/em-extpipe.el
@@ -1,6 +1,6 @@
 ;;; em-extpipe.el --- external shell pipelines  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Sean Whitton <spwhitton@spwhitton.name>
 
diff --git a/lisp/eshell/em-glob.el b/lisp/eshell/em-glob.el
index 0d0ff6188b6..b0c3e6e7a11 100644
--- a/lisp/eshell/em-glob.el
+++ b/lisp/eshell/em-glob.el
@@ -1,6 +1,6 @@
 ;;; em-glob.el --- extended file name globbing  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/em-hist.el b/lisp/eshell/em-hist.el
index cf03f8399a6..21029eae1bc 100644
--- a/lisp/eshell/em-hist.el
+++ b/lisp/eshell/em-hist.el
@@ -1,6 +1,6 @@
 ;;; em-hist.el --- history list management  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
@@ -116,6 +116,12 @@ If set to t, history will always be saved, silently."
                 (const :tag "Ask" ask)
                 (const :tag "Always save" t)))
 
+(defcustom eshell-history-append nil
+  "If non-nil, append new entries to the history file when saving history."
+  :type '(choice (const :tag "Overwrite history file" nil)
+                (const :tag "Append new entries to file" t))
+  :version "30.1")
+
 (defcustom eshell-input-filter 'eshell-input-filter-default
   "Predicate for filtering additions to input history.
 Takes one argument, the input.  If non-nil, the input may be saved on
@@ -294,17 +300,21 @@ Returns nil if INPUT is prepended by blank space, 
otherwise non-nil."
     (if eshell-history-file-name
        (eshell-read-history nil t))
 
-    (add-hook 'eshell-exit-hook #'eshell-write-history nil t))
+    (add-hook 'eshell-exit-hook #'eshell--save-history nil t))
 
   (unless eshell-history-ring
     (setq eshell-history-ring (make-ring eshell-history-size)))
 
-  (add-hook 'eshell-exit-hook #'eshell-write-history nil t)
+  (add-hook 'eshell-exit-hook #'eshell--save-history nil t)
 
   (add-hook 'kill-emacs-query-functions #'eshell-save-some-history)
 
   (add-hook 'eshell-input-filter-functions #'eshell-add-to-history nil t))
 
+(defun eshell--save-history ()
+  "Save the history for current Eshell buffer."
+  (eshell-write-history nil eshell-history-append))
+
 (defun eshell-save-some-history ()
   "Save the history for any open Eshell buffers."
   (dolist (buf (buffer-list))
@@ -318,7 +328,7 @@ Returns nil if INPUT is prepended by blank space, otherwise 
non-nil."
                        (format-message
                         "Save input history for Eshell buffer `%s'? "
                         (buffer-name buf)))))
-             (eshell-write-history)))))
+             (eshell--save-history)))))
   t)
 
 (defun eshell/history (&rest args)
@@ -389,7 +399,7 @@ input."
                ('nil t)                 ; Always add to history
                ('erase                  ; Add, removing any old occurrences
                 (when-let ((old-index (ring-member eshell-history-ring input)))
-                  ;; Remove the old occurence of this input so we can
+                  ;; Remove the old occurrence of this input so we can
                   ;; add it to the end.  FIXME: Should we try to
                   ;; remove multiple old occurrences, e.g. if the user
                   ;; recently changed to using `erase'?
diff --git a/lisp/eshell/em-ls.el b/lisp/eshell/em-ls.el
index 30f39d14b40..fd89a9f778e 100644
--- a/lisp/eshell/em-ls.el
+++ b/lisp/eshell/em-ls.el
@@ -1,6 +1,6 @@
 ;;; em-ls.el --- implementation of ls in Lisp  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el
index ae7d0c43bc4..c3997dc72c3 100644
--- a/lisp/eshell/em-pred.el
+++ b/lisp/eshell/em-pred.el
@@ -1,6 +1,6 @@
 ;;; em-pred.el --- argument predicates and modifiers (ala zsh)  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/em-prompt.el b/lisp/eshell/em-prompt.el
index 15b849a4d37..3662c1fa895 100644
--- a/lisp/eshell/em-prompt.el
+++ b/lisp/eshell/em-prompt.el
@@ -1,6 +1,6 @@
 ;;; em-prompt.el --- command prompts  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/em-rebind.el b/lisp/eshell/em-rebind.el
index e4579497edc..c6ee1a329b6 100644
--- a/lisp/eshell/em-rebind.el
+++ b/lisp/eshell/em-rebind.el
@@ -1,6 +1,6 @@
 ;;; em-rebind.el --- rebind keys when point is at current input  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/em-script.el b/lisp/eshell/em-script.el
index 3a4c315ad15..066063c4cc2 100644
--- a/lisp/eshell/em-script.el
+++ b/lisp/eshell/em-script.el
@@ -1,6 +1,6 @@
 ;;; em-script.el --- Eshell script files  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/em-smart.el b/lisp/eshell/em-smart.el
index fc283547519..91fe02e5545 100644
--- a/lisp/eshell/em-smart.el
+++ b/lisp/eshell/em-smart.el
@@ -1,6 +1,6 @@
 ;;; em-smart.el --- smart display of output  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/em-term.el b/lisp/eshell/em-term.el
index 3f76c349a7e..8f29e2d8509 100644
--- a/lisp/eshell/em-term.el
+++ b/lisp/eshell/em-term.el
@@ -1,6 +1,6 @@
 ;;; em-term.el --- running visual commands  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/em-tramp.el b/lisp/eshell/em-tramp.el
index 94eb9797033..efb37225651 100644
--- a/lisp/eshell/em-tramp.el
+++ b/lisp/eshell/em-tramp.el
@@ -1,6 +1,6 @@
 ;;; em-tramp.el --- Eshell features that require Tramp  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Aidan Gauland <aidalgol@no8wireless.co.nz>
 
@@ -121,12 +121,11 @@ Uses the system sudo through Tramp's sudo method."
      :usage "[(-u | --user) USER] (-s | --shell) | COMMAND
 Execute a COMMAND as the superuser or another USER.")
    (let ((dir (eshell--method-wrap-directory default-directory "sudo" user)))
-     (if shell
-         (throw 'eshell-replace-command
-                (eshell-parse-command "cd" (list dir)))
-       (throw 'eshell-external
-              (let ((default-directory dir))
-                (eshell-named-command (car args) (cdr args))))))))
+     (throw 'eshell-replace-command
+            (if shell
+                (eshell-parse-command "cd" (list dir))
+              `(let ((default-directory ,dir))
+                 (eshell-named-command ',(car args) ',(cdr args))))))))
 
 (put 'eshell/sudo 'eshell-no-numeric-conversions t)
 
@@ -144,12 +143,11 @@ Uses the system doas through Tramp's doas method."
      :usage "[(-u | --user) USER] (-s | --shell) | COMMAND
 Execute a COMMAND as the superuser or another USER.")
    (let ((dir (eshell--method-wrap-directory default-directory "doas" user)))
-     (if shell
-         (throw 'eshell-replace-command
-                (eshell-parse-command "cd" (list dir)))
-       (throw 'eshell-external
-              (let ((default-directory dir))
-                (eshell-named-command (car args) (cdr args))))))))
+     (throw 'eshell-replace-command
+            (if shell
+                (eshell-parse-command "cd" (list dir))
+              `(let ((default-directory ,dir))
+                 (eshell-named-command ',(car args) ',(cdr args))))))))
 
 (put 'eshell/doas 'eshell-no-numeric-conversions t)
 
diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el
index 509b2d31819..78dfd0654e2 100644
--- a/lisp/eshell/em-unix.el
+++ b/lisp/eshell/em-unix.el
@@ -1,6 +1,6 @@
 ;;; em-unix.el --- UNIX command aliases  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
@@ -92,7 +92,7 @@ Otherwise, `rmdir' is required."
   :group 'eshell-unix)
 
 (define-widget 'eshell-interactive-query 'radio
-  "When to interatively query the user about a particular operation.
+  "When to interactively query the user about a particular operation.
 If t, always query.  If nil, never query.  If `root', query when
 the user is logged in as root (including when `default-directory'
 is remote with a root user)."
@@ -166,9 +166,9 @@ Otherwise, Emacs will attempt to use rsh to invoke du on 
the remote machine."
     (add-hook 'pcomplete-try-first-hook
              'eshell-complete-host-reference nil t))
   (setq-local eshell-complex-commands
-             (append '("grep" "egrep" "fgrep" "agrep" "rgrep"
-                        "glimpse" "locate" "cat" "time" "cp" "mv"
-                        "make" "du" "diff")
+             (append '("compile" "grep" "egrep" "fgrep" "agrep"
+                        "rgrep" "glimpse" "locate" "cat" "time" "cp"
+                        "mv" "make" "du" "diff")
                      eshell-complex-commands)))
 
 (defalias 'eshell/date     'current-time-string)
@@ -590,7 +590,7 @@ Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.
      :external "cp"
      :show-usage
      :usage "[OPTION]... SOURCE DEST
-   or:  cp [OPTION]... SOURCE... DIRECTORY
+   or: cp [OPTION]... SOURCE... DIRECTORY
 Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.")
    (if archive
        (setq preserve t no-dereference t em-recursive t))
@@ -619,7 +619,7 @@ Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.")
      :external "ln"
      :show-usage
      :usage "[OPTION]... TARGET [LINK_NAME]
-   or:  ln [OPTION]... TARGET... DIRECTORY
+   or: ln [OPTION]... TARGET... DIRECTORY
 Create a link to the specified TARGET with optional LINK_NAME.  If there is
 more than one TARGET, the last argument must be a directory;  create links
 in DIRECTORY to each TARGET.  Create hard links by default, symbolic links
@@ -741,7 +741,7 @@ Fallback to standard make when called synchronously."
   (eshell-compile "make" args
                   ;; Use plain output unless we're executing in the
                   ;; background.
-                  (not eshell-current-subjob-p)))
+                  (unless eshell-current-subjob-p 'plain)))
 
 (put 'eshell/make 'eshell-no-numeric-conversions t)
 
@@ -940,7 +940,7 @@ external command."
             "display data only this many levels of data")
         (?h "human-readable" 1024 human-readable
             "print sizes in human readable format")
-        (?H "is" 1000 human-readable
+        (?H "si" 1000 human-readable
             "likewise, but use powers of 1000 not 1024")
         (?k "kilobytes" 1024 block-size
             "like --block-size 1024")
@@ -1018,7 +1018,7 @@ Show wall-clock time elapsed during execution of 
COMMAND.")
                                  (eshell-stringify-list
                                   (flatten-tree (cdr time-args))))))))
 
-(defun eshell/whoami (&rest _args)
+(defun eshell/whoami ()
   "Make \"whoami\" Tramp aware."
   (eshell-user-login-name))
 
diff --git a/lisp/eshell/em-xtra.el b/lisp/eshell/em-xtra.el
index 45c3ea3c0fc..a62073e2183 100644
--- a/lisp/eshell/em-xtra.el
+++ b/lisp/eshell/em-xtra.el
@@ -1,6 +1,6 @@
 ;;; em-xtra.el --- extra alias functions  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/esh-arg.el b/lisp/eshell/esh-arg.el
index 2bdfdff8a3a..97ddac58629 100644
--- a/lisp/eshell/esh-arg.el
+++ b/lisp/eshell/esh-arg.el
@@ -1,6 +1,6 @@
 ;;; esh-arg.el --- argument processing  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
@@ -440,6 +440,7 @@ Point is left at the end of the arguments."
 
 (defsubst eshell-looking-at-backslash-return (pos)
   "Test whether a backslash-return sequence occurs at POS."
+  (declare (obsolete nil "30.1"))
   (and (eq (char-after pos) ?\\)
        (or (= (1+ pos) (point-max))
           (and (eq (char-after (1+ pos)) ?\n)
@@ -464,8 +465,8 @@ backslash is ignored and the character after is returned.  
If the
 backslash is in a quoted string, the backslash and the character
 after are both returned."
   (when (eq (char-after) ?\\)
-    (when (eshell-looking-at-backslash-return (point))
-        (throw 'eshell-incomplete "\\"))
+    (when (= (1+ (point)) (point-max))
+      (throw 'eshell-incomplete "\\"))
     (forward-char 2) ; Move one char past the backslash.
     (let ((special-chars (if eshell-current-quoted
                              eshell-special-chars-inside-quoting
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index ecd947774ee..30494bafb48 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -1,6 +1,6 @@
 ;;; esh-cmd.el --- command invocation  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
@@ -934,48 +934,52 @@ This yields the SUBCOMMANDs when found in forms like
   (dolist (elem haystack)
     (cond
      ((eq (car-safe elem) 'eshell-as-subcommand)
-      (iter-yield (cdr elem)))
+      (iter-yield (cadr elem)))
      ((listp elem)
       (iter-yield-from (eshell--find-subcommands elem))))))
 
-(defun eshell--invoke-command-directly (command)
+(defun eshell--invoke-command-directly-p (command)
   "Determine whether the given COMMAND can be invoked directly.
 COMMAND should be a non-top-level Eshell command in parsed form.
 
 A command can be invoked directly if all of the following are true:
 
 * The command is of the form
-  \"(eshell-trap-errors (eshell-named-command NAME ARGS))\",
-  where ARGS is optional.
+  (eshell-with-copied-handles
+   (eshell-trap-errors (eshell-named-command NAME [ARGS])) _).
 
 * NAME is a string referring to an alias function and isn't a
   complex command (see `eshell-complex-commands').
 
 * Any subcommands in ARGS can also be invoked directly."
-  (when (and (eq (car command) 'eshell-trap-errors)
-             (eq (car (cadr command)) 'eshell-named-command))
-    (let ((name (cadr (cadr command)))
-          (args (cdr-safe (nth 2 (cadr command)))))
-      (and name (stringp name)
-          (not (member name eshell-complex-commands))
-          (catch 'simple
-            (dolist (pred eshell-complex-commands t)
-              (when (and (functionp pred)
-                         (funcall pred name))
-                (throw 'simple nil))))
-          (eshell-find-alias-function name)
-           (catch 'indirect-subcommand
-             (iter-do (subcommand (eshell--find-subcommands args))
-               (unless (eshell--invoke-command-directly subcommand)
-                 (throw 'indirect-subcommand nil)))
-             t)))))
-
-(defun eshell-invoke-directly (command)
+  (pcase command
+    (`(eshell-with-copied-handles
+       (eshell-trap-errors (eshell-named-command ,name . ,args))
+       ,_)
+     (and name (stringp name)
+         (not (member name eshell-complex-commands))
+         (catch 'simple
+           (dolist (pred eshell-complex-commands t)
+             (when (and (functionp pred)
+                        (funcall pred name))
+               (throw 'simple nil))))
+         (eshell-find-alias-function name)
+          (catch 'indirect-subcommand
+            (iter-do (subcommand (eshell--find-subcommands (car args)))
+              (unless (eshell--invoke-command-directly-p subcommand)
+                (throw 'indirect-subcommand nil)))
+            t)))))
+
+(defun eshell-invoke-directly-p (command)
   "Determine whether the given COMMAND can be invoked directly.
 COMMAND should be a top-level Eshell command in parsed form, as
 produced by `eshell-parse-command'."
-  (let ((base (cadr (nth 2 (nth 2 (cadr command))))))
-    (eshell--invoke-command-directly base)))
+  (pcase command
+    (`(eshell-commands (progn ,_ (unwind-protect (progn ,base) . ,_)))
+     (eshell--invoke-command-directly-p base))))
+
+(define-obsolete-function-alias 'eshell-invoke-directly
+  'eshell-invoke-directly-p "30.1")
 
 (defun eshell-eval-argument (argument)
   "Evaluate a single Eshell ARGUMENT and return the result."
diff --git a/lisp/eshell/esh-ext.el b/lisp/eshell/esh-ext.el
index 38579d7ef1c..dc2b93e574b 100644
--- a/lisp/eshell/esh-ext.el
+++ b/lisp/eshell/esh-ext.el
@@ -1,6 +1,6 @@
 ;;; esh-ext.el --- commands external to Eshell  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el
index c29b96dd711..4487389bf26 100644
--- a/lisp/eshell/esh-io.el
+++ b/lisp/eshell/esh-io.el
@@ -1,6 +1,6 @@
 ;;; esh-io.el --- I/O management  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el
index 9d2cd1e67eb..fd279f61673 100644
--- a/lisp/eshell/esh-mode.el
+++ b/lisp/eshell/esh-mode.el
@@ -1,6 +1,6 @@
 ;;; esh-mode.el --- user interface  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
@@ -619,14 +619,14 @@ If NO-NEWLINE is non-nil, the input is sent without an 
implied final
 newline."
   (interactive "P")
   ;; Note that the input string does not include its terminal newline.
-  (let ((proc-running-p (and (eshell-head-process)
-                            (not queue-p)))
-       (inhibit-modification-hooks t))
-    (unless (and proc-running-p
+  (let* ((proc-running-p (eshell-head-process))
+         (send-to-process-p (and proc-running-p (not queue-p)))
+         (inhibit-modification-hooks t))
+    (unless (and send-to-process-p
                 (not (eq (process-status
                           (eshell-head-process))
                           'run)))
-      (if (or proc-running-p
+      (if (or send-to-process-p
              (>= (point) eshell-last-output-end))
          (goto-char (point-max))
        (let ((copy (eshell-get-old-input use-region)))
@@ -634,7 +634,7 @@ newline."
          (insert-and-inherit copy)))
       (unless (or no-newline
                  (and eshell-send-direct-to-subprocesses
-                      proc-running-p))
+                      send-to-process-p))
        (insert-before-markers-and-inherit ?\n))
       ;; Delete and reinsert input.  This seems like a no-op, except
       ;; for the resulting entries in the undo list: undoing this
@@ -644,7 +644,7 @@ newline."
             (inhibit-read-only t))
         (delete-region eshell-last-output-end (point))
         (insert text))
-      (if proc-running-p
+      (if send-to-process-p
          (progn
            (eshell-update-markers eshell-last-output-end)
            (if (or eshell-send-direct-to-subprocesses
@@ -673,7 +673,8 @@ newline."
                      (run-hooks 'eshell-input-filter-functions)
                      (and (catch 'eshell-terminal
                             (ignore
-                             (if (eshell-invoke-directly cmd)
+                             (if (and (not proc-running-p)
+                                       (eshell-invoke-directly-p cmd))
                                  (eval cmd)
                                (eshell-eval-command cmd input))))
                           (eshell-life-is-too-much)))))
diff --git a/lisp/eshell/esh-module.el b/lisp/eshell/esh-module.el
index 7fc74d38796..fbd5ae4b9b8 100644
--- a/lisp/eshell/esh-module.el
+++ b/lisp/eshell/esh-module.el
@@ -1,6 +1,6 @@
 ;;; esh-module.el --- Eshell modules  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Keywords: processes
diff --git a/lisp/eshell/esh-opt.el b/lisp/eshell/esh-opt.el
index 09c19767a19..d01e3569d57 100644
--- a/lisp/eshell/esh-opt.el
+++ b/lisp/eshell/esh-opt.el
@@ -1,6 +1,6 @@
 ;;; esh-opt.el --- command options processing  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el
index e7e91f08741..35c81f6a4b2 100644
--- a/lisp/eshell/esh-proc.el
+++ b/lisp/eshell/esh-proc.el
@@ -1,6 +1,6 @@
 ;;; esh-proc.el --- process management  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
@@ -193,7 +193,7 @@ This is like `process-live-p', but additionally checks 
whether
 
 (defalias 'eshell/wait #'eshell-wait-for-process)
 
-(defun eshell/jobs (&rest _args)
+(defun eshell/jobs ()
   "List processes, if there are any."
   (and (fboundp 'process-list)
        (process-list)
diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el
index b22c286c635..f0acfecb701 100644
--- a/lisp/eshell/esh-util.el
+++ b/lisp/eshell/esh-util.el
@@ -1,6 +1,6 @@
 ;;; esh-util.el --- general utilities  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index d484aa406e1..537bc4b0641 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -1,6 +1,6 @@
 ;;; esh-var.el --- handling of variables  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
@@ -255,6 +255,20 @@ copied (a.k.a. \"exported\") to the environment of created 
subprocesses."
 (defvar-keymap eshell-var-mode-map
   "C-c M-v" #'eshell-insert-envvar)
 
+;;; Internal Variables:
+
+(defvar eshell-in-local-scope-p nil
+  "Non-nil if the current command has a local variable scope.
+This is set to t in `eshell-local-variable-bindings' (which see).")
+
+(defvar eshell-local-variable-bindings
+  '((eshell-in-local-scope-p t)
+    (process-environment (eshell-copy-environment))
+    (eshell-variable-aliases-list eshell-variable-aliases-list)
+    (eshell-path-env-list eshell-path-env-list)
+    (comint-pager comint-pager))
+  "A list of `let' bindings for local variable (and subcommand) environments.")
+
 ;;; Functions:
 
 (define-minor-mode eshell-var-mode
@@ -271,12 +285,10 @@ copied (a.k.a. \"exported\") to the environment of 
created subprocesses."
     (setq-local process-environment (eshell-copy-environment)))
   (make-local-variable 'comint-pager)
   (setq-local eshell-subcommand-bindings
-              (append
-               '((process-environment (eshell-copy-environment))
-                 (eshell-variable-aliases-list eshell-variable-aliases-list)
-                 (eshell-path-env-list eshell-path-env-list)
-                 (comint-pager comint-pager))
-               eshell-subcommand-bindings))
+              (append eshell-local-variable-bindings
+                      eshell-subcommand-bindings))
+  (setq-local eshell-complex-commands
+             (append '("env") eshell-complex-commands))
 
   (setq-local eshell-special-chars-inside-quoting
        (append eshell-special-chars-inside-quoting '(?$)))
@@ -294,32 +306,36 @@ copied (a.k.a. \"exported\") to the environment of 
created subprocesses."
     (add-hook 'pcomplete-try-first-hook
              #'eshell-complete-variable-assignment nil t)))
 
-(defun eshell-handle-local-variables ()
-  "Allow for the syntax `VAR=val <command> <args>'."
-  ;; Eshell handles local variable settings (e.g. 'CFLAGS=-O2 make')
-  ;; by making the whole command into a subcommand, and calling
-  ;; `eshell-set-variable' immediately before the command is invoked.
-  ;; This means that 'FOO=x cd bar' won't work exactly as expected,
-  ;; but that is by no means a typical use of local environment
-  ;; variables.
+(defun eshell-parse-local-variables (args)
+  "Parse a list of ARGS, looking for variable assignments.
+Variable assignments are of the form \"VAR=value\".  If ARGS
+begins with any such assignments, throw `eshell-replace-command'
+with a form that will temporarily set those variables.
+Otherwise, return nil."
+  ;; Handle local variable settings by let-binding the entries in
+  ;; `eshell-local-variable-bindings' and calling `eshell-set-variable'
+  ;; for each variable before the command is invoked.
   (let ((setvar "\\`\\([A-Za-z_][A-Za-z0-9_]*\\)=\\(.*\\)\\'")
-        (command eshell-last-command-name)
-        (args eshell-last-arguments))
-    (when (and (stringp command) (string-match setvar command))
+        (head (car args))
+        (rest (cdr args)))
+    (when (and (stringp head) (string-match setvar head))
       (throw 'eshell-replace-command
-             `(eshell-as-subcommand
-               (progn
-                 ,@(let (locals)
-                     (while (and (stringp command)
-                                 (string-match setvar command))
-                       (push `(eshell-set-variable
-                               ,(match-string 1 command)
-                               ,(match-string 2 command))
-                             locals)
-                       (setq command (pop args)))
-                     (nreverse locals))
-                 (eshell-named-command ,command ,(list 'quote args)))
-              )))))
+             `(let ,eshell-local-variable-bindings
+                ,@(let (locals)
+                    (while (and (stringp head)
+                                (string-match setvar head))
+                      (push `(eshell-set-variable
+                              ,(match-string 1 head)
+                              ,(match-string 2 head))
+                            locals)
+                      (setq head (pop rest)))
+                    (nreverse locals))
+                 (eshell-named-command ,head ',rest))))))
+
+(defun eshell-handle-local-variables ()
+  "Allow for the syntax `VAR=val <command> <args>'."
+  (eshell-parse-local-variables (cons eshell-last-command-name
+                                      eshell-last-arguments)))
 
 (defun eshell-interpolate-variable ()
   "Parse a variable interpolation.
@@ -409,19 +425,22 @@ the values of nil for each."
                                               obarray #'boundp))
              (pcomplete-here))))
 
-;; FIXME the real "env" command does more than this, it runs a program
-;; in a modified environment.
 (defun eshell/env (&rest args)
   "Implementation of `env' in Lisp."
-  (eshell-init-print-buffer)
   (eshell-eval-using-options
    "env" args
-   '((?h "help" nil nil "show this usage screen")
+   '(;; FIXME: Support more "env" options, like "--unset".
+     (?h "help" nil nil "show this usage screen")
      :external "env"
-     :usage "<no arguments>")
-   (dolist (setting (sort (eshell-environment-variables) 'string-lessp))
-     (eshell-buffered-print setting "\n"))
-   (eshell-flush)))
+     :parse-leading-options-only
+     :usage "[NAME=VALUE]... [COMMAND [ARG]...]")
+   (if args
+       (or (eshell-parse-local-variables args)
+           (eshell-named-command (car args) (cdr args)))
+     (eshell-init-print-buffer)
+     (dolist (setting (sort (eshell-environment-variables) 'string-lessp))
+       (eshell-buffered-print setting "\n"))
+     (eshell-flush))))
 
 (defun eshell-insert-envvar (envvar-name)
   "Insert ENVVAR-NAME into the current buffer at point."
@@ -709,7 +728,7 @@ to a Lisp variable)."
          ((functionp target)
           (funcall target nil value))
          ((null target)
-          (unless eshell-in-subcommand-p
+          (unless eshell-in-local-scope-p
             (error "Variable `%s' is not settable" (eshell-stringify name)))
           (push `(,name ,(lambda () value) t t)
                 eshell-variable-aliases-list)
diff --git a/lisp/eshell/eshell.el b/lisp/eshell/eshell.el
index 8765ba499a1..7d374587dc4 100644
--- a/lisp/eshell/eshell.el
+++ b/lisp/eshell/eshell.el
@@ -1,6 +1,6 @@
 ;;; eshell.el --- the Emacs command shell  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Version: 2.4.2
diff --git a/lisp/expand.el b/lisp/expand.el
index 7e0b0b56010..f32ab101224 100644
--- a/lisp/expand.el
+++ b/lisp/expand.el
@@ -1,6 +1,6 @@
 ;;; expand.el --- make abbreviations more usable  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Frederic Lepied <Frederic.Lepied@sugix.frmug.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/external-completion.el b/lisp/external-completion.el
index dd2710602fe..b171e27014c 100644
--- a/lisp/external-completion.el
+++ b/lisp/external-completion.el
@@ -1,6 +1,6 @@
 ;;; external-completion.el --- Let external tools control completion style  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Version: 0.1
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
diff --git a/lisp/ezimage.el b/lisp/ezimage.el
index ba3e5b1d369..8d5815c2f18 100644
--- a/lisp/ezimage.el
+++ b/lisp/ezimage.el
@@ -1,6 +1,6 @@
 ;;; ezimage.el --- Generalized Image management  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: file, tags, tools
diff --git a/lisp/face-remap.el b/lisp/face-remap.el
index c5f7af37406..d269d85301c 100644
--- a/lisp/face-remap.el
+++ b/lisp/face-remap.el
@@ -1,6 +1,6 @@
 ;;; face-remap.el --- Functions for managing `face-remapping-alist'  -*- 
lexical-binding: t -*-
 ;;
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Miles Bader <miles@gnu.org>
 ;; Keywords: faces, face remapping, display, user commands
diff --git a/lisp/facemenu.el b/lisp/facemenu.el
index 5066bf25c9d..50c2c91fcdb 100644
--- a/lisp/facemenu.el
+++ b/lisp/facemenu.el
@@ -1,6 +1,6 @@
 ;;; facemenu.el --- create a face menu for interactively adding fonts to text  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1994-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Boris Goldowsky <boris@gnu.org>
 ;; Keywords: faces
diff --git a/lisp/faces.el b/lisp/faces.el
index 8eaabbffc0e..c3a54a08a3d 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -1,6 +1,6 @@
 ;;; faces.el --- Lisp faces -*- lexical-binding: t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
@@ -651,11 +651,11 @@ Optional argument INHERIT is passed to `face-attribute'."
 If FACE is a face-alias, get the documentation for the target face."
   (let ((alias (get face 'face-alias)))
     (if alias
-        (let ((doc (get alias 'face-documentation)))
+        (let ((doc (documentation-property alias 'face-documentation)))
          (format "%s is an alias for the face `%s'.%s" face alias
                   (if doc (format "\n%s" doc)
                     "")))
-      (get face 'face-documentation))))
+      (documentation-property face 'face-documentation))))
 
 
 (defun set-face-documentation (face string)
diff --git a/lisp/ffap.el b/lisp/ffap.el
index 530e3da182e..3492dcbf17a 100644
--- a/lisp/ffap.el
+++ b/lisp/ffap.el
@@ -1,6 +1,6 @@
 ;;; ffap.el --- find file (or url) at point  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Michelangelo Grigni <mic@mathcs.emory.edu>
 ;; Maintainer: emacs-devel@gnu.org
@@ -152,15 +152,15 @@ schemes (e.g. \"ftp\"); in that case, only convert those 
URLs."
   :group 'ffap
   :version "24.3")
 
-(defcustom ffap-lax-url t
+(defcustom ffap-lax-url nil
   "If non-nil, allow lax URL matching.
 The default non-nil value might produce false URLs in C++ code
 with symbols like \"std::find\".  On the other hand, setting
 this to nil will disable recognition of URLs that are not
-well-formed, such as \"user@host\" or \"<user@host>\"."
+well-formed."
   :type 'boolean
   :group 'ffap
-  :version "25.2")                      ; nil -> t
+  :version "30.1")
 
 (defcustom ffap-ftp-default-user "anonymous"
   "User name in FTP file names generated by `ffap-host-to-filename'.
@@ -609,6 +609,13 @@ Looks at `ffap-ftp-default-user', returns \"\" for 
\"localhost\"."
    ((and ffap-url-unwrap-remote (ffap-url-unwrap-remote url)))
    (url)))
 
+(defun ffap-fixup-email (email)
+  "Clean up EMAIL and return it as a mailto: URL."
+  (when (stringp email)
+    (if (string-prefix-p "mailto:"; email)
+        email
+      (concat "mailto:"; email))))
+
 
 ;;; File Name Handling:
 
@@ -1571,6 +1578,7 @@ Uses the face `ffap' if it is defined, or else 
`highlight'."
           (ffap-fixup-url (or (ffap-url-at-point)
                               (ffap-gopher-at-point))))
       (ffap-file-at-point)             ; may yield url!
+      (ffap-fixup-email (thing-at-point 'email))
       (ffap-fixup-machine (ffap-machine-at-point))))
 
 (defun ffap-prompter (&optional guess suffix)
diff --git a/lisp/filecache.el b/lisp/filecache.el
index 42225509eca..86d5e65df06 100644
--- a/lisp/filecache.el
+++ b/lisp/filecache.el
@@ -1,6 +1,6 @@
 ;;; filecache.el --- find files using a pre-loaded cache  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1996, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Peter Breton <pbreton@cs.umb.edu>
 ;; Created: Sun Nov 10 1996
diff --git a/lisp/fileloop.el b/lisp/fileloop.el
index f58d00d9aa9..1fe40387096 100644
--- a/lisp/fileloop.el
+++ b/lisp/fileloop.el
@@ -1,6 +1,6 @@
 ;;; fileloop.el --- Operations on multiple files  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 
diff --git a/lisp/filenotify.el b/lisp/filenotify.el
index 03bd4e51485..4e289d564c9 100644
--- a/lisp/filenotify.el
+++ b/lisp/filenotify.el
@@ -1,6 +1,6 @@
 ;;; filenotify.el --- watch files for changes on disk  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 
diff --git a/lisp/files-x.el b/lisp/files-x.el
index a8d525ec5ff..f70be5f7ff3 100644
--- a/lisp/files-x.el
+++ b/lisp/files-x.el
@@ -1,6 +1,6 @@
 ;;; files-x.el --- extended file handling commands  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Juri Linkov <juri@jurta.org>
 ;; Maintainer: emacs-devel@gnu.org
@@ -791,6 +791,7 @@ definitions that aren't listed in VARIABLES."
     (setq variables (nreverse existing-variables)))
   (connection-local-set-profile-variables profile variables))
 
+;;;###autoload
 (defun hack-connection-local-variables (criteria)
   "Read connection-local variables according to CRITERIA.
 Store the connection-local variables in buffer local
@@ -925,18 +926,54 @@ earlier in the `setq-connection-local'.  The return value 
of the
           connection-local-criteria
           connection-local-profile-name-for-setq)))))
 
+;;;###autoload
+(defmacro connection-local-p (variable &optional application)
+  "Non-nil if VARIABLE has a connection-local binding in `default-directory'.
+`default-directory' must be a remote file name.
+If APPLICATION is nil, the value of
+`connection-local-default-application' is used."
+  (declare (debug (symbolp &optional form)))
+  (unless (symbolp variable)
+    (signal 'wrong-type-argument (list 'symbolp variable)))
+  `(let ((criteria
+          (connection-local-criteria-for-default-directory ,application))
+         connection-local-variables-alist file-local-variables-alist)
+     (when criteria
+       (hack-connection-local-variables criteria)
+       (and (assq ',variable connection-local-variables-alist) t))))
+
+;;;###autoload
+(defmacro connection-local-value (variable &optional application)
+  "Return connection-local VARIABLE for APPLICATION in `default-directory'.
+`default-directory' must be a remote file name.
+If APPLICATION is nil, the value of
+`connection-local-default-application' is used.
+If VARIABLE does not have a connection-local binding, the return
+value is the default binding of the variable."
+  (declare (debug (symbolp &optional form)))
+  (unless (symbolp variable)
+    (signal 'wrong-type-argument (list 'symbolp variable)))
+  `(let ((criteria
+          (connection-local-criteria-for-default-directory ,application))
+         connection-local-variables-alist file-local-variables-alist)
+     (if (not criteria)
+         ,variable
+       (hack-connection-local-variables criteria)
+       (if-let ((result (assq ',variable connection-local-variables-alist)))
+           (cdr result)
+         ,variable))))
+
 ;;;###autoload
 (defun path-separator ()
   "The connection-local value of `path-separator'."
-  (with-connection-local-variables path-separator))
+  (connection-local-value path-separator))
 
 ;;;###autoload
 (defun null-device ()
   "The connection-local value of `null-device'."
-  (with-connection-local-variables null-device))
+  (connection-local-value null-device))
 
 
-
 (provide 'files-x)
 
 ;;; files-x.el ends here
diff --git a/lisp/files.el b/lisp/files.el
index 1cdcec23b11..9c8914bfc50 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -1,6 +1,6 @@
 ;;; files.el --- file input and output commands for Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1985-1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1987, 1992-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Package: emacs
@@ -1246,6 +1246,29 @@ See `load-file' for a different interface to `load'."
   (interactive (list (read-library-name)))
   (load library))
 
+(defun require-with-check (feature &optional filename noerror)
+  "If FEATURE is not already loaded, load it from FILENAME.
+This is like `require' except if FEATURE is already a member of the list
+`features’, then we check if this was provided by a different file than the
+one that we would load now (presumably because `load-path' has been
+changed since the file was loaded).
+If it's the case, we either signal an error (the default), or forcibly reload
+the new file (if NOERROR is equal to `reload'), or otherwise emit a warning."
+  (let ((lh load-history)
+        (res (require feature filename (if (eq noerror 'reload) nil noerror))))
+    ;; If the `feature' was not yet provided, `require' just loaded the right
+    ;; file, so we're done.
+    (when (eq lh load-history)
+      ;; If `require' did nothing, we need to make sure that was warranted.
+      (let ((fn (locate-file (or filename (symbol-name feature))
+                             load-path (get-load-suffixes))))
+        (cond
+         ((assoc fn load-history) nil)  ;We loaded the right file.
+         ((eq noerror 'reload) (load fn nil 'nomessage))
+         (t (funcall (if noerror #'warn #'error)
+                     "Feature provided by other file: %S" feature)))))
+    res))
+
 (defun file-remote-p (file &optional identification connected)
   "Test whether FILE specifies a location on a remote system.
 A file is considered remote if accessing it is likely to
@@ -2185,37 +2208,33 @@ and others are ignored.  PREDICATE is called with the 
buffer as
 the only argument, but not with the buffer as the current buffer.
 
 If there is no such live buffer, return nil."
-  (let ((predicate (or predicate #'identity))
-        (truename (abbreviate-file-name (file-truename filename))))
-    (or (let ((buf (get-file-buffer filename)))
-          (when (and buf (funcall predicate buf)) buf))
-        (let ((list (buffer-list)) found)
-          (while (and (not found) list)
-            (with-current-buffer (car list)
-              (if (and buffer-file-name
-                       (string= buffer-file-truename truename)
-                       (funcall predicate (current-buffer)))
-                  (setq found (car list))))
-            (setq list (cdr list)))
-          found)
-        (let* ((attributes (file-attributes truename))
-               (number (file-attribute-file-identifier attributes))
-               (list (buffer-list)) found)
-          (and buffer-file-numbers-unique
-               (car-safe number)       ;Make sure the inode is not just nil.
-               (while (and (not found) list)
-                 (with-current-buffer (car list)
-                   (if (and buffer-file-name
-                            (equal buffer-file-number number)
-                            ;; Verify this buffer's file number
-                            ;; still belongs to its file.
-                            (file-exists-p buffer-file-name)
-                            (equal (file-attributes buffer-file-truename)
-                                   attributes)
-                            (funcall predicate (current-buffer)))
-                       (setq found (car list))))
-                 (setq list (cdr list))))
-          found))))
+  (or (let ((buf (get-file-buffer filename)))
+        (when (and buf (or (not predicate) (funcall predicate buf))) buf))
+      (let ((truename (abbreviate-file-name (file-truename filename))))
+        (or
+         (let ((buf (get-truename-buffer truename)))
+           (when (and buf (buffer-local-value 'buffer-file-name buf)
+                      (or (not predicate) (funcall predicate buf)))
+             buf))
+         (let* ((attributes (file-attributes truename))
+                (number (file-attribute-file-identifier attributes)))
+           (and buffer-file-numbers-unique
+                (car-safe number)       ;Make sure the inode is not just nil.
+                (let* ((buf (find-buffer 'buffer-file-number number))
+                       (buf-file-name
+                        (and buf (buffer-local-value 'buffer-file-name buf))))
+                  (when (and buf-file-name
+                             ;; Verify this buffer's file number
+                             ;; still belongs to its file.
+                             (file-exists-p buf-file-name)
+                             (equal (file-attributes
+                                     (buffer-local-value
+                                      'buffer-file-truename buf))
+                                    attributes)
+                             (or (not predicate)
+                                 (funcall predicate buf)))
+                    buf))))))))
+
 
 (defcustom find-file-wildcards t
   "Non-nil means file-visiting commands should handle wildcards.
@@ -3040,7 +3059,7 @@ 
ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\|CBR\\|7Z\\|SQUASHFS\\)\\'" .
      ("\\.docbook\\'" . sgml-mode)
      ("\\.com\\'" . dcl-mode)
      ("/config\\.\\(?:bat\\|log\\)\\'" . fundamental-mode)
-     ("/\\.\\(authinfo\\|netrc\\)\\'" . authinfo-mode)
+     ("/\\.?\\(authinfo\\|netrc\\)\\'" . authinfo-mode)
      ;; Windows candidates may be opened case sensitively on Unix
      
("\\.\\(?:[iI][nN][iI]\\|[lL][sS][tT]\\|[rR][eE][gG]\\|[sS][yY][sS]\\)\\'" . 
conf-mode)
      ("\\.la\\'" . conf-unix-mode)
@@ -7083,11 +7102,19 @@ auto-save file, if that is more recent than the visited 
file."
            #'(lambda (window _value)
                (with-selected-window window
                  (unwind-protect
-                     (yes-or-no-p (format "Recover auto save file %s? " 
file-name))
+                      (let ((prompt (format "Recover auto save file %s? " 
file-name))
+                            (choices
+                             '(("yes" ?y "recover auto save file")
+                               ("no" ?n "don't recover auto save file")
+                               ("diff" ?= "show changes between auto save file 
and current file")))
+                            ans)
+                        (while (equal "diff" (setq ans (read-answer prompt 
choices)))
+                          (diff file file-name))
+                        (equal ans "yes"))
                    (when (window-live-p window)
                      (quit-restore-window window 'kill)))))
            (with-current-buffer standard-output
-             (let ((switches dired-listing-switches))
+             (let ((switches (connection-local-value dired-listing-switches)))
                (if (file-symlink-p file)
                    (setq switches (concat switches " -L")))
                ;; Use insert-directory-safely, not insert-directory,
@@ -7139,7 +7166,7 @@ Then you'll be asked about a number of files to recover."
         ;; hook.
         (dired-mode-hook (delete 'dired-omit-mode dired-mode-hook)))
     (dired (concat auto-save-list-file-prefix "*")
-          (concat dired-listing-switches " -t")))
+          (concat (connection-local-value dired-listing-switches) " -t")))
   (use-local-map (nconc (make-sparse-keymap) (current-local-map)))
   (define-key (current-local-map) "\C-c\C-c" 'recover-session-finish)
   (save-excursion
@@ -7539,35 +7566,42 @@ default directory.  However, if FULL is non-nil, they 
are absolute."
           ;; if DIRPART contains wildcards.
           (dirs (if (and dirpart
                          (string-match "[[*?]" (file-local-name dirpart)))
-                    (mapcar 'file-name-as-directory
+                    (mapcar #'file-name-as-directory
                             (file-expand-wildcards
                               (directory-file-name dirpart) nil regexp))
                   (list dirpart)))
           contents)
-      (dolist (dir dirs)
+      (dolist (dir (nreverse dirs))
        (when (or (null dir)    ; Possible if DIRPART is not wild.
                  (file-accessible-directory-p dir))
-         (let ((this-dir-contents
-                ;; Filter out "." and ".."
-                (delq nil
-                       (mapcar (lambda (name)
-                                 (unless (string-match "\\`\\.\\.?\\'"
-                                                       (file-name-nondirectory 
name))
-                                   name))
-                              (directory-files
-                                (or dir ".") full
-                                (if regexp
-                                    ;; We're matching each file name
-                                    ;; element separately.
-                                    (concat "\\`" nondir "\\'")
-                                 (wildcard-to-regexp nondir)))))))
-           (setq contents
-                 (nconc
-                  (if (and dir (not full))
-                       (mapcar (lambda (name) (concat dir name))
-                              this-dir-contents)
-                    this-dir-contents)
-                  contents)))))
+          (if (equal "" nondir)
+              ;; `nondir' is "" when the pattern ends in "/".  Basically ""
+              ;; refers to the directory itself, like ".", but it's not
+              ;; among the names returned by `directory-files', so we have
+              ;; to special-case it.
+              (push (or dir nondir) contents)
+           (let ((this-dir-contents
+                  ;; Filter out "." and ".."
+                  (delq nil
+                         (mapcar (lambda (name)
+                                   (unless (string-match "\\`\\.\\.?\\'"
+                                                         
(file-name-nondirectory
+                                                          name))
+                                     name))
+                                (directory-files
+                                  (or dir ".") full
+                                  (if regexp
+                                      ;; We're matching each file name
+                                      ;; element separately.
+                                      (concat "\\`" nondir "\\'")
+                                  (wildcard-to-regexp nondir)))))))
+             (setq contents
+                   (nconc
+                    (if (and dir (not full))
+                        (mapcar (lambda (name) (concat dir name))
+                                this-dir-contents)
+                      this-dir-contents)
+                    contents))))))
       contents)))
 
 (defcustom find-sibling-rules nil
@@ -7757,7 +7791,7 @@ need to be passed verbatim to shell commands."
     (purecopy "ls"))
   "Absolute or relative name of the `ls'-like program.
 This is used by `insert-directory' and `dired-insert-directory'
-(thus, also by `dired').  For Dired, this should ideally point to
+\(thus, also by `dired').  For Dired, this should ideally point to
 GNU ls, or another version of ls that supports the \"--dired\"
 flag.  See `dired-use-ls-dired'.
 
@@ -7773,6 +7807,16 @@ installing GNU coreutils using something like ports or 
Homebrew."
   :initialize #'custom-initialize-delay
   :version "30.1")
 
+(defun files--use-insert-directory-program-p ()
+  "Return non-nil if we should use `insert-directory-program'.
+Return nil if we should prefer `ls-lisp' instead."
+  ;; FIXME: Should we also check `file-accessible-directory-p' so we
+  ;; automatically redirect to ls-lisp when operating on magic file names?
+  (and (if (boundp 'ls-lisp-use-insert-directory-program)
+           ls-lisp-use-insert-directory-program
+         t)
+       insert-directory-program))
+
 (defcustom directory-free-space-program (purecopy "df")
   "Program to get the amount of free space on a file system.
 We assume the output has the format of `df'.
@@ -7965,9 +8009,11 @@ Optional third arg WILDCARD means treat FILE as shell 
wildcard.
 Optional fourth arg FULL-DIRECTORY-P means file is a directory and
 switches do not contain `d', so that a full listing is expected.
 
-This works by running a directory listing program
-whose name is in the variable `insert-directory-program'.
-If WILDCARD, it also runs the shell specified by `shell-file-name'.
+Depending on the value of `ls-lisp-use-insert-directory-program'
+this works either using a Lisp emulation of the \"ls\" program
+or by running a directory listing program
+whose name is in the variable `insert-directory-program'
+\(and if WILDCARD, it also runs the shell specified by `shell-file-name').
 
 When SWITCHES contains the long `--dired' option, this function
 treats it specially, for the sake of dired.  However, the
@@ -7976,184 +8022,191 @@ normally equivalent short `-D' option is just passed 
on to
   ;; We need the directory in order to find the right handler.
   (let ((handler (find-file-name-handler (expand-file-name file)
                                         'insert-directory)))
-    (if handler
-       (funcall handler 'insert-directory file switches
-                wildcard full-directory-p)
-       (let (result (beg (point)))
-
-         ;; Read the actual directory using `insert-directory-program'.
-         ;; RESULT gets the status code.
-         (let* (;; We at first read by no-conversion, then after
-                ;; putting text property `dired-filename, decode one
-                ;; bunch by one to preserve that property.
-                (coding-system-for-read 'no-conversion)
-                ;; This is to control encoding the arguments in call-process.
-                (coding-system-for-write
-                 (and enable-multibyte-characters
-                      (or file-name-coding-system
-                          default-file-name-coding-system))))
-           (setq result
-                 (if wildcard
-                     ;; If the wildcard is just in the file part, then run ls 
in
-                      ;; the directory part of the file pattern using the last
-                      ;; component as argument.  Otherwise, run ls in the 
longest
-                      ;; subdirectory of the directory part free of wildcards; 
use
-                      ;; the remaining of the file pattern as argument.
-                     (let* ((dir-wildcard (insert-directory-wildcard-in-dir-p 
file))
-                             (default-directory
-                               (cond (dir-wildcard (car dir-wildcard))
-                                     (t
-                                     (if (file-name-absolute-p file)
-                                         (file-name-directory file)
-                                       (file-name-directory (expand-file-name 
file))))))
-                            (pattern (if dir-wildcard (cdr dir-wildcard) 
(file-name-nondirectory file))))
-                       ;; NB since switches is passed to the shell, be
-                       ;; careful of malicious values, eg "-l;reboot".
-                       ;; See eg dired-safe-switches-p.
-                       (call-process
-                        shell-file-name nil t nil
-                        shell-command-switch
-                        (concat (if (memq system-type '(ms-dos windows-nt))
-                                    ""
-                                  "\\") ; Disregard Unix shell aliases!
-                                insert-directory-program
-                                " -d "
-                                (if (stringp switches)
-                                    switches
-                                  (mapconcat 'identity switches " "))
-                                " -- "
-                                ;; Quote some characters that have
-                                ;; special meanings in shells; but
-                                ;; don't quote the wildcards--we want
-                                ;; them to be special.  We also
-                                ;; currently don't quote the quoting
-                                ;; characters in case people want to
-                                ;; use them explicitly to quote
-                                ;; wildcard characters.
-                                (shell-quote-wildcard-pattern pattern))))
-                   ;; SunOS 4.1.3, SVr4 and others need the "." to list the
-                   ;; directory if FILE is a symbolic link.
-                   (unless full-directory-p
-                     (setq switches
-                           (cond
-                             ((stringp switches) (concat switches " -d"))
-                             ((member "-d" switches) switches)
-                             (t (append switches '("-d"))))))
-                   (if (string-match "\\`~" file)
-                       (setq file (expand-file-name file)))
-                   (apply 'call-process
-                          insert-directory-program nil t nil
-                          (append
-                           (if (listp switches) switches
-                             (unless (equal switches "")
-                               ;; Split the switches at any spaces so we can
-                               ;; pass separate options as separate args.
-                               (split-string-and-unquote switches)))
-                           ;; Avoid lossage if FILE starts with `-'.
-                           '("--")
-                           (list file))))))
-
-         ;; If we got "//DIRED//" in the output, it means we got a real
-         ;; directory listing, even if `ls' returned nonzero.
-         ;; So ignore any errors.
-         (when (if (stringp switches)
-                   (string-match "--dired\\>" switches)
-                 (member "--dired" switches))
-           (save-excursion
-             (forward-line -2)
-             (when (looking-at "//SUBDIRED//")
-               (forward-line -1))
-             (if (looking-at "//DIRED//")
-                 (setq result 0))))
-
-         (when (and (not (eq 0 result))
-                    (eq insert-directory-ls-version 'unknown))
-           ;; The first time ls returns an error,
-           ;; find the version numbers of ls,
-           ;; and set insert-directory-ls-version
-           ;; to > if it is more than 5.2.1, < if it is less, nil if it
-           ;; is equal or if the info cannot be obtained.
-           ;; (That can mean it isn't GNU ls.)
-           (let ((version-out
-                  (with-temp-buffer
-                    (call-process "ls" nil t nil "--version")
-                    (buffer-string))))
-             (if (string-match "ls (.*utils) \\([0-9.]*\\)$" version-out)
-                 (let* ((version (match-string 1 version-out))
-                        (split (split-string version "[.]"))
-                        (numbers (mapcar 'string-to-number split))
-                        (min '(5 2 1))
-                        comparison)
-                   (while (and (not comparison) (or numbers min))
-                     (cond ((null min)
-                            (setq comparison '>))
-                           ((null numbers)
-                            (setq comparison '<))
-                           ((> (car numbers) (car min))
-                            (setq comparison '>))
-                           ((< (car numbers) (car min))
-                            (setq comparison '<))
-                           (t
-                            (setq numbers (cdr numbers)
-                                  min (cdr min)))))
-                   (setq insert-directory-ls-version (or comparison '=)))
-               (setq insert-directory-ls-version nil))))
-
-         ;; For GNU ls versions 5.2.2 and up, ignore minor errors.
-         (when (and (eq 1 result) (eq insert-directory-ls-version '>))
-           (setq result 0))
-
-         ;; If `insert-directory-program' failed, signal an error.
-         (unless (eq 0 result)
-           ;; Delete the error message it may have output.
-           (delete-region beg (point))
-           ;; On non-Posix systems, we cannot open a directory, so
-           ;; don't even try, because that will always result in
-           ;; the ubiquitous "Access denied".  Instead, show the
-           ;; command line so the user can try to guess what went wrong.
-           (if (and (file-directory-p file)
-                    (memq system-type '(ms-dos windows-nt)))
-               (error
-                "Reading directory: \"%s %s -- %s\" exited with status %s"
-                insert-directory-program
-                (if (listp switches) (concat switches) switches)
-                file result)
-             ;; Unix.  Access the file to get a suitable error.
-             (access-file file "Reading directory")
-             (error "Listing directory failed but `access-file' worked")))
-          (insert-directory-clean beg switches)
-         ;; Now decode what read if necessary.
-         (let ((coding (or coding-system-for-read
-                           file-name-coding-system
-                           default-file-name-coding-system
-                           'undecided))
-               coding-no-eol
-               val pos)
-           (when (and enable-multibyte-characters
-                      (not (memq (coding-system-base coding)
-                                 '(raw-text no-conversion))))
-             ;; If no coding system is specified or detection is
-             ;; requested, detect the coding.
-             (if (eq (coding-system-base coding) 'undecided)
-                 (setq coding (detect-coding-region beg (point) t)))
-             (if (not (eq (coding-system-base coding) 'undecided))
-                 (save-restriction
-                   (setq coding-no-eol
-                         (coding-system-change-eol-conversion coding 'unix))
-                   (narrow-to-region beg (point))
-                   (goto-char (point-min))
-                   (while (not (eobp))
-                     (setq pos (point)
-                           val (get-text-property (point) 'dired-filename))
-                     (goto-char (next-single-property-change
-                                 (point) 'dired-filename nil (point-max)))
-                     ;; Force no eol conversion on a file name, so
-                     ;; that CR is preserved.
-                     (decode-coding-region pos (point)
-                                           (if val coding-no-eol coding))
-                     (if val
-                         (put-text-property pos (point)
-                                            'dired-filename t)))))))))))
+    (cond
+     (handler
+      (funcall handler 'insert-directory file switches
+              wildcard full-directory-p))
+     ((not (files--use-insert-directory-program-p))
+      (require 'ls-lisp)
+      (declare-function ls-lisp--insert-directory "ls-lisp")
+      (ls-lisp--insert-directory file switches wildcard full-directory-p))
+     (t
+      (let (result (beg (point)))
+
+       ;; Read the actual directory using `insert-directory-program'.
+       ;; RESULT gets the status code.
+       (let* (;; We at first read by no-conversion, then after
+              ;; putting text property `dired-filename, decode one
+              ;; bunch by one to preserve that property.
+              (coding-system-for-read 'no-conversion)
+              ;; This is to control encoding the arguments in call-process.
+              (coding-system-for-write
+               (and enable-multibyte-characters
+                    (or file-name-coding-system
+                        default-file-name-coding-system))))
+         (setq result
+               (if wildcard
+                   ;; If the wildcard is just in the file part, then run ls in
+                    ;; the directory part of the file pattern using the last
+                    ;; component as argument.  Otherwise, run ls in the longest
+                    ;; subdirectory of the directory part free of wildcards; 
use
+                    ;; the remaining of the file pattern as argument.
+                   (let* ((dir-wildcard (insert-directory-wildcard-in-dir-p 
file))
+                           (default-directory
+                            (cond (dir-wildcard (car dir-wildcard))
+                                  (t
+                                  (if (file-name-absolute-p file)
+                                      (file-name-directory file)
+                                    (file-name-directory (expand-file-name 
file))))))
+                          (pattern (if dir-wildcard (cdr dir-wildcard) 
(file-name-nondirectory file))))
+                     ;; NB since switches is passed to the shell, be
+                     ;; careful of malicious values, eg "-l;reboot".
+                     ;; See eg dired-safe-switches-p.
+                     (call-process
+                      shell-file-name nil t nil
+                      shell-command-switch
+                      (concat (if (memq system-type '(ms-dos windows-nt))
+                                  ""
+                                "\\") ; Disregard Unix shell aliases!
+                              insert-directory-program
+                              " -d "
+                              (if (stringp switches)
+                                  switches
+                                (mapconcat #'identity switches " "))
+                              " -- "
+                              ;; Quote some characters that have
+                              ;; special meanings in shells; but
+                              ;; don't quote the wildcards--we want
+                              ;; them to be special.  We also
+                              ;; currently don't quote the quoting
+                              ;; characters in case people want to
+                              ;; use them explicitly to quote
+                              ;; wildcard characters.
+                              (shell-quote-wildcard-pattern pattern))))
+                 ;; SunOS 4.1.3, SVr4 and others need the "." to list the
+                 ;; directory if FILE is a symbolic link.
+                 (unless full-directory-p
+                   (setq switches
+                         (cond
+                           ((stringp switches) (concat switches " -d"))
+                           ((member "-d" switches) switches)
+                           (t (append switches '("-d"))))))
+                 (if (string-match "\\`~" file)
+                     (setq file (expand-file-name file)))
+                 (apply #'call-process
+                        insert-directory-program nil t nil
+                        (append
+                         (if (listp switches) switches
+                           (unless (equal switches "")
+                             ;; Split the switches at any spaces so we can
+                             ;; pass separate options as separate args.
+                             (split-string-and-unquote switches)))
+                         ;; Avoid lossage if FILE starts with `-'.
+                         '("--")
+                         (list file))))))
+
+       ;; If we got "//DIRED//" in the output, it means we got a real
+       ;; directory listing, even if `ls' returned nonzero.
+       ;; So ignore any errors.
+       (when (if (stringp switches)
+                 (string-match "--dired\\>" switches)
+               (member "--dired" switches))
+         (save-excursion
+           (forward-line -2)
+           (when (looking-at "//SUBDIRED//")
+             (forward-line -1))
+           (if (looking-at "//DIRED//")
+               (setq result 0))))
+
+       (when (and (not (eq 0 result))
+                  (eq insert-directory-ls-version 'unknown))
+         ;; The first time ls returns an error,
+         ;; find the version numbers of ls,
+         ;; and set insert-directory-ls-version
+         ;; to > if it is more than 5.2.1, < if it is less, nil if it
+         ;; is equal or if the info cannot be obtained.
+         ;; (That can mean it isn't GNU ls.)
+         (let ((version-out
+                (with-temp-buffer
+                  (call-process "ls" nil t nil "--version")
+                  (buffer-string))))
+           (setq insert-directory-ls-version
+                 (if (string-match "ls (.*utils) \\([0-9.]*\\)$" version-out)
+                     (let* ((version (match-string 1 version-out))
+                            (split (split-string version "[.]"))
+                            (numbers (mapcar #'string-to-number split))
+                            (min '(5 2 1))
+                            comparison)
+                       (while (and (not comparison) (or numbers min))
+                         (cond ((null min)
+                                (setq comparison #'>))
+                               ((null numbers)
+                                (setq comparison #'<))
+                               ((> (car numbers) (car min))
+                                (setq comparison #'>))
+                               ((< (car numbers) (car min))
+                                (setq comparison #'<))
+                               (t
+                                (setq numbers (cdr numbers)
+                                      min (cdr min)))))
+                       (or comparison #'=))
+                   nil))))
+
+       ;; For GNU ls versions 5.2.2 and up, ignore minor errors.
+       (when (and (eq 1 result) (eq insert-directory-ls-version #'>))
+         (setq result 0))
+
+       ;; If `insert-directory-program' failed, signal an error.
+       (unless (eq 0 result)
+         ;; Delete the error message it may have output.
+         (delete-region beg (point))
+         ;; On non-Posix systems, we cannot open a directory, so
+         ;; don't even try, because that will always result in
+         ;; the ubiquitous "Access denied".  Instead, show the
+         ;; command line so the user can try to guess what went wrong.
+         (if (and (file-directory-p file)
+                  (memq system-type '(ms-dos windows-nt)))
+             (error
+              "Reading directory: \"%s %s -- %s\" exited with status %s"
+              insert-directory-program
+              (if (listp switches) (concat switches) switches)
+              file result)
+           ;; Unix.  Access the file to get a suitable error.
+           (access-file file "Reading directory")
+           (error "Listing directory failed but `access-file' worked")))
+        (insert-directory-clean beg switches)
+       ;; Now decode what read if necessary.
+       (let ((coding (or coding-system-for-read
+                         file-name-coding-system
+                         default-file-name-coding-system
+                         'undecided))
+             coding-no-eol
+             val pos)
+         (when (and enable-multibyte-characters
+                    (not (memq (coding-system-base coding)
+                               '(raw-text no-conversion))))
+           ;; If no coding system is specified or detection is
+           ;; requested, detect the coding.
+           (if (eq (coding-system-base coding) 'undecided)
+               (setq coding (detect-coding-region beg (point) t)))
+           (if (not (eq (coding-system-base coding) 'undecided))
+               (save-restriction
+                 (setq coding-no-eol
+                       (coding-system-change-eol-conversion coding 'unix))
+                 (narrow-to-region beg (point))
+                 (goto-char (point-min))
+                 (while (not (eobp))
+                   (setq pos (point)
+                         val (get-text-property (point) 'dired-filename))
+                   (goto-char (next-single-property-change
+                               (point) 'dired-filename nil (point-max)))
+                   ;; Force no eol conversion on a file name, so
+                   ;; that CR is preserved.
+                   (decode-coding-region pos (point)
+                                         (if val coding-no-eol coding))
+                   (if val
+                       (put-text-property pos (point)
+                                          'dired-filename t))))))))))))
 
 (defun insert-directory-adj-pos (pos error-lines)
   "Convert `ls --dired' file name position value POS to a buffer position.
diff --git a/lisp/filesets.el b/lisp/filesets.el
index 639b108ac03..4e2de8fed1b 100644
--- a/lisp/filesets.el
+++ b/lisp/filesets.el
@@ -1,6 +1,6 @@
 ;;; filesets.el --- handle group of files  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Thomas Link <sanobast-emacs@yahoo.de>
 ;; Maintainer: emacs-devel@gnu.org
@@ -286,7 +286,7 @@ See `easy-menu-add-item' for documentation."
   )
 
 (defcustom filesets-menu-in-menu nil
-  "Use that instead of `current-menubar' as the menu to change.
+  "Use that instead of `current-global-map' as the menu to change.
 See `easy-menu-add-item' for documentation."
   :set #'filesets-set-default
   :type 'sexp)
@@ -1648,7 +1648,17 @@ Assume MODE (see `filesets-entry-mode'), if provided."
                                (filesets-entry-get-master entry)))))
                  (cons entry (filesets-ingroup-cache-get entry))))
               (:tree
-                (let* ((dirpatt (filesets-entry-get-tree entry))
+                ;; Warning: ENTRY here could be of at least two
+                ;; differente forms, either
+                ;;    (NAME (:tree DIRECTORY PATTERN))
+                ;; or
+                ;;    (DIRECTORY PATTERN)
+                ;; The latter happens when opening a tree fileset
+                ;; from the Filesets menu.  We need to support both
+                ;; of these forms!
+                (let* ((dirpatt (if (consp (nth 1 entry))
+                                    (filesets-entry-get-tree entry)
+                                  entry))
                        (dir (nth 0 dirpatt))
                        (patt (nth 1 dirpatt))
                        (depth (or (filesets-entry-get-tree-max-level entry)
@@ -1757,7 +1767,7 @@ If no fileset name is provided, prompt for NAME."
       (add-to-list 'filesets-data (list name '(:files)))
       (message
        (substitute-command-keys
-        "Fileset %s created.  Call `\\[filesets-save-config]' to save.")
+        "Fileset %s created.  Call \\[filesets-save-config] to save.")
        name)
       (car filesets-data))))))
     (if entry
diff --git a/lisp/find-cmd.el b/lisp/find-cmd.el
index 6e18113f69f..a148e59bd5c 100644
--- a/lisp/find-cmd.el
+++ b/lisp/find-cmd.el
@@ -1,6 +1,6 @@
 ;;; find-cmd.el --- Build a valid find(1) command with sexps  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Philip Jackson <phil@shellarchive.co.uk>
 ;; Version: 0.6
diff --git a/lisp/find-dired.el b/lisp/find-dired.el
index 48408d35499..41581cc7900 100644
--- a/lisp/find-dired.el
+++ b/lisp/find-dired.el
@@ -1,6 +1,6 @@
 ;;; find-dired.el --- run a `find' command and dired the output  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: Roland McGrath <roland@gnu.org>,
 ;;        Sebastian Kremer <sk@thp.uni-koeln.de>
diff --git a/lisp/find-file.el b/lisp/find-file.el
index 05459c3643d..c4c61e6abe6 100644
--- a/lisp/find-file.el
+++ b/lisp/find-file.el
@@ -4,7 +4,7 @@
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: c, matching, tools
 
-;; Copyright (C) 1994-1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/find-lisp.el b/lisp/find-lisp.el
index dd91d963c3a..0b6f9d35ad8 100644
--- a/lisp/find-lisp.el
+++ b/lisp/find-lisp.el
@@ -4,7 +4,7 @@
 ;; Created: Fri Mar 26 1999
 ;; Keywords: unix
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/finder.el b/lisp/finder.el
index 4e3a3566ce9..1cf607c03c0 100644
--- a/lisp/finder.el
+++ b/lisp/finder.el
@@ -1,6 +1,6 @@
 ;;; finder.el --- topic & keyword-based code finder  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric S. Raymond <esr@thyrsus.com>
 ;; Created: 16 Jun 1992
@@ -68,10 +68,11 @@
     (processes . "processes, subshells, and compilation")
     (terminals . "text terminals (ttys)")
     (tex       . "the TeX document formatter")
+    (text      . "editing text files")
     (tools     . "programming tools")
     (unix      . "UNIX feature interfaces and emulators")
     (vc                . "version control")
-    (wp                . "word processing"))
+    (wp                . "use keyword `text' instead; this keyword is 
obsolete"))
   "Association list of the standard \"Keywords:\" headers.
 Each element has the form (KEYWORD . DESCRIPTION).")
 
diff --git a/lisp/flow-ctrl.el b/lisp/flow-ctrl.el
index 31209e48acf..55ffe1cf14f 100644
--- a/lisp/flow-ctrl.el
+++ b/lisp/flow-ctrl.el
@@ -1,6 +1,6 @@
 ;;; flow-ctrl.el --- help for lusers on cu(1) or ttys with wired-in ^S/^Q flow 
control  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1990-1991, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1990-1991, 1994, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Kevin Gallagher
diff --git a/lisp/foldout.el b/lisp/foldout.el
index ace242ffbc7..495ce4339f7 100644
--- a/lisp/foldout.el
+++ b/lisp/foldout.el
@@ -1,6 +1,6 @@
 ;;; foldout.el --- folding extensions for outline-mode and outline-minor-mode  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Kevin Broadey <KevinB@bartley.demon.co.uk>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/follow.el b/lisp/follow.el
index 7d64161ca33..ce40317ca59 100644
--- a/lisp/follow.el
+++ b/lisp/follow.el
@@ -1,6 +1,6 @@
 ;;; follow.el --- synchronize windows showing the same buffer  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1995-1997, 1999, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1995-1997, 1999, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Anders Lindgren
@@ -413,8 +413,8 @@ being able to use 144 or 216 lines instead of the normal 
72... (your
 mileage may vary).
 
 To split one large window into two side-by-side windows, the commands
-`\\[split-window-right]' or \
-`\\[follow-delete-other-windows-and-split]' can be used.
+\\[split-window-right] or \
+\\[follow-delete-other-windows-and-split] can be used.
 
 Only windows displayed in the same frame follow each other.
 
diff --git a/lisp/font-core.el b/lisp/font-core.el
index 4056fbdc954..7ef0fae60c0 100644
--- a/lisp/font-core.el
+++ b/lisp/font-core.el
@@ -1,6 +1,6 @@
 ;;; font-core.el --- Core interface to font-lock  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: languages, faces
diff --git a/lisp/font-lock.el b/lisp/font-lock.el
index 3df63f82fa1..7b077a826bf 100644
--- a/lisp/font-lock.el
+++ b/lisp/font-lock.el
@@ -1,6 +1,6 @@
 ;;; font-lock.el --- Electric font lock mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: Jamie Zawinski
 ;;     Richard Stallman
diff --git a/lisp/format-spec.el b/lisp/format-spec.el
index 2e76ecc0f8f..cf34017b994 100644
--- a/lisp/format-spec.el
+++ b/lisp/format-spec.el
@@ -1,6 +1,6 @@
 ;;; format-spec.el --- format arbitrary formatting strings -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: tools
diff --git a/lisp/format.el b/lisp/format.el
index 89a83c3cee2..34bd30e83a5 100644
--- a/lisp/format.el
+++ b/lisp/format.el
@@ -1,6 +1,6 @@
 ;;; format.el --- read and save files in multiple formats  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1994-1995, 1997, 1999, 2001-2023 Free Software
+;; Copyright (C) 1994-1995, 1997, 1999, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Boris Goldowsky <boris@gnu.org>
diff --git a/lisp/forms.el b/lisp/forms.el
index 73b95989e5c..009667af273 100644
--- a/lisp/forms.el
+++ b/lisp/forms.el
@@ -1,6 +1,6 @@
 ;;; forms.el --- Forms mode: edit a file as a form to fill in  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
 
 ;; Author: Johan Vromans <jvromans@squirrel.nl>
 
@@ -343,7 +343,7 @@ suitable for forms processing.")
 
 (defvar forms-write-file-filter nil
   "The name of a function that is called before writing the data file.
-This can be used to undo the effects of `form-read-file-hook'.")
+This can be used to undo the effects of `form-read-file-filter'.")
 
 (defvar forms-new-record-filter nil
   "The name of a function that is called when a new record is created.")
diff --git a/lisp/frame.el b/lisp/frame.el
index 2452f7f8d4a..d2376f1e339 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -1,6 +1,6 @@
 ;;; frame.el --- multi-frame management independent of window systems  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1993-1994, 1996-1997, 2000-2023 Free Software
+;; Copyright (C) 1993-1994, 1996-1997, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/frameset.el b/lisp/frameset.el
index 224746bbfe3..436e51905fb 100644
--- a/lisp/frameset.el
+++ b/lisp/frameset.el
@@ -1,6 +1,6 @@
 ;;; frameset.el --- save and restore frame and window setup -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Juanma Barranquero <lekktu@gmail.com>
 ;; Keywords: convenience
diff --git a/lisp/fringe.el b/lisp/fringe.el
index b5ab4f9f605..a64ea4294ad 100644
--- a/lisp/fringe.el
+++ b/lisp/fringe.el
@@ -1,6 +1,6 @@
 ;;; fringe.el --- fringe setup and control  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/generic-x.el b/lisp/generic-x.el
index 7e5ae90ff9a..373bfad92dd 100644
--- a/lisp/generic-x.el
+++ b/lisp/generic-x.el
@@ -1,6 +1,6 @@
 ;;; generic-x.el --- A collection of generic modes  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Peter Breton <pbreton@cs.umb.edu>
 ;; Created: Tue Oct 08 1996
@@ -1491,6 +1491,7 @@ like an INI file.  You can add this hook to 
`find-file-hook'."
     "cd9660"
     "cfs"
     "cgroup"
+    "cgroup2"
     "cifs"
     "coda"
     "coherent"
diff --git a/lisp/gnus/ChangeLog.1 b/lisp/gnus/ChangeLog.1
index 2ce954cca99..ee00e57b0fa 100644
--- a/lisp/gnus/ChangeLog.1
+++ b/lisp/gnus/ChangeLog.1
@@ -663,7 +663,7 @@
 1998-08-07  Gareth Jones  <gdj1@gdjones.demon.co.uk>
 
        * gnus-score.el (gnus-summary-increase-score): Don't downcase
-       before lookin in char-to-header.
+       before looking in char-to-header.
 
 1998-08-07  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
@@ -2745,7 +2745,7 @@
 
 1997-12-05  Dave Love  <d.love@dl.ac.uk>
 
-       * gnus-nocem.el (gnus-nocem-message-wanted-p): Fix paren typpo.
+       * gnus-nocem.el (gnus-nocem-message-wanted-p): Fix paren typo.
        (gnus-nocem-issuers): Allow sexp alternative in :type for alists.
 
 1997-12-05  Dave Love  <d.love@dl.ac.uk>
@@ -3702,7 +3702,7 @@
        * gnus.el: Quassia Gnus v0.1 is released.
 
 
-  Copyright (C) 1997-2023 Free Software Foundation, Inc.
+  Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/gnus/ChangeLog.2 b/lisp/gnus/ChangeLog.2
index 2d7aeabd8cf..53f81862ddf 100644
--- a/lisp/gnus/ChangeLog.2
+++ b/lisp/gnus/ChangeLog.2
@@ -6215,7 +6215,7 @@
        * pop3.el (pop3-retr): Wait 500 msecs.
        (pop3-read-response): Ditto.
 
-       * gnus-msg.el (gnus-setup-message): Get the evaliation order
+       * gnus-msg.el (gnus-setup-message): Get the evaluation order
        right.
        (gnus-inews-make-draft): New function.
        (gnus-setup-message): Use it.
@@ -9474,7 +9474,7 @@
 2002-03-01  Paul Jarc  <prj@po.cwru.edu>
 
        * message.el (message-get-reply-headers): Downcase email addresses
-       for comaparisons for duplicate removal.
+       for comparisons for duplicate removal.
 
 2002-03-01  ShengHuo ZHU  <zsh@cs.rochester.edu>
 
@@ -18538,7 +18538,7 @@
 
 See ChangeLog.1 for earlier changes.
 
-  Copyright (C) 2000-2002, 2004-2023 Free Software Foundation, Inc.
+  Copyright (C) 2000-2002, 2004-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/gnus/ChangeLog.3 b/lisp/gnus/ChangeLog.3
index 0fc5c093371..1633b8835eb 100644
--- a/lisp/gnus/ChangeLog.3
+++ b/lisp/gnus/ChangeLog.3
@@ -13,7 +13,7 @@
 
 2015-04-01  Eric Abrahamsen  <eric@ericabrahamsen.net>
 
-       * registry.el (registry-prune): Re-use `registry-full' in
+       * registry.el (registry-prune): Reuse `registry-full' in
        `registry-prune'.  It's a bit of redundant work, but safer.
        Also ensure that target-size is an integer.
 
@@ -78,7 +78,7 @@
        * gnus-notifications.el (gnus-notifications-action): Raise window
        frame.
        (gnus-notifications-action): Allow mark as read.
-       (gnus-notifications-notify): Show uption to mark as read.
+       (gnus-notifications-notify): Show option to mark as read.
 
 2015-03-08  Adam Sjøgren  <asjo@koldfront.dk>
 
@@ -26326,7 +26326,7 @@
 
 See ChangeLog.2 for earlier changes.
 
-  Copyright (C) 2004-2023 Free Software Foundation, Inc.
+  Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/gnus/canlock.el b/lisp/gnus/canlock.el
index 2eb5e13df9a..02744a7f0a5 100644
--- a/lisp/gnus/canlock.el
+++ b/lisp/gnus/canlock.el
@@ -1,6 +1,6 @@
 ;;; canlock.el --- functions for Cancel-Lock feature  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1998-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Katsumi Yamaoka <yamaoka@jpl.org>
 ;; Keywords: news, cancel-lock, hmac, sha1, rfc2104
diff --git a/lisp/gnus/deuglify.el b/lisp/gnus/deuglify.el
index 2c75d5b7873..80205012696 100644
--- a/lisp/gnus/deuglify.el
+++ b/lisp/gnus/deuglify.el
@@ -1,6 +1,6 @@
 ;;; deuglify.el --- deuglify broken Outlook (Express) articles  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Raymond Scholz <rscholz@zonix.de>
 ;;         Thomas Steffen
diff --git a/lisp/gnus/gmm-utils.el b/lisp/gnus/gmm-utils.el
index c0651e3dbfc..516758c0082 100644
--- a/lisp/gnus/gmm-utils.el
+++ b/lisp/gnus/gmm-utils.el
@@ -1,6 +1,6 @@
 ;;; gmm-utils.el --- Utility functions for Gnus, Message and MML  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Reiner Steib <reiner.steib@gmx.de>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el
index db205c5b657..3ee93031119 100644
--- a/lisp/gnus/gnus-agent.el
+++ b/lisp/gnus/gnus-agent.el
@@ -1,6 +1,6 @@
 ;;; gnus-agent.el --- unplugged support for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el
index bd9a49eb6a5..c3c5eab7d89 100644
--- a/lisp/gnus/gnus-art.el
+++ b/lisp/gnus/gnus-art.el
@@ -1,6 +1,6 @@
 ;;; gnus-art.el --- article mode commands for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
@@ -2871,12 +2871,15 @@ Return file name relative to the parent of DIRECTORY."
                              cid handle directory))
              (throw 'found file)))
           ((equal (concat "<" cid ">") (mm-handle-id handle))
-           (setq file (or (mm-handle-filename handle)
-                          (concat
-                           (make-temp-name "cid")
-                           (car (rassoc (car (mm-handle-type handle))
-                                        mailcap-mime-extensions))))
-                 afile (expand-file-name file directory))
+            ;; Randomize filenames: declared filenames may not be unique.
+            (setq file (format "cid-%d-%s"
+                              (random 99)
+                              (or (mm-handle-filename handle)
+                                  (concat
+                                   (make-temp-name "cid")
+                                   (car (rassoc (car (mm-handle-type handle))
+                                                mailcap-mime-extensions)))))
+                  afile (expand-file-name file directory))
            (mm-save-part-to-file handle afile)
            (throw 'found (concat (file-name-nondirectory
                                   (directory-file-name directory))
diff --git a/lisp/gnus/gnus-async.el b/lisp/gnus/gnus-async.el
index 14295f09be9..fbcc05c4a1d 100644
--- a/lisp/gnus/gnus-async.el
+++ b/lisp/gnus/gnus-async.el
@@ -1,6 +1,6 @@
 ;;; gnus-async.el --- asynchronous support for Gnus  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-bcklg.el b/lisp/gnus/gnus-bcklg.el
index 2c338ccd145..4fb73f9cbfa 100644
--- a/lisp/gnus/gnus-bcklg.el
+++ b/lisp/gnus/gnus-bcklg.el
@@ -1,6 +1,6 @@
 ;;; gnus-bcklg.el --- backlog functions for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-bookmark.el b/lisp/gnus/gnus-bookmark.el
index aee122aa557..ccb9490d73b 100644
--- a/lisp/gnus/gnus-bookmark.el
+++ b/lisp/gnus/gnus-bookmark.el
@@ -1,6 +1,6 @@
 ;;; gnus-bookmark.el --- Bookmarks in Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Bastien Guerry <bzg AT altern DOT org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-cache.el b/lisp/gnus/gnus-cache.el
index 13be21630ec..961219eee8f 100644
--- a/lisp/gnus/gnus-cache.el
+++ b/lisp/gnus/gnus-cache.el
@@ -1,6 +1,6 @@
 ;;; gnus-cache.el --- cache interface for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-cite.el b/lisp/gnus/gnus-cite.el
index a3c24ea05d9..3fde9baa0fe 100644
--- a/lisp/gnus/gnus-cite.el
+++ b/lisp/gnus/gnus-cite.el
@@ -1,6 +1,6 @@
 ;;; gnus-cite.el --- parse citations in articles for Gnus  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 
@@ -1122,31 +1122,17 @@ Returns nil if there is no such line before LIMIT, t 
otherwise."
 When enabled, it automatically turns on `font-lock-mode'."
   :lighter ""
   (when (derived-mode-p 'message-mode)
-    ;; FIXME: Use font-lock-add-keywords!
-    (let ((defaults (car font-lock-defaults))
-         default) ;; keywords
-      (while defaults
-       (setq default (if (consp defaults)
-                         (pop defaults)
-                       (prog1
-                           defaults
-                         (setq defaults nil))))
-       (if gnus-message-citation-mode
-           ;; `gnus-message-citation-keywords' should be the last
-           ;; elements of the keywords because the others are unlikely
-           ;; to have the OVERRIDE flags -- XEmacs applies a keyword
-           ;; having no OVERRIDE flag to matched text even if it has
-           ;; already other faces, while Emacs doesn't.
-           (set (make-local-variable default)
-                (append (default-value default)
-                        gnus-message-citation-keywords))
-         (kill-local-variable default))))
-    ;; Force `font-lock-set-defaults' to update `font-lock-keywords'.
-    (setq font-lock-set-defaults nil)
-    (font-lock-set-defaults)
-    (if font-lock-mode
-       (font-lock-flush)
-      (gnus-message-citation-mode (font-lock-mode 1)))))
+    (if (not font-lock-mode)
+        (gnus-message-citation-mode (font-lock-mode 1))
+      (if gnus-message-citation-mode
+         ;; `gnus-message-citation-keywords' should be the last
+         ;; elements of the keywords because the others are unlikely
+         ;; to have the OVERRIDE flags -- XEmacs applies a keyword
+         ;; having no OVERRIDE flag to matched text even if it has
+         ;; already other faces, while Emacs doesn't.
+         (font-lock-add-keywords nil gnus-message-citation-keywords t)
+        (font-lock-remove-keywords nil gnus-message-citation-keywords))
+      (font-lock-flush))))
 
 (defun turn-on-gnus-message-citation-mode ()
   "Turn on `gnus-message-citation-mode'."
diff --git a/lisp/gnus/gnus-cloud.el b/lisp/gnus/gnus-cloud.el
index a21d57d86ff..af5f42b1c3b 100644
--- a/lisp/gnus/gnus-cloud.el
+++ b/lisp/gnus/gnus-cloud.el
@@ -1,6 +1,6 @@
 ;;; gnus-cloud.el --- storing and retrieving data via IMAP  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: mail
diff --git a/lisp/gnus/gnus-cus.el b/lisp/gnus/gnus-cus.el
index 9225f15b7e1..4da9979adac 100644
--- a/lisp/gnus/gnus-cus.el
+++ b/lisp/gnus/gnus-cus.el
@@ -1,6 +1,6 @@
 ;;; gnus-cus.el --- customization commands for Gnus  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1996, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-dbus.el b/lisp/gnus/gnus-dbus.el
index f6ad48f9069..19d564548f2 100644
--- a/lisp/gnus/gnus-dbus.el
+++ b/lisp/gnus/gnus-dbus.el
@@ -1,6 +1,6 @@
 ;;; gnus-dbus.el --- DBUS integration for Gnus       -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Abrahamsen <eric@ericabrahamsen.net>
 
diff --git a/lisp/gnus/gnus-delay.el b/lisp/gnus/gnus-delay.el
index 07bed67ae0e..4de9588423c 100644
--- a/lisp/gnus/gnus-delay.el
+++ b/lisp/gnus/gnus-delay.el
@@ -1,6 +1,6 @@
 ;;; gnus-delay.el --- Delayed posting of articles  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 ;; Keywords: mail, news, extensions
diff --git a/lisp/gnus/gnus-demon.el b/lisp/gnus/gnus-demon.el
index de6c167a1fc..93bce94ea3d 100644
--- a/lisp/gnus/gnus-demon.el
+++ b/lisp/gnus/gnus-demon.el
@@ -1,6 +1,6 @@
 ;;; gnus-demon.el --- daemonic Gnus behavior  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-diary.el b/lisp/gnus/gnus-diary.el
index 4cb1182117d..60b94dff1fa 100644
--- a/lisp/gnus/gnus-diary.el
+++ b/lisp/gnus/gnus-diary.el
@@ -1,6 +1,6 @@
 ;;; gnus-diary.el --- Wrapper around the NNDiary Gnus back end  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author:        Didier Verna <didier@didierverna.net>
 ;; Created:       Tue Jul 20 10:42:55 1999
diff --git a/lisp/gnus/gnus-dired.el b/lisp/gnus/gnus-dired.el
index b146b51430a..48c1aef968b 100644
--- a/lisp/gnus/gnus-dired.el
+++ b/lisp/gnus/gnus-dired.el
@@ -1,6 +1,6 @@
 ;;; gnus-dired.el --- utility functions where gnus and dired meet  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Authors: Benjamin Rutt <brutt@bloomington.in.us>,
 ;;          Shenghuo Zhu <zsh@cs.rochester.edu>
diff --git a/lisp/gnus/gnus-draft.el b/lisp/gnus/gnus-draft.el
index 76aa5647a3d..1fc2b33fffb 100644
--- a/lisp/gnus/gnus-draft.el
+++ b/lisp/gnus/gnus-draft.el
@@ -1,6 +1,6 @@
 ;;; gnus-draft.el --- draft message support for Gnus  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-dup.el b/lisp/gnus/gnus-dup.el
index 8e31a1762b0..fb752cff67f 100644
--- a/lisp/gnus/gnus-dup.el
+++ b/lisp/gnus/gnus-dup.el
@@ -1,6 +1,6 @@
 ;;; gnus-dup.el --- suppression of duplicate articles in Gnus  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-eform.el b/lisp/gnus/gnus-eform.el
index cc5beb16a34..ca76c714caa 100644
--- a/lisp/gnus/gnus-eform.el
+++ b/lisp/gnus/gnus-eform.el
@@ -1,6 +1,6 @@
 ;;; gnus-eform.el --- a mode for editing forms for Gnus  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-fun.el b/lisp/gnus/gnus-fun.el
index fc934ab142e..677903f461e 100644
--- a/lisp/gnus/gnus-fun.el
+++ b/lisp/gnus/gnus-fun.el
@@ -1,6 +1,6 @@
 ;;; gnus-fun.el --- various frivolous extension functions to Gnus  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-gravatar.el b/lisp/gnus/gnus-gravatar.el
index cdfd85e9831..67c828bf775 100644
--- a/lisp/gnus/gnus-gravatar.el
+++ b/lisp/gnus/gnus-gravatar.el
@@ -1,6 +1,6 @@
 ;;; gnus-gravatar.el --- Gnus Gravatar support -*- lexical-binding: t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Julien Danjou <julien@danjou.info>
 ;; Keywords: multimedia, news
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index a9c38334933..d562d052d82 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -1,6 +1,6 @@
 ;;; gnus-group.el --- group mode commands for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
@@ -1064,11 +1064,11 @@ When FORCE, rebuild the tool bar."
 All normal editing commands are switched off.
 \\<gnus-group-mode-map>
 The group buffer lists (some of) the groups available.  For instance,
-`\\[gnus-group-list-groups]' will list all subscribed groups with unread 
articles, while `\\[gnus-group-list-zombies]'
+\\[gnus-group-list-groups] will list all subscribed groups with unread 
articles, while \\[gnus-group-list-zombies]
 lists all zombie groups.
 
-Groups that are displayed can be entered with `\\[gnus-group-read-group]'.  To 
subscribe
-to a group not displayed, type `\\[gnus-group-toggle-subscription]'.
+Groups that are displayed can be entered with \\[gnus-group-read-group].  To 
subscribe
+to a group not displayed, type \\[gnus-group-toggle-subscription].
 
 For more in-depth information on this mode, read the manual 
(`\\[gnus-info-find-node]').
 
diff --git a/lisp/gnus/gnus-html.el b/lisp/gnus/gnus-html.el
index 829e4cf0099..2d8d6db24bf 100644
--- a/lisp/gnus/gnus-html.el
+++ b/lisp/gnus/gnus-html.el
@@ -1,6 +1,6 @@
 ;;; gnus-html.el --- Render HTML in a buffer.  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: html, web
diff --git a/lisp/gnus/gnus-icalendar.el b/lisp/gnus/gnus-icalendar.el
index b0efe689636..af7284b88e8 100644
--- a/lisp/gnus/gnus-icalendar.el
+++ b/lisp/gnus/gnus-icalendar.el
@@ -1,6 +1,6 @@
 ;;; gnus-icalendar.el --- reply to iCalendar meeting requests  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Jan Tatarik <Jan.Tatarik@gmail.com>
 ;; Keywords: mail, icalendar, org
diff --git a/lisp/gnus/gnus-int.el b/lisp/gnus/gnus-int.el
index 49238e62bea..558ad8648ca 100644
--- a/lisp/gnus/gnus-int.el
+++ b/lisp/gnus/gnus-int.el
@@ -1,6 +1,6 @@
 ;;; gnus-int.el --- backend interface functions for Gnus  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-kill.el b/lisp/gnus/gnus-kill.el
index 5f96f002a77..8b74cd2e476 100644
--- a/lisp/gnus/gnus-kill.el
+++ b/lisp/gnus/gnus-kill.el
@@ -1,6 +1,6 @@
 ;;; gnus-kill.el --- kill commands for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/gnus-logic.el b/lisp/gnus/gnus-logic.el
index 426249e9a40..3652b02672b 100644
--- a/lisp/gnus/gnus-logic.el
+++ b/lisp/gnus/gnus-logic.el
@@ -1,6 +1,6 @@
 ;;; gnus-logic.el --- advanced scoring code for Gnus  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-mh.el b/lisp/gnus/gnus-mh.el
index 59e8947928f..0035ff26a25 100644
--- a/lisp/gnus/gnus-mh.el
+++ b/lisp/gnus/gnus-mh.el
@@ -1,6 +1,6 @@
 ;;; gnus-mh.el --- mh-e interface for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/gnus-ml.el b/lisp/gnus/gnus-ml.el
index 59c3e60c6e3..fb0f5d830ad 100644
--- a/lisp/gnus/gnus-ml.el
+++ b/lisp/gnus/gnus-ml.el
@@ -1,6 +1,6 @@
 ;;; gnus-ml.el --- Mailing list minor mode for Gnus  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Julien Gilles <jgilles@free.fr>
 ;; Keywords: news, mail
diff --git a/lisp/gnus/gnus-mlspl.el b/lisp/gnus/gnus-mlspl.el
index 9fc065fe756..6985a40e305 100644
--- a/lisp/gnus/gnus-mlspl.el
+++ b/lisp/gnus/gnus-mlspl.el
@@ -1,6 +1,6 @@
 ;;; gnus-mlspl.el --- a group params-based mail splitting mechanism  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Alexandre Oliva <oliva@lsd.ic.unicamp.br>
 ;; Keywords: news, mail
diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el
index b065ae34851..fdf97e1aabd 100644
--- a/lisp/gnus/gnus-msg.el
+++ b/lisp/gnus/gnus-msg.el
@@ -1,6 +1,6 @@
 ;;; gnus-msg.el --- mail and post interface for Gnus  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
 ;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -1209,7 +1209,7 @@ The original article(s) will be yanked."
   (gnus-summary-reply
    (gnus-summary-work-articles n) t (gnus-summary-work-articles n)))
 
-(defun gnus-summary-mail-forward (&optional arg post)
+(defun gnus-summary-mail-forward (&optional arg all-headers post)
   "Forward the current message(s) to another user.
 If process marks exist, forward all marked messages;
 if ARG is nil, see `message-forward-as-mime' and `message-forward-show-mml';
@@ -1217,17 +1217,25 @@ if ARG is 1, decode the message and forward directly 
inline;
 if ARG is 2, forward message as an rfc822 MIME section;
 if ARG is 3, decode message and forward as an rfc822 MIME section;
 if ARG is 4, forward message directly inline;
-otherwise, use flipped `message-forward-as-mime'.
+otherwise, use negated `message-forward-as-mime'.
 If POST, post instead of mail.
-For the \"inline\" alternatives, also see the variable
-`message-forward-ignored-headers'."
-  (interactive "P" gnus-summary-mode)
+If symbolic prefix ALL-HEADERS is the symbol `a', include all
+original headers in the forwarded message, except those matching
+`message-forward-ignored-headers'.  Otherwise, include headers
+based on the options `message-forward-included-headers',
+`message-forward-ignored-headers', and potentially
+`message-forward-included-mime-headers'."
+  (interactive (gnus-interactive "P\ny") gnus-summary-mode)
   (if (cdr (gnus-summary-work-articles nil))
       ;; Process marks are given.
       (gnus-uu-digest-mail-forward nil post)
     ;; No process marks.
     (let ((message-forward-as-mime message-forward-as-mime)
-         (message-forward-show-mml message-forward-show-mml))
+         (message-forward-show-mml message-forward-show-mml)
+          (message-forward-included-headers
+           (if (eq all-headers 'a)
+               nil
+             message-forward-included-headers)))
       (cond
        ((null arg))
        ((eq arg 1)
@@ -1380,11 +1388,11 @@ composing a new message."
          (forward-char 1))
        (widen)))))
 
-(defun gnus-summary-post-forward (&optional arg)
+(defun gnus-summary-post-forward (&optional arg all-headers)
   "Forward the current article to a newsgroup.
 See `gnus-summary-mail-forward' for ARG."
-  (interactive "P" gnus-summary-mode)
-  (gnus-summary-mail-forward arg t))
+  (interactive (gnus-interactive "P\ny") gnus-summary-mode)
+  (gnus-summary-mail-forward arg all-headers t))
 
 (defun gnus-summary-mail-crosspost-complaint (n)
   "Send a complaint about crossposting to the current article(s)."
diff --git a/lisp/gnus/gnus-notifications.el b/lisp/gnus/gnus-notifications.el
index 5e5b4a31e9e..f34f5ea0e26 100644
--- a/lisp/gnus/gnus-notifications.el
+++ b/lisp/gnus/gnus-notifications.el
@@ -1,6 +1,6 @@
 ;;; gnus-notifications.el --- Send notification on new message in Gnus  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Julien Danjou <julien@danjou.info>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-picon.el b/lisp/gnus/gnus-picon.el
index 562c2b7423f..48c70045a37 100644
--- a/lisp/gnus/gnus-picon.el
+++ b/lisp/gnus/gnus-picon.el
@@ -1,6 +1,6 @@
 ;;; gnus-picon.el --- displaying pretty icons in Gnus  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news xpm annotation glyph faces
diff --git a/lisp/gnus/gnus-range.el b/lisp/gnus/gnus-range.el
index 285018bc642..dbb24571e55 100644
--- a/lisp/gnus/gnus-range.el
+++ b/lisp/gnus/gnus-range.el
@@ -1,6 +1,6 @@
 ;;; gnus-range.el --- range and sequence functions for Gnus  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el
index d9834031b80..0881bfce03c 100644
--- a/lisp/gnus/gnus-registry.el
+++ b/lisp/gnus/gnus-registry.el
@@ -1,6 +1,6 @@
 ;;; gnus-registry.el --- article registry for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Ted Zlatanov <tzz@lifelogs.com>
 ;; Keywords: news registry
diff --git a/lisp/gnus/gnus-rfc1843.el b/lisp/gnus/gnus-rfc1843.el
index e50f735dcb7..c814f55411f 100644
--- a/lisp/gnus/gnus-rfc1843.el
+++ b/lisp/gnus/gnus-rfc1843.el
@@ -1,6 +1,6 @@
 ;;; gnus-rfc1843.el --- HZ (rfc1843) decoding interface functions for Gnus  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
 ;; Keywords: news HZ HZ+ mail i18n
diff --git a/lisp/gnus/gnus-rmail.el b/lisp/gnus/gnus-rmail.el
index 55706e80565..26cae246b67 100644
--- a/lisp/gnus/gnus-rmail.el
+++ b/lisp/gnus/gnus-rmail.el
@@ -1,6 +1,6 @@
 ;;; gnus-rmail.el --- Saving to rmail/babyl files  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/gnus/gnus-salt.el b/lisp/gnus/gnus-salt.el
index 853c3f6d8ac..358a301da90 100644
--- a/lisp/gnus/gnus-salt.el
+++ b/lisp/gnus/gnus-salt.el
@@ -1,6 +1,6 @@
 ;;; gnus-salt.el --- alternate summary mode interfaces for Gnus  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el
index 62167ea9e6a..bd19e7d7cd7 100644
--- a/lisp/gnus/gnus-score.el
+++ b/lisp/gnus/gnus-score.el
@@ -1,6 +1,6 @@
 ;;; gnus-score.el --- scoring code for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Per Abrahamsen <amanda@iesd.auc.dk>
 ;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el
index 839e5d203ff..a967d6d71da 100644
--- a/lisp/gnus/gnus-search.el
+++ b/lisp/gnus/gnus-search.el
@@ -1,6 +1,6 @@
 ;;; gnus-search.el --- Search facilities for Gnus    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Abrahamsen <eric@ericabrahamsen.net>
 
@@ -1450,7 +1450,7 @@ Returns a list of [group article score] vectors."
        (when (and f-name
                    (file-readable-p f-name)
                   (null (file-directory-p f-name)))
-          ;; `expand-file-name' canoncalizes the file name,
+          ;; `expand-file-name' canonicalizes the file name,
           ;; specifically collapsing multiple consecutive directory
           ;; separators.
           (setq f-name (expand-file-name f-name)
diff --git a/lisp/gnus/gnus-sieve.el b/lisp/gnus/gnus-sieve.el
index c7182859282..04af180a9d2 100644
--- a/lisp/gnus/gnus-sieve.el
+++ b/lisp/gnus/gnus-sieve.el
@@ -1,6 +1,6 @@
 ;;; gnus-sieve.el --- Utilities to manage sieve scripts for Gnus  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: NAGY Andras <nagya@inf.elte.hu>,
 ;;     Simon Josefsson <simon@josefsson.org>
diff --git a/lisp/gnus/gnus-spec.el b/lisp/gnus/gnus-spec.el
index a58ad1fc128..a7c79c5c653 100644
--- a/lisp/gnus/gnus-spec.el
+++ b/lisp/gnus/gnus-spec.el
@@ -1,6 +1,6 @@
 ;;; gnus-spec.el --- format spec functions for Gnus  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-srvr.el b/lisp/gnus/gnus-srvr.el
index 7dd237bce4d..63956222fa1 100644
--- a/lisp/gnus/gnus-srvr.el
+++ b/lisp/gnus/gnus-srvr.el
@@ -1,6 +1,6 @@
 ;;; gnus-srvr.el --- virtual server support for Gnus  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 19b8b09de03..f337278994c 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -1,6 +1,6 @@
 ;;; gnus-start.el --- startup functions for Gnus -*- lexical-binding:t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index 1639c062471..dc66e1375ab 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -1,6 +1,6 @@
 ;;; gnus-sum.el --- summary mode commands for Gnus  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
@@ -3062,17 +3062,17 @@ the summary mode hooks are run.")
   "Major mode for reading articles.
 \\<gnus-summary-mode-map>
 Each line in this buffer represents one article.  To read an
-article, you can, for instance, type `\\[gnus-summary-next-page]'.  To move 
forwards
-and backwards while displaying articles, type 
`\\[gnus-summary-next-unread-article]' and 
`\\[gnus-summary-prev-unread-article]',
+article, you can, for instance, type \\[gnus-summary-next-page].  To move 
forwards
+and backwards while displaying articles, type 
\\[gnus-summary-next-unread-article] and \\[gnus-summary-prev-unread-article],
 respectively.
 
 You can also post articles and send mail from this buffer.  To
-follow up an article, type `\\[gnus-summary-followup]'.  To mail a reply to 
the author
-of an article, type `\\[gnus-summary-reply]'.
+follow up an article, type \\[gnus-summary-followup].  To mail a reply to the 
author
+of an article, type \\[gnus-summary-reply].
 
 There are approximately one gazillion commands you can execute in
 this buffer; read the Info manual for more
-information (`\\[gnus-info-find-node]').
+information (\\[gnus-info-find-node]).
 
 The following commands are available:
 
diff --git a/lisp/gnus/gnus-topic.el b/lisp/gnus/gnus-topic.el
index f41c457ecbc..7a1053bd6f0 100644
--- a/lisp/gnus/gnus-topic.el
+++ b/lisp/gnus/gnus-topic.el
@@ -1,6 +1,6 @@
 ;;; gnus-topic.el --- a folding minor mode for Gnus group buffers  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Ilja Weis <kult@uni-paderborn.de>
 ;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/gnus-undo.el b/lisp/gnus/gnus-undo.el
index e19a7b78363..c29659db237 100644
--- a/lisp/gnus/gnus-undo.el
+++ b/lisp/gnus/gnus-undo.el
@@ -1,6 +1,6 @@
 ;;; gnus-undo.el --- minor mode for undoing in Gnus  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index 1d25d7ac919..b5aa0b02d34 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -1,6 +1,6 @@
 ;;; gnus-util.el --- utility functions for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus-uu.el b/lisp/gnus/gnus-uu.el
index 6ed6358e8ce..95236a167fc 100644
--- a/lisp/gnus/gnus-uu.el
+++ b/lisp/gnus/gnus-uu.el
@@ -1,6 +1,6 @@
 ;;; gnus-uu.el --- extract (uu)encoded files in Gnus  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1985-1987, 1993-1998, 2000-2023 Free Software
+;; Copyright (C) 1985-1987, 1993-1998, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/gnus-vm.el b/lisp/gnus/gnus-vm.el
index 9d83b974719..9e7b5d86662 100644
--- a/lisp/gnus/gnus-vm.el
+++ b/lisp/gnus/gnus-vm.el
@@ -1,6 +1,6 @@
 ;;; gnus-vm.el --- vm interface for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Per Persson <pp@gnu.ai.mit.edu>
 ;; Keywords: news, mail
diff --git a/lisp/gnus/gnus-win.el b/lisp/gnus/gnus-win.el
index 9d8b34aef29..885d20823b7 100644
--- a/lisp/gnus/gnus-win.el
+++ b/lisp/gnus/gnus-win.el
@@ -1,6 +1,6 @@
 ;;; gnus-win.el --- window configuration functions for Gnus  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index 6bf66233101..99833e4eeca 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -1,6 +1,6 @@
 ;;; gnus.el --- a newsreader for GNU Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1987-1990, 1993-1998, 2000-2023 Free Software
+;; Copyright (C) 1987-1990, 1993-1998, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/gssapi.el b/lisp/gnus/gssapi.el
index beb9ba41e11..58c26c4e47c 100644
--- a/lisp/gnus/gssapi.el
+++ b/lisp/gnus/gssapi.el
@@ -1,6 +1,6 @@
 ;;; gssapi.el --- GSSAPI/Kerberos 5 interface for Emacs  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 ;;         Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/legacy-gnus-agent.el b/lisp/gnus/legacy-gnus-agent.el
index bd95c5137f5..d4f08c72de8 100644
--- a/lisp/gnus/legacy-gnus-agent.el
+++ b/lisp/gnus/legacy-gnus-agent.el
@@ -1,6 +1,6 @@
 ;;; legacy-gnus-agent.el --- Legacy unplugged support for Gnus  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Kevin Greiner <kgreiner@xpediantsolutions.com>
 ;; Keywords: news
diff --git a/lisp/gnus/mail-source.el b/lisp/gnus/mail-source.el
index f870c0b8274..fdafc29f7e8 100644
--- a/lisp/gnus/mail-source.el
+++ b/lisp/gnus/mail-source.el
@@ -1,6 +1,6 @@
 ;;; mail-source.el --- functions for fetching mail  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news, mail
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index 9e60c21e3d4..979d2fecf56 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -1,6 +1,6 @@
 ;;; message.el --- composing mail and news messages -*- lexical-binding: t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: mail, news
@@ -1876,9 +1876,13 @@ downcased."
   :type '(repeat (repeat string)))
 
 (defcustom message-mail-user-agent nil
-  "Like `mail-user-agent'.
-Except if it is nil, use Gnus native MUA; if it is t, use
-`mail-user-agent'."
+  "Your preferred package for composing and sending email when using 
message.el.
+Like `mail-user-agent' (which see), this specifies the package you prefer
+to use for composing and sending email messages.
+The value can be anything accepted by `mail-user-agent', and in addition
+it can be nil or t.  If the value is nil, use the Gnus native Mail User
+Agent (MUA); if it is t, use the value of `mail-user-agent'.
+For more about mail user agents, see Info node `(emacs)Mail Methods'"
   :version "22.1"
   :type '(radio (const :tag "Gnus native"
                       :format "%t\n"
diff --git a/lisp/gnus/mm-archive.el b/lisp/gnus/mm-archive.el
index 50f6012148e..9add3e1c8ea 100644
--- a/lisp/gnus/mm-archive.el
+++ b/lisp/gnus/mm-archive.el
@@ -1,6 +1,6 @@
 ;;; mm-archive.el --- Functions for parsing archive files as MIME  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
diff --git a/lisp/gnus/mm-bodies.el b/lisp/gnus/mm-bodies.el
index 2290b667abe..912bbc1fe8c 100644
--- a/lisp/gnus/mm-bodies.el
+++ b/lisp/gnus/mm-bodies.el
@@ -1,6 +1,6 @@
 ;;; mm-bodies.el --- Functions for decoding MIME things  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el
index 3c7d1e7e073..f91755e967b 100644
--- a/lisp/gnus/mm-decode.el
+++ b/lisp/gnus/mm-decode.el
@@ -1,6 +1,6 @@
 ;;; mm-decode.el --- Functions for decoding MIME things  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
diff --git a/lisp/gnus/mm-encode.el b/lisp/gnus/mm-encode.el
index 14b7da299b8..560d7bd30a9 100644
--- a/lisp/gnus/mm-encode.el
+++ b/lisp/gnus/mm-encode.el
@@ -1,6 +1,6 @@
 ;;; mm-encode.el --- Functions for encoding MIME things  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
diff --git a/lisp/gnus/mm-extern.el b/lisp/gnus/mm-extern.el
index 1d628c3d6b5..c23e176d60d 100644
--- a/lisp/gnus/mm-extern.el
+++ b/lisp/gnus/mm-extern.el
@@ -1,6 +1,6 @@
 ;;; mm-extern.el --- showing message/external-body  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
 ;; Keywords: message external-body
diff --git a/lisp/gnus/mm-partial.el b/lisp/gnus/mm-partial.el
index 35b1ff197f8..56781527aca 100644
--- a/lisp/gnus/mm-partial.el
+++ b/lisp/gnus/mm-partial.el
@@ -1,6 +1,6 @@
 ;;; mm-partial.el --- showing message/partial  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
 ;; Keywords: message partial
diff --git a/lisp/gnus/mm-url.el b/lisp/gnus/mm-url.el
index 11847a79f17..be6c9bb7977 100644
--- a/lisp/gnus/mm-url.el
+++ b/lisp/gnus/mm-url.el
@@ -1,6 +1,6 @@
 ;;; mm-url.el --- a wrapper of url functions/commands for Gnus  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
 
diff --git a/lisp/gnus/mm-util.el b/lisp/gnus/mm-util.el
index 2065747b859..0e4bbbe650f 100644
--- a/lisp/gnus/mm-util.el
+++ b/lisp/gnus/mm-util.el
@@ -1,6 +1,6 @@
 ;;; mm-util.el --- Utility functions for Mule and low level things  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
diff --git a/lisp/gnus/mm-uu.el b/lisp/gnus/mm-uu.el
index 72c39aae83c..3c7e3cbdf1a 100644
--- a/lisp/gnus/mm-uu.el
+++ b/lisp/gnus/mm-uu.el
@@ -1,6 +1,6 @@
 ;;; mm-uu.el --- Return uu stuff as mm handles  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
 ;; Keywords: postscript uudecode binhex shar forward gnatsweb pgp
diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el
index 47d2b5f57e6..3a7192092af 100644
--- a/lisp/gnus/mm-view.el
+++ b/lisp/gnus/mm-view.el
@@ -1,6 +1,6 @@
 ;;; mm-view.el --- functions for viewing MIME objects  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
diff --git a/lisp/gnus/mml-sec.el b/lisp/gnus/mml-sec.el
index 44ffaf9f229..98f8ebbcbcd 100644
--- a/lisp/gnus/mml-sec.el
+++ b/lisp/gnus/mml-sec.el
@@ -1,6 +1,6 @@
 ;;; mml-sec.el --- A package with security functions for MML documents  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 
diff --git a/lisp/gnus/mml-smime.el b/lisp/gnus/mml-smime.el
index 896c95f8d3e..3064c46d2a3 100644
--- a/lisp/gnus/mml-smime.el
+++ b/lisp/gnus/mml-smime.el
@@ -1,6 +1,6 @@
 ;;; mml-smime.el --- S/MIME support for MML  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 ;; Keywords: Gnus, MIME, S/MIME, MML
diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el
index 24cd5eb83d3..edb3c286242 100644
--- a/lisp/gnus/mml.el
+++ b/lisp/gnus/mml.el
@@ -1,6 +1,6 @@
 ;;; mml.el --- A package for parsing and validating MML documents  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
diff --git a/lisp/gnus/mml1991.el b/lisp/gnus/mml1991.el
index 33b1f3a4c78..b44d50b5f77 100644
--- a/lisp/gnus/mml1991.el
+++ b/lisp/gnus/mml1991.el
@@ -1,6 +1,6 @@
 ;;; mml1991.el --- Old PGP message format (RFC 1991) support for MML  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Sascha Lüdecke <sascha@meta-x.de>,
 ;;     Simon Josefsson <simon@josefsson.org> (Mailcrypt interface, Gnus glue)
diff --git a/lisp/gnus/mml2015.el b/lisp/gnus/mml2015.el
index df3dd434b0a..602a4baa73d 100644
--- a/lisp/gnus/mml2015.el
+++ b/lisp/gnus/mml2015.el
@@ -1,6 +1,6 @@
 ;;; mml2015.el --- MIME Security with Pretty Good Privacy (PGP)  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
 ;; Keywords: PGP MIME MML
diff --git a/lisp/gnus/nnagent.el b/lisp/gnus/nnagent.el
index 30d5514a8b7..7ccb02a45d0 100644
--- a/lisp/gnus/nnagent.el
+++ b/lisp/gnus/nnagent.el
@@ -1,6 +1,6 @@
 ;;; nnagent.el --- offline backend for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news, mail
diff --git a/lisp/gnus/nnbabyl.el b/lisp/gnus/nnbabyl.el
index 4ad994b12f1..b002b3c0114 100644
--- a/lisp/gnus/nnbabyl.el
+++ b/lisp/gnus/nnbabyl.el
@@ -1,6 +1,6 @@
 ;;; nnbabyl.el --- rmail mbox access for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el
index 8728aab1def..b6f423ee2f8 100644
--- a/lisp/gnus/nndiary.el
+++ b/lisp/gnus/nndiary.el
@@ -1,6 +1,6 @@
 ;;; nndiary.el --- A diary back end for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author:        Didier Verna <didier@didierverna.net>
 ;; Created:       Fri Jul 16 18:55:42 1999
@@ -1030,7 +1030,7 @@ all.  This may very well take some time.")
 (defun nndiary-generate-nov-databases (&optional server)
   "Generate NOV databases in all nndiary directories."
   (interactive (list (or (nnoo-current-server 'nndiary) "")))
-  ;; Read the active file to make sure we don't re-use articles
+  ;; Read the active file to make sure we don't reuse articles
   ;; numbers in empty groups.
   (nnmail-activate 'nndiary)
   (unless (nndiary-server-opened server)
diff --git a/lisp/gnus/nndir.el b/lisp/gnus/nndir.el
index 3b21a933409..039925331d1 100644
--- a/lisp/gnus/nndir.el
+++ b/lisp/gnus/nndir.el
@@ -1,6 +1,6 @@
 ;;; nndir.el --- single directory newsgroup access for Gnus  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/nndoc.el b/lisp/gnus/nndoc.el
index 0d499a15c3d..06a5e6808dd 100644
--- a/lisp/gnus/nndoc.el
+++ b/lisp/gnus/nndoc.el
@@ -1,6 +1,6 @@
 ;;; nndoc.el --- single file access for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nndraft.el b/lisp/gnus/nndraft.el
index bf90cfaa207..3ad495966f4 100644
--- a/lisp/gnus/nndraft.el
+++ b/lisp/gnus/nndraft.el
@@ -1,6 +1,6 @@
 ;;; nndraft.el --- draft article access for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/nneething.el b/lisp/gnus/nneething.el
index a6b5870ca98..9d1c676b912 100644
--- a/lisp/gnus/nneething.el
+++ b/lisp/gnus/nneething.el
@@ -1,6 +1,6 @@
 ;;; nneething.el --- arbitrary file access for Gnus  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nnfolder.el b/lisp/gnus/nnfolder.el
index 3516a75e927..66683f77433 100644
--- a/lisp/gnus/nnfolder.el
+++ b/lisp/gnus/nnfolder.el
@@ -1,6 +1,6 @@
 ;;; nnfolder.el --- mail folder access for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 ;;      ShengHuo Zhu <zsh@cs.rochester.edu> (adding NOV)
diff --git a/lisp/gnus/nngateway.el b/lisp/gnus/nngateway.el
index 152ef08f0f7..d7e772e8bf5 100644
--- a/lisp/gnus/nngateway.el
+++ b/lisp/gnus/nngateway.el
@@ -1,6 +1,6 @@
 ;;; nngateway.el --- posting news via mail gateways  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news, mail
diff --git a/lisp/gnus/nnheader.el b/lisp/gnus/nnheader.el
index 5dc5bf1fd75..97821894b48 100644
--- a/lisp/gnus/nnheader.el
+++ b/lisp/gnus/nnheader.el
@@ -1,6 +1,6 @@
 ;;; nnheader.el --- header access macros for Gnus and its backends  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1987-1990, 1993-1998, 2000-2023 Free Software
+;; Copyright (C) 1987-1990, 1993-1998, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index 81449cb58b2..17a55f988c9 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -1,6 +1,6 @@
 ;;; nnimap.el --- IMAP interface for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;         Simon Josefsson <simon@josefsson.org>
diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el
index 904b564409a..fef12eebe09 100644
--- a/lisp/gnus/nnmail.el
+++ b/lisp/gnus/nnmail.el
@@ -1,6 +1,6 @@
 ;;; nnmail.el --- mail support functions for the Gnus mail backends  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news, mail
diff --git a/lisp/gnus/nnmairix.el b/lisp/gnus/nnmairix.el
index deb2b669b6b..c517f85db9b 100644
--- a/lisp/gnus/nnmairix.el
+++ b/lisp/gnus/nnmairix.el
@@ -1,6 +1,6 @@
 ;;; nnmairix.el --- Mairix back end for Gnus, the Emacs newsreader  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: David Engster <deng@randomsample.de>
 ;; Keywords: mail searching
diff --git a/lisp/gnus/nnmbox.el b/lisp/gnus/nnmbox.el
index c1a064c27f3..ac6846dda05 100644
--- a/lisp/gnus/nnmbox.el
+++ b/lisp/gnus/nnmbox.el
@@ -1,6 +1,6 @@
 ;;; nnmbox.el --- mail mbox access for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nnmh.el b/lisp/gnus/nnmh.el
index bb5ea3fa1bb..e11d063f6ee 100644
--- a/lisp/gnus/nnmh.el
+++ b/lisp/gnus/nnmh.el
@@ -1,6 +1,6 @@
 ;;; nnmh.el --- mhspool access for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el
index d969716f020..7a37cb6090b 100644
--- a/lisp/gnus/nnml.el
+++ b/lisp/gnus/nnml.el
@@ -1,6 +1,6 @@
 ;;; nnml.el --- mail spool access for Gnus  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Authors: Didier Verna <didier@didierverna.net> (adding compaction)
 ;;     Simon Josefsson <simon@josefsson.org>
@@ -830,7 +830,7 @@ article number.  This function is called narrowed to an 
article."
 (defun nnml-generate-nov-databases (&optional server)
   "Generate NOV databases in all nnml directories."
   (interactive (list (or (nnoo-current-server 'nnml) "")))
-  ;; Read the active file to make sure we don't re-use articles
+  ;; Read the active file to make sure we don't reuse articles
   ;; numbers in empty groups.
   (nnmail-activate 'nnml)
   (unless (nnml-server-opened server)
diff --git a/lisp/gnus/nnoo.el b/lisp/gnus/nnoo.el
index 81ac2b65ff3..d280ff1bbb9 100644
--- a/lisp/gnus/nnoo.el
+++ b/lisp/gnus/nnoo.el
@@ -1,6 +1,6 @@
 ;;; nnoo.el --- OO Gnus Backends  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/nnregistry.el b/lisp/gnus/nnregistry.el
index 0702418a91a..55d77ea1fe4 100644
--- a/lisp/gnus/nnregistry.el
+++ b/lisp/gnus/nnregistry.el
@@ -1,6 +1,6 @@
 ;;; nnregistry.el --- access to articles via Gnus' message-id registry  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Ludovic Courtès <ludo@gnu.org>
 ;; Keywords: news, mail
diff --git a/lisp/gnus/nnrss.el b/lisp/gnus/nnrss.el
index 06a0bc7e799..fe2d0df5f3f 100644
--- a/lisp/gnus/nnrss.el
+++ b/lisp/gnus/nnrss.el
@@ -1,6 +1,6 @@
 ;;; nnrss.el --- interfacing with RSS  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
 ;; Keywords: RSS
diff --git a/lisp/gnus/nnselect.el b/lisp/gnus/nnselect.el
index c4fbe3a5bd2..c6a1c0a9342 100644
--- a/lisp/gnus/nnselect.el
+++ b/lisp/gnus/nnselect.el
@@ -1,6 +1,6 @@
 ;;; nnselect.el --- a virtual group backend   -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrew Cohen <cohen@andy.bu.edu>
 ;; Keywords: news mail
diff --git a/lisp/gnus/nnspool.el b/lisp/gnus/nnspool.el
index ca97afcb7f1..ce0aea8dd57 100644
--- a/lisp/gnus/nnspool.el
+++ b/lisp/gnus/nnspool.el
@@ -1,6 +1,6 @@
 ;;; nnspool.el --- spool access for GNU Emacs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1988-1990, 1993-1998, 2000-2023 Free Software
+;; Copyright (C) 1988-1990, 1993-1998, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el
index fb9d8fa53bf..fe165662988 100644
--- a/lisp/gnus/nntp.el
+++ b/lisp/gnus/nntp.el
@@ -1,6 +1,6 @@
 ;;; nntp.el --- nntp access for Gnus  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1987-1990, 1992-1998, 2000-2023 Free Software
+;; Copyright (C) 1987-1990, 1992-1998, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el
index c43abe57ee0..9eea0f89996 100644
--- a/lisp/gnus/nnvirtual.el
+++ b/lisp/gnus/nnvirtual.el
@@ -1,6 +1,6 @@
 ;;; nnvirtual.el --- virtual newsgroups access for Gnus  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: David Moore <dmoore@ucsd.edu>
 ;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/nnweb.el b/lisp/gnus/nnweb.el
index f175379f53d..c8a21792662 100644
--- a/lisp/gnus/nnweb.el
+++ b/lisp/gnus/nnweb.el
@@ -1,6 +1,6 @@
 ;;; nnweb.el --- retrieving articles via web search engines  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/gnus/score-mode.el b/lisp/gnus/score-mode.el
index e2c89ef8964..6906872c75d 100644
--- a/lisp/gnus/score-mode.el
+++ b/lisp/gnus/score-mode.el
@@ -1,6 +1,6 @@
 ;;; score-mode.el --- mode for editing Gnus score files  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news, mail
diff --git a/lisp/gnus/smiley.el b/lisp/gnus/smiley.el
index 3c17f9bf511..c39a5806951 100644
--- a/lisp/gnus/smiley.el
+++ b/lisp/gnus/smiley.el
@@ -1,6 +1,6 @@
 ;;; smiley.el --- displaying smiley faces  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: news mail multimedia
diff --git a/lisp/gnus/smime.el b/lisp/gnus/smime.el
index ddebfec078a..b61579912dd 100644
--- a/lisp/gnus/smime.el
+++ b/lisp/gnus/smime.el
@@ -1,6 +1,6 @@
 ;;; smime.el --- S/MIME support library  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 ;; Keywords: SMIME X.509 PEM OpenSSL
diff --git a/lisp/gnus/spam-report.el b/lisp/gnus/spam-report.el
index 8435d2d0124..c0158c2e795 100644
--- a/lisp/gnus/spam-report.el
+++ b/lisp/gnus/spam-report.el
@@ -1,6 +1,6 @@
 ;;; spam-report.el --- Reporting spam  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Ted Zlatanov <tzz@lifelogs.com>
 ;; Keywords: network, spam, mail, gmane, report
diff --git a/lisp/gnus/spam-stat.el b/lisp/gnus/spam-stat.el
index ee6da6ecb44..f4ad9e48f6f 100644
--- a/lisp/gnus/spam-stat.el
+++ b/lisp/gnus/spam-stat.el
@@ -1,6 +1,6 @@
 ;;; spam-stat.el --- detecting spam based on statistics  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <alex@gnu.org>
 ;; Keywords: network
diff --git a/lisp/gnus/spam-wash.el b/lisp/gnus/spam-wash.el
index 685cb7e92d0..94feaa27796 100644
--- a/lisp/gnus/spam-wash.el
+++ b/lisp/gnus/spam-wash.el
@@ -1,6 +1,6 @@
 ;;; spam-wash.el --- wash spam before analysis  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2004, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrew Cohen <cohen@andy.bu.edu>
 ;; Keywords: mail
diff --git a/lisp/gnus/spam.el b/lisp/gnus/spam.el
index c598b10bc08..1ae214ea4fa 100644
--- a/lisp/gnus/spam.el
+++ b/lisp/gnus/spam.el
@@ -1,6 +1,6 @@
 ;;; spam.el --- Identifying spam  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Maintainer: Ted Zlatanov <tzz@lifelogs.com>
diff --git a/lisp/help-at-pt.el b/lisp/help-at-pt.el
index 6c18a85ddfd..95d0fafc544 100644
--- a/lisp/help-at-pt.el
+++ b/lisp/help-at-pt.el
@@ -1,6 +1,6 @@
 ;;; help-at-pt.el --- local help through the keyboard  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Luc Teirlinck <teirllm@auburn.edu>
 ;; Keywords: help
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index a8c60946121..1ba848c107d 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -1,6 +1,6 @@
 ;;; help-fns.el --- Complex help functions -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-1986, 1993-1994, 1998-2023 Free Software
+;; Copyright (C) 1985-1986, 1993-1994, 1998-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -741,18 +741,28 @@ the C sources, too."
 
 (defun help-fns--parent-mode (function)
   ;; If this is a derived mode, link to the parent.
-  (let ((parent-mode (and (symbolp function)
-                          ;; FIXME: Should we mention other parent modes?
-                          (get function
-                               'derived-mode-parent))))
+  (when (symbolp function)
+    (let ((parent-mode (get function 'derived-mode-parent))
+          (extra-parents (get function 'derived-mode-extra-parents)))
     (when parent-mode
       (insert (substitute-quotes "  Parent mode: `"))
       (let ((beg (point)))
-        (insert (format "%s" parent-mode))
+        (insert (format "%S" parent-mode))
         (make-text-button beg (point)
                           'type 'help-function
                           'help-args (list parent-mode)))
-      (insert (substitute-quotes "'.\n")))))
+      (insert (substitute-quotes "'.\n")))
+    (when extra-parents
+      (insert (format "  Extra parent mode%s:" (if (cdr extra-parents) "s" 
"")))
+      (dolist (parent extra-parents)
+        (insert (substitute-quotes " `"))
+        (let ((beg (point)))
+          (insert (format "%S" parent))
+          (make-text-button beg (point)
+                            'type 'help-function
+                            'help-args (list parent)))
+        (insert (substitute-quotes "'")))
+      (insert ".\n")))))
 
 (defun help-fns--obsolete (function)
   ;; Ignore lambda constructs, keyboard macros, etc.
@@ -1789,9 +1799,8 @@ If FRAME is omitted or nil, use the selected frame."
                            alias)
                         ""))))
                  (insert "\nDocumentation:\n"
-                          (substitute-command-keys
-                           (or (face-documentation face)
-                               "Not documented as a face."))
+                          (or (face-documentation face)
+                              "Not documented as a face.")
                          "\n\n"))
                (with-current-buffer standard-output
                  (save-excursion
diff --git a/lisp/help-macro.el b/lisp/help-macro.el
index fac3419f184..cea8b379ec0 100644
--- a/lisp/help-macro.el
+++ b/lisp/help-macro.el
@@ -1,6 +1,6 @@
 ;;; help-macro.el --- makes command line help such as help-for-help  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Lynn Slater <lrs@indetech.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index b51276d5e06..9c405efeee5 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -1,6 +1,6 @@
 ;;; help-mode.el --- `help-mode' used by *Help* buffers  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1985-1986, 1993-1994, 1998-2023 Free Software
+;; Copyright (C) 1985-1986, 1993-1994, 1998-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/help.el b/lisp/help.el
index 889ecac94f3..eae29bb5734 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -1,6 +1,6 @@
 ;;; help.el --- help commands for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1986, 1993-1994, 1998-2023 Free Software
+;; Copyright (C) 1985-1986, 1993-1994, 1998-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -171,7 +171,10 @@ buffer.")
 
 ;; Inspired by a mg fork (https://github.com/troglobit/mg)
 (defun help-quick ()
-  "Display a quick-help buffer."
+  "Display a quick-help buffer showing popular commands and their bindings.
+The window showing quick-help can be toggled using \\[help-quick-toggle].
+You can click on a key binding shown in the quick-help buffer to display
+the documentation of the command bound to that key sequence."
   (interactive)
   (with-current-buffer (get-buffer-create "*Quick Help*")
     (let ((inhibit-read-only t) (padding 2) blocks)
@@ -246,10 +249,14 @@ buffer.")
       ;; ... and shrink it immediately.
       (fit-window-to-buffer))
     (message
-     (substitute-command-keys "Toggle the quick help buffer using 
\\[help-quick-toggle]."))))
+     (substitute-command-keys "Toggle display of quick-help buffer using 
\\[help-quick-toggle]."))))
 
 (defun help-quick-toggle ()
-  "Toggle the quick-help window."
+  "Toggle display of a window showing popular commands and their bindings.
+This toggles on and off the display of the quick-help buffer, which shows
+popular commands and their bindings as produced by `help-quick'.
+You can click on a key binding shown in the quick-help buffer to display
+the documentation of the command bound to that key sequence."
   (interactive)
   (if (and-let* ((window (get-buffer-window "*Quick Help*")))
         (quit-window t window))
diff --git a/lisp/hex-util.el b/lisp/hex-util.el
index 9b40c1d2799..9a9564c7095 100644
--- a/lisp/hex-util.el
+++ b/lisp/hex-util.el
@@ -1,6 +1,6 @@
 ;;; hex-util.el --- Functions to encode/decode hexadecimal string -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
 ;; Keywords: data
diff --git a/lisp/hexl.el b/lisp/hexl.el
index 5fa09459a46..1288cf4d7fb 100644
--- a/lisp/hexl.el
+++ b/lisp/hexl.el
@@ -1,6 +1,6 @@
 ;;; hexl.el --- edit a file in a hex dump format using the hexl filter -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1989, 1994, 1998, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1989, 1994, 1998, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Keith Gabryelski <ag@wheaties.ai.mit.edu>
diff --git a/lisp/hfy-cmap.el b/lisp/hfy-cmap.el
index 95f82a1f68c..ee8eac6732a 100644
--- a/lisp/hfy-cmap.el
+++ b/lisp/hfy-cmap.el
@@ -1,6 +1,6 @@
 ;;; hfy-cmap.el --- Fallback color name -> rgb mapping for `htmlfontify'  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2002-2003, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2009-2024 Free Software Foundation, Inc.
 
 ;; Emacs Lisp Archive Entry
 ;; Package: htmlfontify
diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el
index 5c536b190fb..516bee67dd0 100644
--- a/lisp/hi-lock.el
+++ b/lisp/hi-lock.el
@@ -1,6 +1,6 @@
 ;;; hi-lock.el --- minor mode for interactive automatic highlighting  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: David M. Koppelman <koppel@ece.lsu.edu>
 ;; Keywords: faces, minor-mode, matching, display
diff --git a/lisp/hilit-chg.el b/lisp/hilit-chg.el
index d5899175616..41bd4026b8e 100644
--- a/lisp/hilit-chg.el
+++ b/lisp/hilit-chg.el
@@ -1,6 +1,6 @@
 ;;; hilit-chg.el --- minor mode displaying buffer changes with special face  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Richard Sharman <rsharman@pobox.com>
 ;; Keywords: faces
diff --git a/lisp/hippie-exp.el b/lisp/hippie-exp.el
index 573366dd0a1..298634c2b7e 100644
--- a/lisp/hippie-exp.el
+++ b/lisp/hippie-exp.el
@@ -1,6 +1,6 @@
 ;;; hippie-exp.el --- expand text trying various ways to find its expansion  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Anders Holst <aho@sans.kth.se>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/hl-line.el b/lisp/hl-line.el
index 11631418c76..2826477c7ca 100644
--- a/lisp/hl-line.el
+++ b/lisp/hl-line.el
@@ -1,6 +1,6 @@
 ;;; hl-line.el --- highlight the current line  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el
index 6c303226e54..6b9c623f31f 100644
--- a/lisp/htmlfontify.el
+++ b/lisp/htmlfontify.el
@@ -1,6 +1,6 @@
 ;;; htmlfontify.el --- htmlize a buffer/source tree with optional hyperlinks 
-*- lexical-binding: t -*-
 
-;; Copyright (C) 2002-2003, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2009-2024 Free Software Foundation, Inc.
 
 ;; Emacs Lisp Archive Entry
 ;; Package: htmlfontify
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index 70c7516f903..95ff014aa5b 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -1,6 +1,6 @@
 ;;; ibuf-ext.el --- extensions for ibuffer  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Colin Walters <walters@verbum.org>
 ;; Maintainer: John Paul Wallington <jpw@gnu.org>
diff --git a/lisp/ibuf-macs.el b/lisp/ibuf-macs.el
index 36616389f99..1fd94967836 100644
--- a/lisp/ibuf-macs.el
+++ b/lisp/ibuf-macs.el
@@ -1,6 +1,6 @@
 ;;; ibuf-macs.el --- macros for ibuffer  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Colin Walters <walters@verbum.org>
 ;; Maintainer: John Paul Wallington <jpw@gnu.org>
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el
index 1368a62d87b..c65213f5bde 100644
--- a/lisp/ibuffer.el
+++ b/lisp/ibuffer.el
@@ -1,6 +1,6 @@
 ;;; ibuffer.el --- operate on buffers like dired  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Colin Walters <walters@verbum.org>
 ;; Maintainer: John Paul Wallington <jpw@gnu.org>
@@ -2376,135 +2376,135 @@ particular subset of them, and sorting by various 
criteria.
 
 Operations on marked buffers:
 \\<ibuffer-mode-map>
-  `\\[ibuffer-do-save]' - Save the marked buffers.
-  `\\[ibuffer-do-view]' - View the marked buffers in the selected frame.
-  `\\[ibuffer-do-view-other-frame]' - View the marked buffers in another frame.
-  `\\[ibuffer-do-revert]' - Revert the marked buffers.
-  `\\[ibuffer-do-toggle-read-only]' - Toggle read-only state of marked buffers.
-  `\\[ibuffer-do-toggle-lock]' - Toggle lock state of marked buffers.
-  `\\[ibuffer-do-delete]' - Kill the marked buffers.
-  `\\[ibuffer-do-isearch]' - Do incremental search in the marked buffers.
-  `\\[ibuffer-do-isearch-regexp]' - Isearch for regexp in the marked buffers.
-  `\\[ibuffer-do-replace-regexp]' - Replace by regexp in each of the marked
-          buffers.
-  `\\[ibuffer-do-query-replace]' - Query replace in each of the marked buffers.
-  `\\[ibuffer-do-query-replace-regexp]' - As above, with a regular expression.
-  `\\[ibuffer-do-print]' - Print the marked buffers.
-  `\\[ibuffer-do-occur]' - List lines in all marked buffers which match
-          a given regexp (like the function `occur').
-  `\\[ibuffer-do-shell-command-pipe]' - Pipe the contents of the marked
-          buffers to a shell command.
-  `\\[ibuffer-do-shell-command-pipe-replace]' - Replace the contents of the 
marked
-          buffers with the output of a shell command.
-  `\\[ibuffer-do-shell-command-file]' - Run a shell command with the
-          buffer's file as an argument.
-  `\\[ibuffer-do-eval]' - Evaluate a form in each of the marked buffers.  This
-          is a very flexible command.  For example, if you want to make all
-          of the marked buffers read-only, try using (read-only-mode 1) as
-          the input form.
-  `\\[ibuffer-do-view-and-eval]' - As above, but view each buffer while the 
form
-          is evaluated.
-  `\\[ibuffer-do-kill-lines]' - Remove the marked lines from the *Ibuffer* 
buffer,
-          but don't kill the associated buffer.
-  `\\[ibuffer-do-kill-on-deletion-marks]' - Kill all buffers marked for 
deletion.
+  \\[ibuffer-do-save] - Save the marked buffers.
+  \\[ibuffer-do-view] - View the marked buffers in the selected frame.
+  \\[ibuffer-do-view-other-frame] - View the marked buffers in another frame.
+  \\[ibuffer-do-revert] - Revert the marked buffers.
+  \\[ibuffer-do-toggle-read-only] - Toggle read-only state of marked buffers.
+  \\[ibuffer-do-toggle-lock] - Toggle lock state of marked buffers.
+  \\[ibuffer-do-delete] - Kill the marked buffers.
+  \\[ibuffer-do-isearch] - Do incremental search in the marked buffers.
+  \\[ibuffer-do-isearch-regexp] - Isearch for regexp in the marked buffers.
+  \\[ibuffer-do-replace-regexp] - Replace by regexp in each of the marked
+        buffers.
+  \\[ibuffer-do-query-replace] - Query replace in each of the marked buffers.
+  \\[ibuffer-do-query-replace-regexp] - As above, with a regular expression.
+  \\[ibuffer-do-print] - Print the marked buffers.
+  \\[ibuffer-do-occur] - List lines in all marked buffers which match
+        a given regexp (like the function `occur').
+  \\[ibuffer-do-shell-command-pipe] - Pipe the contents of the marked
+        buffers to a shell command.
+  \\[ibuffer-do-shell-command-pipe-replace] - Replace the contents of the 
marked
+        buffers with the output of a shell command.
+  \\[ibuffer-do-shell-command-file] - Run a shell command with the
+        buffer's file as an argument.
+  \\[ibuffer-do-eval] - Evaluate a form in each of the marked buffers.  This
+        is a very flexible command.  For example, if you want to make all
+        of the marked buffers read-only, try using (read-only-mode 1) as
+        the input form.
+  \\[ibuffer-do-view-and-eval] - As above, but view each buffer while the form
+        is evaluated.
+  \\[ibuffer-do-kill-lines] - Remove the marked lines from the *Ibuffer* 
buffer,
+        but don't kill the associated buffer.
+  \\[ibuffer-do-kill-on-deletion-marks] - Kill all buffers marked for deletion.
 
 Marking commands:
 
-  `\\[ibuffer-mark-forward]' - Mark the buffer at point.
-  `\\[ibuffer-toggle-marks]' - Unmark all currently marked buffers, and mark
-          all unmarked buffers.
-  `\\[ibuffer-change-marks]' - Change the mark used on marked buffers.
-  `\\[ibuffer-unmark-forward]' - Unmark the buffer at point.
-  `\\[ibuffer-unmark-backward]' - Unmark the previous buffer.
-  `\\[ibuffer-unmark-all]' - Unmark buffers marked with MARK.
-  `\\[ibuffer-unmark-all-marks]' - Unmark all marked buffers.
-  `\\[ibuffer-mark-by-mode]' - Mark buffers by major mode.
-  `\\[ibuffer-mark-unsaved-buffers]' - Mark all \"unsaved\" buffers.
-          This means that the buffer is modified, and has an associated file.
-  `\\[ibuffer-mark-modified-buffers]' - Mark all modified buffers,
-          regardless of whether they have an associated file.
-  `\\[ibuffer-mark-special-buffers]' - Mark all buffers whose name begins and
-          ends with `*'.
-  `\\[ibuffer-mark-dissociated-buffers]' - Mark all buffers which have
-          an associated file, but that file doesn't currently exist.
-  `\\[ibuffer-mark-read-only-buffers]' - Mark all read-only buffers.
-  `\\[ibuffer-mark-dired-buffers]' - Mark buffers in `dired-mode'.
-  `\\[ibuffer-mark-help-buffers]' - Mark buffers in `help-mode', 
`apropos-mode', etc.
-  `\\[ibuffer-mark-old-buffers]' - Mark buffers older than `ibuffer-old-time'.
-  `\\[ibuffer-mark-for-delete]' - Mark the buffer at point for deletion.
-  `\\[ibuffer-mark-by-name-regexp]' - Mark buffers by their name, using a 
regexp.
-  `\\[ibuffer-mark-by-mode-regexp]' - Mark buffers by their major mode, using 
a regexp.
-  `\\[ibuffer-mark-by-file-name-regexp]' - Mark buffers by their filename, 
using a regexp.
-  `\\[ibuffer-mark-by-content-regexp]' - Mark buffers by their content, using 
a regexp.
-  `\\[ibuffer-mark-by-locked]' - Mark all locked buffers.
+  \\[ibuffer-mark-forward] - Mark the buffer at point.
+  \\[ibuffer-toggle-marks] - Unmark all currently marked buffers, and mark
+        all unmarked buffers.
+  \\[ibuffer-change-marks] - Change the mark used on marked buffers.
+  \\[ibuffer-unmark-forward] - Unmark the buffer at point.
+  \\[ibuffer-unmark-backward] - Unmark the previous buffer.
+  \\[ibuffer-unmark-all] - Unmark buffers marked with MARK.
+  \\[ibuffer-unmark-all-marks] - Unmark all marked buffers.
+  \\[ibuffer-mark-by-mode] - Mark buffers by major mode.
+  \\[ibuffer-mark-unsaved-buffers] - Mark all \"unsaved\" buffers.
+        This means that the buffer is modified, and has an associated file.
+  \\[ibuffer-mark-modified-buffers] - Mark all modified buffers,
+        regardless of whether they have an associated file.
+  \\[ibuffer-mark-special-buffers] - Mark all buffers whose name begins and
+        ends with `*'.
+  \\[ibuffer-mark-dissociated-buffers] - Mark all buffers which have
+        an associated file, but that file doesn't currently exist.
+  \\[ibuffer-mark-read-only-buffers] - Mark all read-only buffers.
+  \\[ibuffer-mark-dired-buffers] - Mark buffers in `dired-mode'.
+  \\[ibuffer-mark-help-buffers] - Mark buffers in `help-mode', `apropos-mode', 
etc.
+  \\[ibuffer-mark-old-buffers] - Mark buffers older than `ibuffer-old-time'.
+  \\[ibuffer-mark-for-delete] - Mark the buffer at point for deletion.
+  \\[ibuffer-mark-by-name-regexp] - Mark buffers by their name, using a regexp.
+  \\[ibuffer-mark-by-mode-regexp] - Mark buffers by their major mode, using a 
regexp.
+  \\[ibuffer-mark-by-file-name-regexp] - Mark buffers by their filename, using 
a regexp.
+  \\[ibuffer-mark-by-content-regexp] - Mark buffers by their content, using a 
regexp.
+  \\[ibuffer-mark-by-locked] - Mark all locked buffers.
 
 Filtering commands:
 
-  `\\[ibuffer-filter-chosen-by-completion]' - Select and apply filter chosen 
by completion.
-  `\\[ibuffer-filter-by-mode]' - Add a filter by any major mode.
-  `\\[ibuffer-filter-by-used-mode]' - Add a filter by a major mode now in use.
-  `\\[ibuffer-filter-by-derived-mode]' - Add a filter by derived mode.
-  `\\[ibuffer-filter-by-name]' - Add a filter by buffer name.
-  `\\[ibuffer-filter-by-content]' - Add a filter by buffer content.
-  `\\[ibuffer-filter-by-basename]' - Add a filter by basename.
-  `\\[ibuffer-filter-by-directory]' - Add a filter by directory name.
-  `\\[ibuffer-filter-by-filename]' - Add a filter by filename.
-  `\\[ibuffer-filter-by-file-extension]' - Add a filter by file extension.
-  `\\[ibuffer-filter-by-modified]' - Add a filter by modified buffers.
-  `\\[ibuffer-filter-by-predicate]' - Add a filter by an arbitrary Lisp 
predicate.
-  `\\[ibuffer-filter-by-size-gt]' - Add a filter by buffer size.
-  `\\[ibuffer-filter-by-size-lt]' - Add a filter by buffer size.
-  `\\[ibuffer-filter-by-starred-name]' - Add a filter by special buffers.
-  `\\[ibuffer-filter-by-visiting-file]' - Add a filter by buffers visiting 
files.
-  `\\[ibuffer-save-filters]' - Save the current filters with a name.
-  `\\[ibuffer-switch-to-saved-filters]' - Switch to previously saved filters.
-  `\\[ibuffer-add-saved-filters]' - Add saved filters to current filters.
-  `\\[ibuffer-and-filter]' - Replace the top two filters with their logical 
AND.
-  `\\[ibuffer-or-filter]' - Replace the top two filters with their logical OR.
-  `\\[ibuffer-pop-filter]' - Remove the top filter.
-  `\\[ibuffer-negate-filter]' - Invert the logical sense of the top filter.
-  `\\[ibuffer-decompose-filter]' - Break down the topmost filter.
-  `\\[ibuffer-filter-disable]' - Remove all filtering currently in effect.
+  \\[ibuffer-filter-chosen-by-completion] - Select and apply filter chosen by 
completion.
+  \\[ibuffer-filter-by-mode] - Add a filter by any major mode.
+  \\[ibuffer-filter-by-used-mode] - Add a filter by a major mode now in use.
+  \\[ibuffer-filter-by-derived-mode] - Add a filter by derived mode.
+  \\[ibuffer-filter-by-name] - Add a filter by buffer name.
+  \\[ibuffer-filter-by-content] - Add a filter by buffer content.
+  \\[ibuffer-filter-by-basename] - Add a filter by basename.
+  \\[ibuffer-filter-by-directory] - Add a filter by directory name.
+  \\[ibuffer-filter-by-filename] - Add a filter by filename.
+  \\[ibuffer-filter-by-file-extension] - Add a filter by file extension.
+  \\[ibuffer-filter-by-modified] - Add a filter by modified buffers.
+  \\[ibuffer-filter-by-predicate] - Add a filter by an arbitrary Lisp 
predicate.
+  \\[ibuffer-filter-by-size-gt] - Add a filter by buffer size.
+  \\[ibuffer-filter-by-size-lt] - Add a filter by buffer size.
+  \\[ibuffer-filter-by-starred-name] - Add a filter by special buffers.
+  \\[ibuffer-filter-by-visiting-file] - Add a filter by buffers visiting files.
+  \\[ibuffer-save-filters] - Save the current filters with a name.
+  \\[ibuffer-switch-to-saved-filters] - Switch to previously saved filters.
+  \\[ibuffer-add-saved-filters] - Add saved filters to current filters.
+  \\[ibuffer-and-filter] - Replace the top two filters with their logical AND.
+  \\[ibuffer-or-filter] - Replace the top two filters with their logical OR.
+  \\[ibuffer-pop-filter] - Remove the top filter.
+  \\[ibuffer-negate-filter] - Invert the logical sense of the top filter.
+  \\[ibuffer-decompose-filter] - Break down the topmost filter.
+  \\[ibuffer-filter-disable] - Remove all filtering currently in effect.
 
 Filter group commands:
 
-  `\\[ibuffer-filters-to-filter-group]' - Create filter group from filters.
-  `\\[ibuffer-pop-filter-group]' - Remove top filter group.
-  `\\[ibuffer-forward-filter-group]' - Move to the next filter group.
-  `\\[ibuffer-backward-filter-group]' - Move to the previous filter group.
-  `\\[ibuffer-clear-filter-groups]' - Remove all active filter groups.
-  `\\[ibuffer-save-filter-groups]' - Save the current groups with a name.
-  `\\[ibuffer-switch-to-saved-filter-groups]' - Restore previously saved 
groups.
-  `\\[ibuffer-delete-saved-filter-groups]' - Delete previously saved groups.
+  \\[ibuffer-filters-to-filter-group] - Create filter group from filters.
+  \\[ibuffer-pop-filter-group] - Remove top filter group.
+  \\[ibuffer-forward-filter-group] - Move to the next filter group.
+  \\[ibuffer-backward-filter-group] - Move to the previous filter group.
+  \\[ibuffer-clear-filter-groups] - Remove all active filter groups.
+  \\[ibuffer-save-filter-groups] - Save the current groups with a name.
+  \\[ibuffer-switch-to-saved-filter-groups] - Restore previously saved groups.
+  \\[ibuffer-delete-saved-filter-groups] - Delete previously saved groups.
 
 Sorting commands:
 
-  `\\[ibuffer-toggle-sorting-mode]' - Rotate between the various sorting modes.
-  `\\[ibuffer-invert-sorting]' - Reverse the current sorting order.
-  `\\[ibuffer-do-sort-by-alphabetic]' - Sort the buffers lexicographically.
-  `\\[ibuffer-do-sort-by-filename/process]' - Sort the buffers by the file 
name.
-  `\\[ibuffer-do-sort-by-recency]' - Sort the buffers by last viewing time.
-  `\\[ibuffer-do-sort-by-size]' - Sort the buffers by size.
-  `\\[ibuffer-do-sort-by-major-mode]' - Sort the buffers by major mode.
+  \\[ibuffer-toggle-sorting-mode] - Rotate between the various sorting modes.
+  \\[ibuffer-invert-sorting] - Reverse the current sorting order.
+  \\[ibuffer-do-sort-by-alphabetic] - Sort the buffers lexicographically.
+  \\[ibuffer-do-sort-by-filename/process] - Sort the buffers by the file name.
+  \\[ibuffer-do-sort-by-recency] - Sort the buffers by last viewing time.
+  \\[ibuffer-do-sort-by-size] - Sort the buffers by size.
+  \\[ibuffer-do-sort-by-major-mode] - Sort the buffers by major mode.
 
 Other commands:
 
-  `\\[ibuffer-update]' - Regenerate the list of all buffers.
-          Prefix arg means to toggle whether buffers that match
-          `ibuffer-maybe-show-predicates' should be displayed.
-  `\\[ibuffer-auto-mode]' - Toggle automatic updates.
-
-  `\\[ibuffer-switch-format]' - Change the current display format.
-  `\\[forward-line]' - Move point to the next line.
-  `\\[previous-line]' - Move point to the previous line.
-  `\\[describe-mode]' - This help.
-  `\\[ibuffer-diff-with-file]' - View the differences between this buffer
-          and its associated file.
-  `\\[ibuffer-visit-buffer]' - View the buffer on this line.
-  `\\[ibuffer-visit-buffer-other-window]' - As above, but in another window.
-  `\\[ibuffer-visit-buffer-other-window-noselect]' - As both above, but don't 
select
-          the new window.
-  `\\[ibuffer-bury-buffer]' - Bury (not kill!) the buffer on this line.
+  \\[ibuffer-update] - Regenerate the list of all buffers.
+        Prefix arg means to toggle whether buffers that match
+        `ibuffer-maybe-show-predicates' should be displayed.
+  \\[ibuffer-auto-mode] - Toggle automatic updates.
+
+  \\[ibuffer-switch-format] - Change the current display format.
+  \\[forward-line] - Move point to the next line.
+  \\[previous-line] - Move point to the previous line.
+  \\[describe-mode] - This help.
+  \\[ibuffer-diff-with-file] - View the differences between this buffer
+        and its associated file.
+  \\[ibuffer-visit-buffer] - View the buffer on this line.
+  \\[ibuffer-visit-buffer-other-window] - As above, but in another window.
+  \\[ibuffer-visit-buffer-other-window-noselect] - As both above, but don't 
select
+        the new window.
+  \\[ibuffer-bury-buffer] - Bury (not kill!) the buffer on this line.
 
 ** Information on Filtering:
 
@@ -2525,7 +2525,7 @@ with \"gnus\".  You can accomplish this via:
   \\[ibuffer-filter-by-name] ^gnus RET
 
 Additionally, you can OR the top two filters together with
-`\\[ibuffer-or-filters]'.  To see all buffers in either
+\\[ibuffer-or-filters].  To see all buffers in either
 `emacs-lisp-mode' or `lisp-interaction-mode', type:
 
   \\[ibuffer-filter-by-mode] emacs-lisp-mode RET
@@ -2535,9 +2535,9 @@ Additionally, you can OR the top two filters together with
 Filters can also be saved and restored using mnemonic names: see the
 functions `ibuffer-save-filters' and `ibuffer-switch-to-saved-filters'.
 
-To remove the top filter on the stack, use `\\[ibuffer-pop-filter]', and
+To remove the top filter on the stack, use \\[ibuffer-pop-filter], and
 to disable all filtering currently in effect, use
-`\\[ibuffer-filter-disable]'.
+\\[ibuffer-filter-disable].
 
 ** Filter Groups:
 
@@ -2545,7 +2545,7 @@ Once one has mastered filters, the next logical step up 
is \"filter
 groups\".  A filter group is basically a named group of buffers which
 match a filter, which are displayed together in an Ibuffer buffer.  To
 create a filter group, simply use the regular functions to create a
-filter, and then type `\\[ibuffer-filters-to-filter-group]'.
+filter, and then type \\[ibuffer-filters-to-filter-group].
 
 A quick example will make things clearer.  Suppose that one wants to
 group all of one's Emacs Lisp buffers together.  To do this, type:
@@ -2563,7 +2563,7 @@ multiple filter groups; instead, the first filter group 
is used.  The
 filter groups are displayed in this order of precedence.
 
 You may rearrange filter groups by using the usual pair
-`\\[ibuffer-kill-line]' and `\\[ibuffer-yank]'.  Yanked groups
+\\[ibuffer-kill-line] and \\[ibuffer-yank].  Yanked groups
 will be inserted before the group at point."
   ;; Include state info next to the mode name.
   (setq-local mode-line-process
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index f4c4feb7304..aa3c5680a7e 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -1,6 +1,6 @@
 ;;; icomplete.el --- minibuffer completion incremental feedback -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: Ken Manheimer <ken dot manheimer at gmail...>
 ;; Created: Mar 1993 Ken Manheimer, klm@nist.gov - first release to usenet
@@ -789,10 +789,8 @@ and SUFFIX, if non-nil, are obtained from 
`affixation-function' or
 `group-function'.  Consecutive `equal' sections are avoided.
 COMP is the element in PROSPECTS or a transformation also given
 by `group-function''s second \"transformation\" protocol."
-  (let* ((aff-fun (or (completion-metadata-get md 'affixation-function)
-                      (plist-get completion-extra-properties 
:affixation-function)))
-         (ann-fun (or (completion-metadata-get md 'annotation-function)
-                      (plist-get completion-extra-properties 
:annotation-function)))
+  (let* ((aff-fun (completion-metadata-get md 'affixation-function))
+         (ann-fun (completion-metadata-get md 'annotation-function))
          (grp-fun (and completions-group
                        (completion-metadata-get md 'group-function)))
          (annotated
diff --git a/lisp/ido.el b/lisp/ido.el
index 2daf3bae717..6e51dc67196 100644
--- a/lisp/ido.el
+++ b/lisp/ido.el
@@ -1,6 +1,6 @@
 ;;; ido.el --- interactively do things with buffers and files -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Kim F. Storm <storm@cua.dk>
 ;; Based on: iswitchb by Stephen Eglen <stephen@cns.ed.ac.uk>
diff --git a/lisp/ielm.el b/lisp/ielm.el
index e51c46054b4..777aebb70cf 100644
--- a/lisp/ielm.el
+++ b/lisp/ielm.el
@@ -1,6 +1,6 @@
 ;;; ielm.el --- interaction mode for Emacs Lisp  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Smith <maa036@lancaster.ac.uk>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/iimage.el b/lisp/iimage.el
index b4c175a7b63..205141577c9 100644
--- a/lisp/iimage.el
+++ b/lisp/iimage.el
@@ -1,6 +1,6 @@
 ;;; iimage.el --- Inline image minor mode.  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: KOSEKI Yoshinori <kose@meadowy.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/image-file.el b/lisp/image-file.el
index a28da2f05ba..57e9799dc34 100644
--- a/lisp/image-file.el
+++ b/lisp/image-file.el
@@ -1,6 +1,6 @@
 ;;; image-file.el --- support for visiting image files  -*- lexical-binding:t 
-*-
 ;;
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Miles Bader <miles@gnu.org>
 ;; Keywords: multimedia
diff --git a/lisp/image-mode.el b/lisp/image-mode.el
index d5ca6348c92..355685e70fd 100644
--- a/lisp/image-mode.el
+++ b/lisp/image-mode.el
@@ -1,6 +1,6 @@
 ;;; image-mode.el --- support for visiting image files  -*- lexical-binding: t 
-*-
 ;;
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Richard Stallman <rms@gnu.org>
 ;; Keywords: multimedia
diff --git a/lisp/image.el b/lisp/image.el
index e20fbcf4c98..73801f88d1e 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -1,6 +1,6 @@
 ;;; image.el --- image API  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: multimedia
diff --git a/lisp/image/compface.el b/lisp/image/compface.el
index 25204147906..9fb139ad830 100644
--- a/lisp/image/compface.el
+++ b/lisp/image/compface.el
@@ -1,6 +1,6 @@
 ;;; compface.el --- functions for converting X-Face headers -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: multimedia, news
diff --git a/lisp/image/exif.el b/lisp/image/exif.el
index 4807df0fbbb..2c1c4850bef 100644
--- a/lisp/image/exif.el
+++ b/lisp/image/exif.el
@@ -1,6 +1,6 @@
 ;;; exif.el --- parsing Exif data in JPEG images -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: images
diff --git a/lisp/image/gravatar.el b/lisp/image/gravatar.el
index b2f0d453761..9e1cb7d50ad 100644
--- a/lisp/image/gravatar.el
+++ b/lisp/image/gravatar.el
@@ -1,6 +1,6 @@
 ;;; gravatar.el --- Get Gravatars -*- lexical-binding: t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Julien Danjou <julien@danjou.info>
 ;; Keywords: comm, multimedia
diff --git a/lisp/image/image-converter.el b/lisp/image/image-converter.el
index ff9d4ad0d82..2e2010e06f0 100644
--- a/lisp/image/image-converter.el
+++ b/lisp/image/image-converter.el
@@ -1,6 +1,6 @@
 ;;; image-converter.el --- Converting images from exotic formats -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: images
diff --git a/lisp/image/image-crop.el b/lisp/image/image-crop.el
index 9ef848c5bc8..0f0701dc2fd 100644
--- a/lisp/image/image-crop.el
+++ b/lisp/image/image-crop.el
@@ -1,6 +1,6 @@
 ;;; image-crop.el --- Image Cropping  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Keywords: multimedia
 
diff --git a/lisp/image/image-dired-dired.el b/lisp/image/image-dired-dired.el
index d522c06d10b..7219a106ca8 100644
--- a/lisp/image/image-dired-dired.el
+++ b/lisp/image/image-dired-dired.el
@@ -1,6 +1,6 @@
 ;;; image-dired-dired.el --- Dired specific commands for Image-Dired  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Mathias Dahl <mathias.rem0veth1s.dahl@gmail.com>
 ;; Maintainer: Stefan Kangas <stefankangas@gmail.com>
@@ -383,7 +383,7 @@ matching tag will be marked in the Dired buffer."
                       (file-name-directory curr-file)))
         (setq curr-file (file-name-nondirectory curr-file))
         (goto-char (point-min))
-        (when (search-forward-regexp (format "\\s %s$" curr-file) nil t)
+        (when (search-forward-regexp (format "\\s %s[*@]?$" curr-file) nil t)
           (setq hits (+ hits 1))
           (dired-mark 1))))
     (message "%d files with matching tag marked" hits)))
diff --git a/lisp/image/image-dired-external.el 
b/lisp/image/image-dired-external.el
index 1da41ad178f..8a73f518e6b 100644
--- a/lisp/image/image-dired-external.el
+++ b/lisp/image/image-dired-external.el
@@ -1,6 +1,6 @@
 ;;; image-dired-external.el --- External process support for Image-Dired  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Mathias Dahl <mathias.rem0veth1s.dahl@gmail.com>
 ;; Maintainer: Stefan Kangas <stefankangas@gmail.com>
diff --git a/lisp/image/image-dired-tags.el b/lisp/image/image-dired-tags.el
index 79ac6fb58f2..2b5248cb14b 100644
--- a/lisp/image/image-dired-tags.el
+++ b/lisp/image/image-dired-tags.el
@@ -1,6 +1,6 @@
 ;;; image-dired-tags.el --- Tag support for Image-Dired  -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Mathias Dahl <mathias.rem0veth1s.dahl@gmail.com>
 ;; Maintainer: Stefan Kangas <stefankangas@gmail.com>
@@ -51,6 +51,7 @@ Return the value of last form in BODY."
   "Check if `image-dired-tags-db-file' exists.
 If not, try to create it (including any parent directories).
 Signal error if there are problems creating it."
+  (require 'image-dired)                ; for `image-dired-dir'
   (or (file-exists-p image-dired-tags-db-file)
       (let (dir buf)
         (unless (file-directory-p (setq dir (file-name-directory
diff --git a/lisp/image/image-dired-util.el b/lisp/image/image-dired-util.el
index e17cc6c919f..c3860cb0b0a 100644
--- a/lisp/image/image-dired-util.el
+++ b/lisp/image/image-dired-util.el
@@ -1,6 +1,6 @@
 ;;; image-dired-util.el --- util functions for Image-Dired  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Mathias Dahl <mathias.rem0veth1s.dahl@gmail.com>
 ;; Maintainer: Stefan Kangas <stefankangas@gmail.com>
diff --git a/lisp/image/image-dired.el b/lisp/image/image-dired.el
index 83f228b2d59..9eb68e240fe 100644
--- a/lisp/image/image-dired.el
+++ b/lisp/image/image-dired.el
@@ -1,6 +1,6 @@
 ;;; image-dired.el --- use dired to browse and manipulate your images -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Mathias Dahl <mathias.rem0veth1s.dahl@gmail.com>
 ;; Maintainer: Stefan Kangas <stefankangas@gmail.com>
diff --git a/lisp/image/wallpaper.el b/lisp/image/wallpaper.el
index c778264d3ef..79682e921b0 100644
--- a/lisp/image/wallpaper.el
+++ b/lisp/image/wallpaper.el
@@ -1,6 +1,6 @@
 ;;; wallpaper.el --- Change the desktop background  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 ;; Keywords: images
diff --git a/lisp/imenu.el b/lisp/imenu.el
index c51824b7ef3..f628936cedc 100644
--- a/lisp/imenu.el
+++ b/lisp/imenu.el
@@ -1,6 +1,6 @@
 ;;; imenu.el --- framework for mode-specific buffer indexes  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1994-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Ake Stenhoff <etxaksf@aom.ericsson.se>
 ;;         Lars Lindberg <lli@sypro.cap.se>
diff --git a/lisp/indent-aux.el b/lisp/indent-aux.el
index ed41d4926f7..edcc6ffc22d 100644
--- a/lisp/indent-aux.el
+++ b/lisp/indent-aux.el
@@ -1,6 +1,6 @@
 ;;; indent-aux.el --- Autoloaded indentation commands for Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Package: emacs
diff --git a/lisp/indent.el b/lisp/indent.el
index f856f0c9ab5..74ef9183d95 100644
--- a/lisp/indent.el
+++ b/lisp/indent.el
@@ -1,6 +1,6 @@
 ;;; indent.el --- indentation commands for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985, 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Package: emacs
@@ -265,7 +265,7 @@ indentation by specifying a large negative ARG."
   (interactive "r\nP\np")
   (if (and (not arg) interactive)
       (set-transient-map indent-rigidly-map t #'deactivate-mark
-                         "Indent region with %k")
+                         "Type %k to indent region interactively")
     (save-excursion
       (goto-char end)
       (setq end (point-marker))
diff --git a/lisp/info-look.el b/lisp/info-look.el
index 8653a292a16..da7beafe500 100644
--- a/lisp/info-look.el
+++ b/lisp/info-look.el
@@ -1,6 +1,6 @@
 ;;; info-look.el --- major-mode-sensitive Info index lookup facility -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Ralph Schleicher <rs@ralph-schleicher.de>
 ;; Keywords: help languages
diff --git a/lisp/info-xref.el b/lisp/info-xref.el
index a910f38af84..95e9a1e55f7 100644
--- a/lisp/info-xref.el
+++ b/lisp/info-xref.el
@@ -1,6 +1,6 @@
 ;;; info-xref.el --- check external references in an Info document -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Kevin Ryde <user42@zip.com.au>
 ;; Keywords: docs
@@ -79,9 +79,11 @@ If removing the last \"-<NUM>\" from the filename gives a 
file
 which exists, then consider FILENAME a subfile.  This is an
 imperfect test, probably ought to open up the purported top file
 and see what subfiles it says."
-  (and (string-match "\\`\\(\\([^-]*-\\)*[^-]*\\)-[0-9]+\\(.*\\)\\'" filename)
-       (file-exists-p (concat (match-string 1 filename)
-                              (match-string 3 filename)))))
+  (let ((nondir (file-name-nondirectory filename)))
+    (and (string-match "\\`\\(\\([^-]*-\\)*[^-]*\\)-[0-9]+\\(.*\\)\\'" nondir)
+         (file-exists-p (concat (file-name-directory filename)
+                                (match-string 1 nondir)
+                                (match-string 3 nondir))))))
 
 (defmacro info-xref-with-file (filename &rest body)
   ;; checkdoc-params: (filename body)
diff --git a/lisp/info.el b/lisp/info.el
index 51e9eb72edf..e91cc7b8e54 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -1,6 +1,6 @@
 ;;; info.el --- Info package for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1986, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1992-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: help
@@ -213,6 +213,53 @@ a version of Emacs without installing it.")
 These directories are searched after those in `Info-directory-list'."
   :type '(repeat directory))
 
+(defcustom Info-url-alist
+  '((("auth" "autotype" "bovine" "calc" "ccmode" "cl" "dbus" "dired-x"
+      "ebrowse" "ede" "ediff" "edt" "efaq" "efaq-w32" "eglot" "eieio"
+      "eintr" "elisp" "emacs" "emacs-gnutls" "emacs-mime" "epa" "erc"
+      "ert" "eshell" "eudc" "eww" "flymake" "forms" "gnus"
+      "htmlfontify" "idlwave" "ido" "info" "mairix-el" "message"
+      "mh-e" "modus-themes" "newsticker" "nxml-mode" "octave-mode"
+      "org" "pcl-cvs" "pgg" "rcirc" "reftex" "remember" "sasl" "sc"
+      "semantic" "ses" "sieve" "smtpmail" "speedbar" "srecode"
+      "todo-mode" "tramp" "transient" "url" "use-package" "vhdl-mode"
+      "vip" "viper" "vtable" "widget" "wisent" "woman") .
+     "https://www.gnu.org/software/emacs/manual/html_node/%m/%e";))
+  "Alist telling `Info-mode' where manuals are accessible online.
+
+Each element of this list has the form (MANUALs . URL-SPEC).
+MANUALs represents the name of one or more manuals.  It can
+either be a string or a list of strings.  URL-SPEC can be a
+string in which the substring \"%m\" will be expanded to the
+manual-name, \"%n\" to the node-name, and \"%e\" to the
+URL-encoded node-name (without a `.html' suffix).  (The
+URL-encoding of the node-name mimics GNU Texinfo, as documented
+at Info node `(texinfo)HTML Xref Node Name Expansion'.)
+Alternatively, URL-SPEC can be a function which is given
+manual-name, node-name and URL-encoded node-name as arguments,
+and is expected to return the corresponding URL as a string.
+
+This variable particularly affects the command
+`Info-goto-node-web', which see.
+
+The default value of this variable refers to the official,
+HTTPS-accessible HTML-representations of all manuals that Emacs
+includes.  These URLs refer to the most recently released version
+of Emacs, disregarding the version of the running Emacs.  In
+other words, the content of your local Info node and the
+associated online node may differ.  The resource represented by
+the generated URL may even be not found by the gnu.org server."
+  :version "30.1"
+  :type '(alist
+           :tag "Mapping from manual-name(s) to URL-specification"
+           :key-type (choice
+                       (string :tag "A single manual-name")
+                       (repeat :tag "List of manual-names" string))
+           :value-type (choice
+                         (string :tag "URL-specification string")
+                         (function
+                           :tag "URL-specification function"))))
+
 (defcustom Info-scroll-prefer-subnodes nil
   "If non-nil, \\<Info-mode-map>\\[Info-scroll-up] in a menu visits subnodes.
 
@@ -732,8 +779,53 @@ in `Info-file-supports-index-cookies-list'."
                    (read-file-name "Info file name: " nil nil t))
                (if (numberp current-prefix-arg)
                    (format "*info*<%s>" current-prefix-arg))))
-  (info-setup file-or-node
-             (switch-to-buffer-other-window (or buffer "*info*"))))
+  (info-pop-to-buffer file-or-node buffer t))
+
+(defun info-pop-to-buffer (&optional file-or-node buffer-or-name other-window)
+  "Put Info node FILE-OR-NODE in specified buffer and display it.
+Optional argument FILE-OR-NODE is as for `info'.
+
+If the optional argument BUFFER-OR-NAME is a buffer, use that
+buffer.  If it is a string, use that string as the name of the
+buffer, creating it if it does not exist.  Otherwise, use a
+buffer with the name `*info*', creating it if it does not exist.
+
+Optional argument OTHER-WINDOW nil means to prefer the selected
+window.  OTHER-WINDOW non-nil means to prefer another window.
+Select the window used, if it has been made."
+  (let ((buffer (cond
+                ((bufferp buffer-or-name)
+                 buffer-or-name)
+                ((stringp buffer-or-name)
+                 (get-buffer-create buffer-or-name))
+                (t
+                 (get-buffer-create "*info*")))))
+    (with-current-buffer buffer
+      (unless (derived-mode-p 'Info-mode)
+       (Info-mode)))
+
+    (let* ((window
+           (display-buffer buffer
+                           (if other-window
+                               '(nil (inhibit-same-window . t))
+                             '(display-buffer-same-window)))))
+      (with-current-buffer buffer
+       (if file-or-node
+           ;; If argument already contains parentheses, don't add another set
+           ;; since the argument will then be parsed improperly.  This also
+           ;; has the added benefit of allowing node names to be included
+           ;; following the parenthesized filename.
+           (Info-goto-node
+            (if (and (stringp file-or-node) (string-match "(.*)" file-or-node))
+                file-or-node
+               (concat "(" file-or-node ")")))
+         (if (and (zerop (buffer-size))
+                  (null Info-history))
+             ;; If we just created the Info buffer, go to the directory.
+             (Info-directory))))
+
+      (when window
+       (select-window window)))))
 
 ;;;###autoload (put 'info 'info-file (purecopy "emacs"))
 ;;;###autoload
@@ -768,8 +860,8 @@ See a list of available Info commands in `Info-mode'."
     ;; of names that might have been wrapped (in emails, etc.).
     (setq file-or-node
           (string-replace "\n" " " file-or-node)))
-  (info-setup file-or-node
-             (pop-to-buffer-same-window (or buffer "*info*"))))
+
+  (info-pop-to-buffer file-or-node buffer))
 
 (defun info-setup (file-or-node buffer)
   "Display Info node FILE-OR-NODE in BUFFER."
@@ -789,6 +881,8 @@ See a list of available Info commands in `Info-mode'."
        ;; If we just created the Info buffer, go to the directory.
        (Info-directory))))
 
+(make-obsolete 'info-setup "use `info-pop-to-buffer' instead" "30.1")
+
 ;;;###autoload
 (defun info-emacs-manual ()
   "Display the Emacs manual in Info mode."
@@ -927,7 +1021,7 @@ If NOERROR, inhibit error messages when we can't find the 
node."
   (setq nodename (info--node-canonicalize-whitespace nodename))
   (setq filename (Info-find-file filename noerror))
   ;; Go into Info buffer.
-  (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
+  (or (derived-mode-p 'Info-mode) (info-pop-to-buffer filename))
   ;; Record the node we are leaving, if we were in one.
   (and (not no-going-back)
        Info-current-file
@@ -957,7 +1051,7 @@ otherwise, that defaults to `Top'."
   "Go to an Info node FILENAME and NODENAME, re-reading disk contents.
 When *info* is already displaying FILENAME and NODENAME, the window position
 is preserved, if possible."
-  (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
+  (or (derived-mode-p 'Info-mode) (info-pop-to-buffer filename))
   (let ((old-filename Info-current-file)
        (old-nodename Info-current-node)
        (window-selected (eq (selected-window) (get-buffer-window)))
@@ -1807,33 +1901,50 @@ By default, go to the current Info node."
      (Info-url-for-node (format "(%s)%s" filename node)))))
 
 (defun Info-url-for-node (node)
-  "Return a URL for NODE, a node in the GNU Emacs or Elisp manual.
-NODE should be a string on the form \"(manual)Node\".  Only emacs
-and elisp manuals are supported."
-  (unless (string-match "\\`(\\(.+\\))\\(.+\\)\\'" node)
-    (error "Invalid node name %s" node))
-  (let ((manual (match-string 1 node))
-        (node (match-string 2 node)))
-    (unless (member manual '("emacs" "elisp"))
-      (error "Only emacs/elisp manuals are supported"))
-    ;; Encode a bunch of characters the way that makeinfo does.
-    (setq node
-          (mapconcat (lambda (ch)
-                       (if (or (< ch 32)        ; ^@^A-^Z^[^\^]^^^-
+  "Return the URL corresponding to NODE.
+
+NODE should be a string of the form \"(manual)Node\"."
+  ;; GNU Texinfo skips whitespaces and newlines between the closing
+  ;; parenthesis and the node-name, i.e. space, tab, line feed and
+  ;; carriage return.
+  (unless (string-match "\\`(\\(.+\\))[ \t\n\r]*\\(.+\\)\\'" node)
+    (error "Invalid node-name %s" node))
+  ;; Use `if-let*' instead of `let*' so we check if an association was
+  ;; found.
+  (if-let* ((manual (match-string 1 node))
+             (node (match-string 2 node))
+             (association (seq-find
+                            (lambda (pair)
+                              (seq-contains-p (ensure-list (car pair))
+                                manual #'string-equal-ignore-case))
+                            Info-url-alist))
+             (url-spec (cdr association))
+             (encoded-node
+               ;; Reproduce GNU Texinfo's way of URL-encoding.
+               ;; (info "(texinfo) HTML Xref Node Name Expansion")
+               (if (equal node "Top")
+                 ""
+                 (url-hexify-string
+                   (string-replace " " "-"
+                     (mapconcat
+                       (lambda (ch)
+                         (if (or (< ch 32)      ; ^@^A-^Z^[^\^]^^^-
                                (<= 33 ch 47)    ; !"#$%&'()*+,-./
                                (<= 58 ch 64)    ; :;<=>?@
                                (<= 91 ch 96)    ; [\]_`
                                (<= 123 ch 127)) ; {|}~ DEL
                            (format "_00%x" ch)
-                         (char-to-string ch)))
-                     node
-                     ""))
-    (concat "https://www.gnu.org/software/emacs/manual/html_node/";
-            manual "/"
-            (and (not (equal node "Top"))
-                 (concat
-                  (url-hexify-string (string-replace " " "-" node))
-                  ".html")))))
+                           (char-to-string ch)))
+                       node ""))))))
+    (cond
+      ((stringp url-spec)
+        (format-spec url-spec
+          `((?m . ,manual) (?n . ,node) (?e . ,encoded-node))))
+      ((functionp url-spec)
+        (funcall url-spec manual node encoded-node))
+      (t (error "URL-specification neither string nor function")))
+    (error "No URL-specification associated with manual-name `%s'"
+      manual)))
 
 (defvar Info-read-node-completion-table)
 
@@ -2290,7 +2401,7 @@ This command doesn't descend into sub-nodes, like 
\\<Info-mode-map>\\[Info-forwa
   (interactive nil Info-mode)
   ;; In case another window is currently selected
   (save-window-excursion
-    (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
+    (or (derived-mode-p 'Info-mode) (info-pop-to-buffer))
     (Info-goto-node (Info-extract-pointer "next"))))
 
 (defun Info-prev ()
@@ -2299,7 +2410,7 @@ This command doesn't go up to the parent node, like 
\\<Info-mode-map>\\[Info-bac
   (interactive nil Info-mode)
   ;; In case another window is currently selected
   (save-window-excursion
-    (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
+    (or (derived-mode-p 'Info-mode) (info-pop-to-buffer))
     (Info-goto-node (Info-extract-pointer "prev[ious]*" "previous"))))
 
 (defun Info-up (&optional same-file)
@@ -2308,7 +2419,7 @@ If SAME-FILE is non-nil, do not move to a different Info 
file."
   (interactive nil Info-mode)
   ;; In case another window is currently selected
   (save-window-excursion
-    (or (derived-mode-p 'Info-mode) (switch-to-buffer "*info*"))
+    (or (derived-mode-p 'Info-mode) (info-pop-to-buffer))
     (let ((old-node Info-current-node)
          (old-file Info-current-file)
          (node (Info-extract-pointer "up")) p)
@@ -4686,8 +4797,14 @@ the variable `Info-file-list-for-emacs'."
                (eq command 'execute-extended-command))
           (Info-goto-emacs-command-node
            (read-command "Find documentation for command: ")))
+          ((symbolp command)
+           (Info-goto-emacs-command-node command))
          (t
-          (Info-goto-emacs-command-node command)))))
+          (message
+            (substitute-command-keys
+             (format
+              "\\`%s' invokes an anonymous command defined with `lambda'"
+              (key-description key))))))))
 
 (defvar Info-link-keymap
   (let ((keymap (make-sparse-keymap)))
@@ -5485,7 +5602,7 @@ completion alternatives to currently visited manuals."
                 (raise-frame (window-frame window))
                 (select-frame-set-input-focus (window-frame window))
                 (select-window window))
-           (switch-to-buffer found)))
+           (info-pop-to-buffer nil found)))
       ;; The buffer doesn't exist; create it.
       (info-initialize)
       (info (Info-find-file manual)
diff --git a/lisp/informat.el b/lisp/informat.el
index 6ef26d326a4..79ffad57302 100644
--- a/lisp/informat.el
+++ b/lisp/informat.el
@@ -1,6 +1,6 @@
 ;;; informat.el --- info support functions package for Emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1986, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: help
diff --git a/lisp/international/ccl.el b/lisp/international/ccl.el
index 7e58621a67f..b093df36a0f 100644
--- a/lisp/international/ccl.el
+++ b/lisp/international/ccl.el
@@ -1,6 +1,6 @@
 ;;; ccl.el --- CCL (Code Conversion Language) compiler  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/characters.el b/lisp/international/characters.el
index a48c0f77008..1e5963f89f3 100644
--- a/lisp/international/characters.el
+++ b/lisp/international/characters.el
@@ -1,6 +1,6 @@
 ;;; characters.el --- set syntax and category for multibyte characters  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2000-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
@@ -1696,6 +1696,9 @@ Setup `char-width-table' appropriate for non-CJK language 
environment."
 ;; Fix some exceptions that blocks.awk/Blocks.txt couldn't get right.
 (set-char-table-range char-script-table '(#x2ea . #x2eb) 'bopomofo)
 (set-char-table-range char-script-table #xab65 'greek)
+(set-char-table-range char-script-table #x16fe0 'tangut)
+(set-char-table-range char-script-table #x16fe1 'nushu)
+
 
 
 ;;; Setting unicode-category-table.
diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el
index f2814c7a84b..4f3aab5a6be 100644
--- a/lisp/international/emoji.el
+++ b/lisp/international/emoji.el
@@ -1,6 +1,6 @@
 ;;; emoji.el --- Inserting emojis  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: fun
@@ -683,11 +683,12 @@ We prefer the earliest unique letter."
                            strings))))
               (complete-with-action action table string pred)))
            nil t)))
-    (when (cl-plusp (length name))
-      (let ((glyph (if emoji-alternate-names
-                       (cadr (split-string name "\t"))
-                     (gethash name emoji--all-bases))))
-        (cons glyph (gethash glyph emoji--derived))))))
+    (if (cl-plusp (length name))
+        (let ((glyph (if emoji-alternate-names
+                         (cadr (split-string name "\t"))
+                       (gethash name emoji--all-bases))))
+          (cons glyph (gethash glyph emoji--derived)))
+      (user-error "You didn't specify an emoji"))))
 
 (defvar-keymap emoji-zoom-map
   "+" #'emoji-zoom-increase
diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el
index d879920b1d0..33e444507c4 100644
--- a/lisp/international/fontset.el
+++ b/lisp/international/fontset.el
@@ -1,6 +1,6 @@
 ;;; fontset.el --- commands for handling fontset  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
@@ -645,8 +645,14 @@
               (nil . "microsoft-cp1251")
               (nil . "koi8-r"))
 
-     (arabic ,(font-spec :registry "iso10646-1"
-                        :otf '(arab nil (init medi fina liga)))
+     (arabic ,(if (featurep 'android)
+                  ;; The Android font driver does not support the
+                  ;; detection of OTF tags but all fonts installed on
+                  ;; Android with Arabic characters provide shaping
+                  ;; information required for displaying Arabic text.
+                  (font-spec :registry "iso10646-1" :script 'arabic)
+                (font-spec :registry "iso10646-1"
+                          :otf '(arab nil (init medi fina liga))))
             (nil . "MuleArabic-0")
             (nil . "MuleArabic-1")
             (nil . "MuleArabic-2")
@@ -657,7 +663,9 @@
      (hebrew ,(font-spec :registry "iso10646-1" :script 'hebrew)
             (nil . "ISO8859-8"))
 
-     (khmer ,(font-spec :registry "iso10646-1" :otf '(khmr nil (pres))))
+     (khmer ,(if (featurep 'android)
+                 (font-spec :registry "iso10646-1" :script 'khmer)
+               (font-spec :registry "iso10646-1" :otf '(khmr nil (pres)))))
 
      (kana (nil . "JISX0208*")
           (nil . "GB2312.1980-0")
diff --git a/lisp/international/isearch-x.el b/lisp/international/isearch-x.el
index 448e633d0c2..2112ab921e2 100644
--- a/lisp/international/isearch-x.el
+++ b/lisp/international/isearch-x.el
@@ -1,6 +1,6 @@
 ;;; isearch-x.el --- extended isearch handling commands  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/iso-ascii.el b/lisp/international/iso-ascii.el
index 749118ea20f..a8129db9504 100644
--- a/lisp/international/iso-ascii.el
+++ b/lisp/international/iso-ascii.el
@@ -1,6 +1,6 @@
 ;;; iso-ascii.el --- set up char tables for ISO 8859/1 on ASCII terminals  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1987, 1995, 1998, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1987, 1995, 1998, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Howard Gayle
diff --git a/lisp/international/iso-cvt.el b/lisp/international/iso-cvt.el
index 0adf8a24092..7f052e3fe66 100644
--- a/lisp/international/iso-cvt.el
+++ b/lisp/international/iso-cvt.el
@@ -1,7 +1,7 @@
 ;;; iso-cvt.el --- translate ISO 8859-1 from/to various encodings -*- 
lexical-binding: t; -*-
 ;; This file was formerly called gm-lingo.el.
 
-;; Copyright (C) 1993-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Gschwind <mike@vlsivie.tuwien.ac.at>
 ;; Keywords: tex, iso, latin, i18n
diff --git a/lisp/international/iso-transl.el b/lisp/international/iso-transl.el
index cd83d723ece..67659f7c265 100644
--- a/lisp/international/iso-transl.el
+++ b/lisp/international/iso-transl.el
@@ -1,6 +1,6 @@
 ;;; iso-transl.el --- keyboard input for ISO 10646 chars -*- coding: utf-8; 
lexical-binding: t; -*-
 
-;; Copyright (C) 1987, 1993-1999, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1987, 1993-1999, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Howard Gayle
diff --git a/lisp/international/ja-dic-cnv.el b/lisp/international/ja-dic-cnv.el
index 81d5a1acdf4..6f3a0c929c5 100644
--- a/lisp/international/ja-dic-cnv.el
+++ b/lisp/international/ja-dic-cnv.el
@@ -1,6 +1,6 @@
 ;;; ja-dic-cnv.el --- convert a Japanese dictionary (SKK-JISYO.L) to Emacs 
Lisp  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
diff --git a/lisp/international/kinsoku.el b/lisp/international/kinsoku.el
index 93719768bac..7c2ad1abf29 100644
--- a/lisp/international/kinsoku.el
+++ b/lisp/international/kinsoku.el
@@ -1,6 +1,6 @@
 ;;; kinsoku.el --- `Kinsoku' processing funcs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/kkc.el b/lisp/international/kkc.el
index b10d3e76075..193c9c6147f 100644
--- a/lisp/international/kkc.el
+++ b/lisp/international/kkc.el
@@ -1,6 +1,6 @@
 ;;; kkc.el --- Kana Kanji converter  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/latexenc.el b/lisp/international/latexenc.el
index e245a099742..6e2306449bc 100644
--- a/lisp/international/latexenc.el
+++ b/lisp/international/latexenc.el
@@ -1,6 +1,6 @@
 ;;; latexenc.el --- guess correct coding system in LaTeX files -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Arne Jørgensen <arne@arnested.dk>
 ;; Keywords: mule, coding system, latex
diff --git a/lisp/international/latin1-disp.el 
b/lisp/international/latin1-disp.el
index d3a458ac516..69b9f81658b 100644
--- a/lisp/international/latin1-disp.el
+++ b/lisp/international/latin1-disp.el
@@ -1,6 +1,6 @@
 ;;; latin1-disp.el --- display tables for non-ASCII on Latin-1 terminals -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: i18n
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index fe3610b0fbc..6b4c83112e3 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -1,6 +1,6 @@
 ;;; mule-cmds.el --- commands for multilingual environment  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
@@ -2159,7 +2159,9 @@ See `set-language-info-alist' for use in programs."
   (interactive
    (list (read-language-name
          'documentation
-         (format-prompt "Describe language environment" 
current-language-environment))))
+         (format-prompt "Describe language environment"
+                         current-language-environment)
+          current-language-environment)))
   (let ((help-buffer-under-preparation t))
     (if (null language-name)
        (setq language-name current-language-environment))
diff --git a/lisp/international/mule-conf.el b/lisp/international/mule-conf.el
index f65f124b633..1a58e9b7068 100644
--- a/lisp/international/mule-conf.el
+++ b/lisp/international/mule-conf.el
@@ -1,6 +1,6 @@
 ;;; mule-conf.el --- configure multilingual environment  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 
2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
 ;;   Registration Number H14PRO021
diff --git a/lisp/international/mule-diag.el b/lisp/international/mule-diag.el
index 6a533f0418e..e8556119995 100644
--- a/lisp/international/mule-diag.el
+++ b/lisp/international/mule-diag.el
@@ -1,6 +1,6 @@
 ;;; mule-diag.el --- show diagnosis of multilingual environment (Mule)  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/mule-util.el b/lisp/international/mule-util.el
index c87a4a0ea95..504c15e749b 100644
--- a/lisp/international/mule-util.el
+++ b/lisp/international/mule-util.el
@@ -1,6 +1,6 @@
 ;;; mule-util.el --- utility functions for multilingual environment (mule)  
-*- lexical-binding:t -*-
 
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/mule.el b/lisp/international/mule.el
index b934485deeb..b4472561c59 100644
--- a/lisp/international/mule.el
+++ b/lisp/international/mule.el
@@ -1,6 +1,6 @@
 ;;; mule.el --- basic commands for multilingual environment  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/ogonek.el b/lisp/international/ogonek.el
index e2229be288e..4fddd2701d5 100644
--- a/lisp/international/ogonek.el
+++ b/lisp/international/ogonek.el
@@ -1,6 +1,6 @@
 ;;; ogonek.el --- change the encoding of Polish diacritics  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Włodek Bzyl
 ;;        Ryszard Kubiak
@@ -75,7 +75,7 @@ The codes are given in the following order:
 Je/sli czytasz ten tekst, to albo przegl/adasz plik /xr/od/lowy
 biblioteki `ogonek.el', albo wywo/la/le/s polecenie `ogonek-jak'.
 W drugim przypadku mo/zesz usun/a/c tekst z ekranu, stosuj/ac
-polecenie `\\[kill-buffer]'.
+polecenie \\[kill-buffer].
 
 Niniejsza biblioteka dostarcza funkcji do zmiany kodowania polskich
 znak/ow diakrytycznych. Funkcje te mo/zna pogrupowa/c nast/epuj/aco.
@@ -174,7 +174,7 @@ znak/ow diakrytycznych. Funkcje te mo/zna pogrupowa/c 
nast/epuj/aco.
 
 If you read this text then you are either looking at the library's
 source text or you have called the `ogonek-how' command.  In the
-latter case you may remove this text using `\\[kill-buffer]'.
+latter case you may remove this text using \\[kill-buffer].
 
 The library provides functions for changing the encoding of Polish
 diacritic characters, the ones with an `ogonek' below or above them.
diff --git a/lisp/international/quail.el b/lisp/international/quail.el
index 894378bda8b..48d2ccb8828 100644
--- a/lisp/international/quail.el
+++ b/lisp/international/quail.el
@@ -1,6 +1,6 @@
 ;;; quail.el --- provides simple input method for multilingual text  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
@@ -1324,9 +1324,11 @@ If STR has `advice' text property, append the following 
special event:
                ;; binding in `universal-argument-map' just return
                ;; (list KEY), otherwise act as if there was no
                ;; overriding map.
-               (or (not (eq (cadr overriding-terminal-local-map)
-                            universal-argument-map))
-                   (lookup-key overriding-terminal-local-map (vector key))))
+               ;; We used to do that only for `universal-argument-map',
+               ;; but according to bug#68338 this should also apply to
+               ;; other transient maps.  Let's hope it's OK to apply it
+               ;; to all `overriding-terminal-local-map's.
+               (lookup-key overriding-terminal-local-map (vector key)))
          overriding-local-map)
       (list key)
     (quail-setup-overlays (quail-conversion-keymap))
diff --git a/lisp/international/rfc1843.el b/lisp/international/rfc1843.el
index 287096ad352..10000cb24a3 100644
--- a/lisp/international/rfc1843.el
+++ b/lisp/international/rfc1843.el
@@ -1,6 +1,6 @@
 ;;; rfc1843.el --- HZ (RFC 1843) decoding  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
 ;; Keywords: news HZ HZ+ mail i18n
diff --git a/lisp/international/textsec-check.el 
b/lisp/international/textsec-check.el
index 6739f7b9a9d..3a0841c1b5a 100644
--- a/lisp/international/textsec-check.el
+++ b/lisp/international/textsec-check.el
@@ -1,6 +1,6 @@
 ;;; textsec-check.el --- Check for suspicious texts  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/international/textsec.el b/lisp/international/textsec.el
index e69e7c19842..86429f15f7c 100644
--- a/lisp/international/textsec.el
+++ b/lisp/international/textsec.el
@@ -1,6 +1,6 @@
 ;;; textsec.el --- Functions for handling homoglyphs and the like  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/international/titdic-cnv.el b/lisp/international/titdic-cnv.el
index abd4d3fd40b..c4706e061e3 100644
--- a/lisp/international/titdic-cnv.el
+++ b/lisp/international/titdic-cnv.el
@@ -1,6 +1,6 @@
 ;;; titdic-cnv.el --- convert cxterm dictionary (TIT format) to Quail package 
-*- coding: utf-8-emacs; lexical-binding:t -*-
 
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/ucs-normalize.el 
b/lisp/international/ucs-normalize.el
index 67e8ab428e9..ccb2022375c 100644
--- a/lisp/international/ucs-normalize.el
+++ b/lisp/international/ucs-normalize.el
@@ -1,6 +1,6 @@
 ;;; ucs-normalize.el --- Unicode normalization NFC/NFD/NFKD/NFKC  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Taichi Kawabata <kawabata.taichi@gmail.com>
 ;; Keywords: unicode, normalization
diff --git a/lisp/international/utf-7.el b/lisp/international/utf-7.el
index 335866f65ff..25f5e8367d8 100644
--- a/lisp/international/utf-7.el
+++ b/lisp/international/utf-7.el
@@ -1,6 +1,6 @@
 ;;; utf-7.el --- utf-7 coding system  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: i18n, mail
diff --git a/lisp/international/utf7.el b/lisp/international/utf7.el
index af66a7c2e01..63009b0744a 100644
--- a/lisp/international/utf7.el
+++ b/lisp/international/utf7.el
@@ -1,6 +1,6 @@
 ;;; utf7.el --- UTF-7 encoding/decoding for Emacs   -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Jon K Hellan <hellan@acm.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 4672440bdff..a139a6fb84e 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -1,6 +1,6 @@
 ;;; isearch.el --- incremental search minor mode -*- lexical-binding: t -*-
 
-;; Copyright (C) 1992-1997, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1997, 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
 ;; Maintainer: emacs-devel@gnu.org
@@ -282,13 +282,13 @@ Value is nil, t, or a function.
 
 If nil, default to literal searches (note that `case-fold-search'
 and `isearch-lax-whitespace' may still be applied).\\<isearch-mode-map>
-If t, default to regexp searches (as if typing `\\[isearch-toggle-regexp]' 
during
+If t, default to regexp searches (as if typing \\[isearch-toggle-regexp] during
 isearch).
 
 If a function, use that function as an `isearch-regexp-function'.
 Example functions (and the keys to toggle them during isearch)
-are `word-search-regexp' \(`\\[isearch-toggle-word]'), `isearch-symbol-regexp'
-\(`\\[isearch-toggle-symbol]'), and `char-fold-to-regexp' 
\(`\\[isearch-toggle-char-fold]')."
+are `word-search-regexp' \(\\[isearch-toggle-word]), `isearch-symbol-regexp'
+\(\\[isearch-toggle-symbol]), and `char-fold-to-regexp' 
\(\\[isearch-toggle-char-fold])."
   ;; :type is set below by `isearch-define-mode-toggle'.
   :type '(choice (const :tag "Literal search" nil)
                  (const :tag "Regexp search" t)
@@ -2875,7 +2875,8 @@ The command accepts Unicode names like \"smiling face\" or
       (isearch-search)
       (when (and (memq isearch-wrap-pause '(no no-ding))
                  (not isearch-success))
-        (isearch-repeat (if isearch-forward 'forward 'backward)))))
+        (let ((isearch-cmds isearch-cmds))
+          (isearch-repeat (if isearch-forward 'forward 'backward))))))
   (isearch-push-state)
   (if isearch-op-fun (funcall isearch-op-fun))
   (isearch-update))
diff --git a/lisp/isearchb.el b/lisp/isearchb.el
index 85b0b636c6c..8cde93ed846 100644
--- a/lisp/isearchb.el
+++ b/lisp/isearchb.el
@@ -1,6 +1,6 @@
 ;;; isearchb.el --- a marriage between iswitchb and isearch  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el
index d0522d6a791..05c0bd847b3 100644
--- a/lisp/jit-lock.el
+++ b/lisp/jit-lock.el
@@ -1,6 +1,6 @@
 ;;; jit-lock.el --- just-in-time fontification  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Gerd Moellmann <gerd@gnu.org>
 ;; Keywords: faces files
@@ -500,6 +500,7 @@ This applies to the buffer associated with marker START."
          (setq start (point-min) end (max start end)))
        ;; Don't cause refontification (it's already been done), but just do
        ;; some random buffer change, so as to force redisplay.
+       (put-text-property start end 'fontified nil)
        (put-text-property start end 'fontified t)))))
 
 ;;; Stealth fontification.
diff --git a/lisp/jka-cmpr-hook.el b/lisp/jka-cmpr-hook.el
index ad55475be25..ced998fafb6 100644
--- a/lisp/jka-cmpr-hook.el
+++ b/lisp/jka-cmpr-hook.el
@@ -1,6 +1,6 @@
 ;;; jka-cmpr-hook.el --- preloaded code to enable jka-compr.el  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1995, 1997, 1999-2000, 2002-2023 Free Software
+;; Copyright (C) 1993-1995, 1997, 1999-2000, 2002-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Jay K. Adams <jka@ece.cmu.edu>
diff --git a/lisp/jka-compr.el b/lisp/jka-compr.el
index 265df109669..8e6d14cc290 100644
--- a/lisp/jka-compr.el
+++ b/lisp/jka-compr.el
@@ -1,6 +1,6 @@
 ;;; jka-compr.el --- reading/writing/loading compressed files  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
 ;; Author: Jay K. Adams <jka@ece.cmu.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/json.el b/lisp/json.el
index 5c2b46cdb4e..524a048f1d8 100644
--- a/lisp/json.el
+++ b/lisp/json.el
@@ -1,6 +1,6 @@
 ;;; json.el --- JavaScript Object Notation parser / generator -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Theresa O'Connor <ted@oconnor.cx>
 ;; Version: 1.5
diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el
index 7caa8a6612c..14fe0447008 100644
--- a/lisp/jsonrpc.el
+++ b/lisp/jsonrpc.el
@@ -1,10 +1,10 @@
 ;;; jsonrpc.el --- JSON-RPC library                  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: João Távora <joaotavora@gmail.com>
 ;; Keywords: processes, languages, extensions
-;; Version: 1.0.18
+;; Version: 1.0.24
 ;; Package-Requires: ((emacs "25.2"))
 
 ;; This is a GNU ELPA :core package.  Avoid functionality that is not
@@ -51,6 +51,7 @@
 (defclass jsonrpc-connection ()
   ((name
     :accessor jsonrpc-name
+    :initform "anonymous"
     :initarg :name
     :documentation "A name for the connection")
    (-request-dispatcher
@@ -67,31 +68,36 @@
     :initform nil
     :accessor jsonrpc-last-error
     :documentation "Last JSONRPC error message received from endpoint.")
-   (-request-continuations
-    :initform (make-hash-table)
-    :accessor jsonrpc--request-continuations
-    :documentation "A hash table of request ID to continuation lambdas.")
+   (-continuations
+    :initform nil
+    :accessor jsonrpc--continuations
+    :documentation "An alist of request IDs to continuation specs.")
    (-events-buffer
     :initform nil
     :accessor jsonrpc--events-buffer
     :documentation "A buffer pretty-printing the JSONRPC events")
-   (-events-buffer-scrollback-size
-    :initarg :events-buffer-scrollback-size
-    :initform nil
-    :accessor jsonrpc--events-buffer-scrollback-size
-    :documentation "Max size of events buffer.  0 disables, nil means 
infinite.")
+   (-events-buffer-config
+    :initform '(:size nil :format full)
+    :initarg :events-buffer-config
+    :documentation "Plist configuring the events buffer functions.")
    (-deferred-actions
     :initform (make-hash-table :test #'equal)
     :accessor jsonrpc--deferred-actions
     :documentation "Map (DEFERRED BUF) to (FN TIMER ID).  FN is\
 a saved DEFERRED `async-request' from BUF, to be sent not later\
 than TIMER as ID.")
+   (-sync-request-alist ; bug#67945
+    :initform nil
+    :accessor jsonrpc--sync-request-alist
+    :documentation "List of ((ID [ANXIOUS...])) where ID refers  \
+to a sync `jsonrpc-request' and each ANXIOUS to another completed\
+request that is higher up in the stack but couldn't run.")
    (-next-request-id
     :initform 0
     :accessor jsonrpc--next-request-id
     :documentation "Next number used for a request"))
   :documentation "Base class representing a JSONRPC connection.
-The following initargs are accepted:
+The following keyword argument initargs are accepted:
 
 :NAME (mandatory), a string naming the connection
 
@@ -105,7 +111,33 @@ RESULT) or signal an error of type `jsonrpc-error'.
 :NOTIFICATION-DISPATCHER (optional), a function of three
 arguments (CONN METHOD PARAMS) for handling JSONRPC
 notifications.  CONN, METHOD and PARAMS are the same as in
-:REQUEST-DISPATCHER.")
+:REQUEST-DISPATCHER.
+
+:EVENTS-BUFFER-CONFIG is a plist.  Its `:size' stipulates the
+size of the log buffer (0 disables, nil means infinite).  The
+`:format' property is a symbol for choosing the log entry format.")
+
+(cl-defmethod initialize-instance :after
+  ((c jsonrpc-connection) ((&key (events-buffer-scrollback-size
+                                  nil
+                                  e-b-s-s-supplied-p)
+                                 &allow-other-keys)
+                           t))
+  (when e-b-s-s-supplied-p
+    (warn
+     "`:events-buffer-scrollback-size' deprecated. Use 
`events-buffer-config'.")
+    (with-slots ((plist -events-buffer-config)) c
+      (setf plist (copy-sequence plist)
+            plist (plist-put plist :size events-buffer-scrollback-size)))))
+
+(cl-defmethod slot-missing ((_c jsonrpc-connection)
+                            (_n (eql :events-buffer-scrollback-size))
+                            (_op (eql oset))
+                            _)
+  ;; Yuck!  But this just coerces EIEIO to backward-compatibly accept
+  ;; the :e-b-s-s initarg that is no longer associated with a slot
+  ;; #pineForCLOS..
+  )
 
 ;;; API mandatory
 (cl-defgeneric jsonrpc-connection-send (conn &key id method params result 
error)
@@ -132,6 +164,41 @@ immediately."
   (:method (_s _what)   ;; by default all connections are ready
            t))
 
+;;; API optional
+(cl-defgeneric jsonrpc-convert-to-endpoint (connection message subtype)
+  "Convert MESSAGE to JSONRPCesque message accepted by endpoint.
+MESSAGE is a plist, jsonrpc.el's internal representation of a
+JSONRPC message.  SUBTYPE is one of `request', `reply' or
+`notification'.
+
+Return a plist to be serialized to JSON with `json-serialize' and
+transmitted to endpoint."
+  ;; TODO: describe representations and serialization in manual and
+  ;; link here.
+  (:method (_s message subtype)
+           `(:jsonrpc "2.0"
+                      ,@(if (eq subtype 'reply)
+                            ;; true JSONRPC doesn't have `method'
+                            ;; fields in responses.
+                            (cl-loop for (k v) on message by #'cddr
+                                     unless (eq k :method)
+                                     collect k and collect v)
+                          message))))
+
+;;; API optional
+(cl-defgeneric jsonrpc-convert-from-endpoint (connection remote-message)
+  "Convert JSONRPC-esque REMOTE-MESSAGE to a plist.
+REMOTE-MESSAGE is a plist read with `json-parse'.
+
+Return a plist of jsonrpc.el's internal representation of a
+JSONRPC message."
+  ;; TODO: describe representations and serialization in manual and
+  ;; link here.
+  (:method (_s remote-message)
+           (cl-loop for (k v) on remote-message by #'cddr
+                    unless (eq k :jsonrpc-json)
+                    collect k and collect v)))
+
 
 ;;; Convenience
 ;;;
@@ -154,58 +221,107 @@ immediately."
 
 (defun jsonrpc-forget-pending-continuations (connection)
   "Stop waiting for responses from the current JSONRPC CONNECTION."
-  (clrhash (jsonrpc--request-continuations connection)))
+  (setf (jsonrpc--continuations connection) nil))
 
 (defvar jsonrpc-inhibit-debug-on-error nil
   "Inhibit `debug-on-error' when answering requests.
 Some extensions, notably ert.el, set `debug-on-error' to non-nil,
-which makes it hard to test the behaviour of catching the Elisp
+which makes it hard to test the behavior of catching the Elisp
 error and replying to the endpoint with an JSONRPC-error.  This
 variable can be set around calls like `jsonrpc-request' to
 circumvent that.")
 
-(defun jsonrpc-connection-receive (connection message)
-  "Process MESSAGE just received from CONNECTION.
+(defun jsonrpc-connection-receive (conn foreign-message)
+  "Process FOREIGN-MESSAGE just received from CONN.
 This function will destructure MESSAGE and call the appropriate
-dispatcher in CONNECTION."
-  (cl-destructuring-bind (&key method id error params result _jsonrpc)
-      message
-    (let (continuations)
-      (jsonrpc--log-event connection message 'server)
-      (setf (jsonrpc-last-error connection) error)
-      (cond
-       (;; A remote request
-        (and method id)
-        (let* ((debug-on-error (and debug-on-error
-                                    (not jsonrpc-inhibit-debug-on-error)))
-               (reply
-                (condition-case-unless-debug _ignore
-                    (condition-case oops
-                        `(:result ,(funcall (jsonrpc--request-dispatcher 
connection)
-                                            connection (intern method) params))
-                      (jsonrpc-error
-                       `(:error
-                         (:code
-                          ,(or (alist-get 'jsonrpc-error-code (cdr oops)) 
-32603)
-                          :message ,(or (alist-get 'jsonrpc-error-message
-                                                   (cdr oops))
-                                        "Internal error")))))
-                  (error
-                   '(:error (:code -32603 :message "Internal error"))))))
-          (apply #'jsonrpc--reply connection id reply)))
-       (;; A remote notification
-        method
-        (funcall (jsonrpc--notification-dispatcher connection)
-                 connection (intern method) params))
-       (;; A remote response
-        (setq continuations
-              (and id (gethash id (jsonrpc--request-continuations 
connection))))
-        (let ((timer (nth 2 continuations)))
-          (when timer (cancel-timer timer)))
-        (remhash id (jsonrpc--request-continuations connection))
-        (if error (funcall (nth 1 continuations) error)
-          (funcall (nth 0 continuations) result))))
-      (jsonrpc--call-deferred connection))))
+dispatcher in CONN."
+  (cl-destructuring-bind (&rest whole &key method id error params result 
_jsonrpc)
+      (jsonrpc-convert-from-endpoint conn foreign-message)
+    (unwind-protect
+        (let* ((log-plist (list :json (plist-get foreign-message :jsonrpc-json)
+                                :kind (cond ((and method id) 'request)
+                                            (method          'notification)
+                                            (id              'reply))
+                                :message whole
+                                :foreign-message foreign-message))
+               (response-p (and (null method) id))
+               (cont (and response-p (jsonrpc--remove conn id))))
+          (cl-remf foreign-message :jsonrpc-json)
+          ;; Do this pre-processing of the response so we can always
+          ;; log richer information _before_ any non-local calls
+          ;; further ahead. Putting the `jsonrpc--event' as
+          ;; an unwind-form would make us log after the fact.
+          (when cont
+            (pcase-let ((`(,_ ,method ,_ ,_ ,_) cont))
+              (if (keywordp method)
+                  (setq method (substring (symbol-name method) 1)))
+              ;; TODO: also set the depth
+              (setq whole (plist-put whole :method method))))
+
+          ;; Do the logging
+          (apply #'jsonrpc--event conn 'server log-plist)
+          (with-slots (last-error
+                       (rdispatcher -request-dispatcher)
+                       (ndispatcher -notification-dispatcher)
+                       (sr-alist -sync-request-alist))
+              conn
+            (setf last-error error)
+            (cond
+             (;; A remote response whose request has been canceled
+              ;; (i.e. timeout or C-g)
+              ;;
+              (and response-p (null cont))
+              (jsonrpc--event
+               conn 'internal
+               :log-text
+               (format "Response to request %s which has been canceled"
+                       id)
+               :id id)
+              ;; TODO: food for thought: this seems to be also where
+              ;; notifying the server of the cancellation would come
+              ;; in.
+              )
+             (;; A remote response that can't run yet (bug#67945)
+              (and response-p
+                   (and sr-alist (not (eq id (caar sr-alist)))))
+              (jsonrpc--event
+               conn 'internal
+               :log-text
+               (format "anxious continuation to %s can't run, held up by %s"
+                       id
+                       (mapcar #'car sr-alist)))
+              (push (cons cont (list result error))
+                    (cdr (car sr-alist))))
+             (;; A remote response that can continue now
+              response-p
+              (jsonrpc--continue conn id cont result error))
+             (;; A remote request
+              (and method id)
+              (let* ((debug-on-error (and debug-on-error
+                                          (not 
jsonrpc-inhibit-debug-on-error)))
+                     (reply
+                      (condition-case-unless-debug _ignore
+                          (condition-case oops
+                              `(:result ,(funcall rdispatcher conn (intern 
method)
+                                                  params))
+                            (jsonrpc-error
+                             `(:error
+                               (:code
+                                ,(or (alist-get 'jsonrpc-error-code (cdr oops))
+                                     -32603)
+                                :message ,(or (alist-get 'jsonrpc-error-message
+                                                         (cdr oops))
+                                              "Internal error")))))
+                        (error
+                         '(:error (:code -32603 :message "Internal error"))))))
+                (apply #'jsonrpc--reply conn id method reply)))
+             (;; A remote notification
+              method
+              (funcall ndispatcher conn (intern method) params))
+             (t
+              (jsonrpc--event conn 'internal
+                              :log-text "Malformed message" )))))
+      (jsonrpc--call-deferred conn))))
 
 
 ;;; Contacting the remote endpoint
@@ -298,6 +414,7 @@ ignored."
                  (apply
                   #'jsonrpc--async-request-1
                   connection method params
+                  :sync-request t
                   :success-fn (lambda (result)
                                 (unless canceled
                                   (throw tag `(done ,result))))
@@ -320,15 +437,19 @@ ignored."
                          (setq canceled t))
                        `(canceled ,cancel-on-input-retval))
                       (t (while t (accept-process-output nil 30)))))
-            ;; In normal operation, cancellation is handled by the
-            ;; timeout function and response filter, but we still have
-            ;; to protect against user-quit (C-g) or the
-            ;; `cancel-on-input' case.
-            (pcase-let* ((`(,id ,timer) id-and-timer))
-              (remhash id (jsonrpc--request-continuations connection))
-              (remhash (list deferred (current-buffer))
-                       (jsonrpc--deferred-actions connection))
-              (when timer (cancel-timer timer))))))
+            ;; In normal operation, continuations for error/success is
+            ;; handled by `jsonrpc--continue'.  Timeouts also remove
+            ;; the continuation...
+            (pcase-let* ((`(,id ,_) id-and-timer))
+              ;; ...but we still have to guard against exist explicit
+              ;; user-quit (C-g) or the `cancel-on-input' case, so
+              ;; discard the continuation.
+              (jsonrpc--remove connection id (list deferred (current-buffer)))
+              ;; ...finally, whatever may have happened to this sync
+              ;; request, it might have been holding up any outer
+              ;; "anxious" continuations.  The following ensures we
+              ;; cll them.
+              (jsonrpc--continue connection id)))))
     (when (eq 'error (car retval))
       (signal 'jsonrpc-error
               (cons
@@ -364,22 +485,25 @@ ignored."
     :accessor jsonrpc--on-shutdown
     :initform #'ignore
     :initarg :on-shutdown
-    :documentation "Function run when the process dies."))
+    :documentation "Function run when the process dies.")
+   (-autoport-inferior
+    :initform nil
+    :documentation "Used by `jsonrpc-autoport-bootstrap'."))
   :documentation "A JSONRPC connection over an Emacs process.
 The following initargs are accepted:
 
 :PROCESS (mandatory), a live running Emacs process object or a
-function of no arguments producing one such object.  The process
-represents either a pipe connection to locally running process or
-a stream connection to a network host.  The remote endpoint is
-expected to understand JSONRPC messages with basic HTTP-style
-enveloping headers such as \"Content-Length:\".
+function producing one such object.  If a function, it is passed
+the `jsonrpc-process-connection' object.  The process represents
+either a pipe connection to locally running process or a stream
+connection to a network host.  The remote endpoint is expected to
+understand JSONRPC messages with basic HTTP-style enveloping
+headers such as \"Content-Length:\".
 
 :ON-SHUTDOWN (optional), a function of one argument, the
 connection object, called when the process dies.")
 
-(cl-defmethod initialize-instance ((conn jsonrpc-process-connection) slots)
-  (cl-call-next-method)
+(cl-defmethod initialize-instance :after ((conn jsonrpc-process-connection) 
slots)
   (cl-destructuring-bind (&key ((:process proc)) name &allow-other-keys) slots
     ;; FIXME: notice the undocumented bad coupling in the stderr
     ;; buffer name, it must be named exactly like this we expect when
@@ -388,37 +512,22 @@ connection object, called when the process dies.")
     ;; could use a pipe with a process filter instead of
     ;; `after-change-functions'.  Alternatively, we need a new initarg
     ;; (but maybe not a slot).
-    (let ((calling-buffer (current-buffer)))
-      (with-current-buffer (get-buffer-create (format "*%s stderr*" name))
-        (let ((inhibit-read-only t)
-              (hidden-name (concat " " (buffer-name))))
-          (erase-buffer)
-          (buffer-disable-undo)
-          (add-hook
-           'after-change-functions
-           (lambda (beg _end _pre-change-len)
-             (cl-loop initially (goto-char beg)
-                      do (forward-line)
-                      when (bolp)
-                      for line = (buffer-substring
-                                  (line-beginning-position 0)
-                                  (line-end-position 0))
-                      do (with-current-buffer (jsonrpc-events-buffer conn)
-                           (goto-char (point-max))
-                           (let ((inhibit-read-only t))
-                             (insert (format "[stderr] %s\n" line))))
-                      until (eobp)))
-           nil t)
-          ;; If we are correctly coupled to the client, the process
-          ;; now created should pick up the current stderr buffer,
-          ;; which we immediately rename
-          (setq proc (if (functionp proc)
-                         (with-current-buffer calling-buffer (funcall proc))
-                       proc))
-          (ignore-errors (kill-buffer hidden-name))
-          (rename-buffer hidden-name)
-          (process-put proc 'jsonrpc-stderr (current-buffer))
-          (setq buffer-read-only t))))
+    (let* ((stderr-buffer-name (format "*%s stderr*" name))
+           (stderr-buffer (jsonrpc--forwarding-buffer stderr-buffer-name 
"[stderr] " conn))
+           (hidden-name (concat " " stderr-buffer-name)))
+      ;; If we are correctly coupled to the client, the process now
+      ;; created should pick up the `stderr-buffer' just created, which
+      ;; we immediately rename
+      (setq proc (if (functionp proc)
+                     (if (zerop (cdr (func-arity proc)))
+                         (funcall proc)
+                       (funcall proc conn))
+                   proc))
+      (with-current-buffer stderr-buffer
+        (ignore-errors (kill-buffer hidden-name))
+        (rename-buffer hidden-name)
+        (setq buffer-read-only t))
+      (process-put proc 'jsonrpc-stderr stderr-buffer))
     (setf (jsonrpc--process conn) proc)
     (set-process-buffer proc (get-buffer-create (format " *%s output*" name)))
     (set-process-filter proc #'jsonrpc--process-filter)
@@ -434,29 +543,42 @@ connection object, called when the process dies.")
 (cl-defmethod jsonrpc-connection-send ((connection jsonrpc-process-connection)
                                        &rest args
                                        &key
-                                       _id
+                                       id
                                        method
                                        _params
-                                       _result
-                                       _error
+                                       (_result nil result-supplied-p)
+                                       error
                                        _partial)
   "Send MESSAGE, a JSON object, to CONNECTION."
   (when method
-    (plist-put args :method
-               (cond ((keywordp method) (substring (symbol-name method) 1))
-                     ((and method (symbolp method)) (symbol-name method)))))
-  (let* ( (message `(:jsonrpc "2.0" ,@args))
-          (json (jsonrpc--json-encode message))
-          (headers
-           `(("Content-Length" . ,(format "%d" (string-bytes json)))
-             ;; ("Content-Type" . "application/vscode-jsonrpc; charset=utf-8")
-             )))
+    ;; sanitize method into a string
+    (setq args
+          (plist-put args :method
+                     (cond ((keywordp method) (substring (symbol-name method) 
1))
+                           ((symbolp method) (symbol-name method))
+                           ((stringp method) method)
+                           (t (error "[jsonrpc] invalid method %s" method))))))
+  (let* ((kind (cond ((or result-supplied-p error) 'reply)
+                     (id 'request)
+                     (method 'notification)))
+         (converted (jsonrpc-convert-to-endpoint connection args kind))
+         (json (jsonrpc--json-encode converted))
+         (headers
+          `(("Content-Length" . ,(format "%d" (string-bytes json)))
+            ;; ("Content-Type" . "application/vscode-jsonrpc; charset=utf-8")
+            )))
     (process-send-string
      (jsonrpc--process connection)
      (cl-loop for (header . value) in headers
               concat (concat header ": " value "\r\n") into header-section
               finally return (format "%s\r\n%s" header-section json)))
-    (jsonrpc--log-event connection message 'client)))
+    (jsonrpc--event
+     connection
+     'client
+     :json json
+     :kind  kind
+     :message args
+     :foreign-message converted)))
 
 (defun jsonrpc-process-type (conn)
   "Return the `process-type' of JSONRPC connection CONN."
@@ -523,42 +645,48 @@ With optional CLEANUP, kill any associated buffers."
   "Encode OBJECT into a JSON string.")
 
 (cl-defun jsonrpc--reply
-    (connection id &key (result nil result-supplied-p) (error nil 
error-supplied-p))
+    (connection id method &key (result nil result-supplied-p) (error nil 
error-supplied-p))
   "Reply to CONNECTION's request ID with RESULT or ERROR."
   (apply #'jsonrpc-connection-send connection
          `(:id ,id
                ,@(and result-supplied-p `(:result ,result))
-               ,@(and error-supplied-p `(:error ,error)))))
+               ,@(and error-supplied-p `(:error ,error))
+               :method ,method)))
 
 (defun jsonrpc--call-deferred (connection)
   "Call CONNECTION's deferred actions, who may again defer themselves."
   (when-let ((actions (hash-table-values (jsonrpc--deferred-actions 
connection))))
-    (jsonrpc--debug connection `(:maybe-run-deferred
-                                 ,(mapcar (apply-partially #'nth 2) actions)))
+    (jsonrpc--event
+     connection 'internal
+     :log-text (format "re-attempting deferred requests %s"
+                       (mapcar (apply-partially #'nth 2) actions)))
     (mapc #'funcall (mapcar #'car actions))))
 
 (defun jsonrpc--process-sentinel (proc change)
   "Called when PROC undergoes CHANGE."
   (let ((connection (process-get proc 'jsonrpc-connection)))
-    (jsonrpc--debug connection `(:message "Connection state changed" :change 
,change))
+    (jsonrpc--debug connection "Connection state change: `%s'" change)
     (when (not (process-live-p proc))
       (with-current-buffer (jsonrpc-events-buffer connection)
         (let ((inhibit-read-only t))
           (insert "\n----------b---y---e---b---y---e----------\n")))
       ;; Cancel outstanding timers
-      (maphash (lambda (_id triplet)
-                 (pcase-let ((`(,_success ,_error ,timeout) triplet))
-                   (when timeout (cancel-timer timeout))))
-               (jsonrpc--request-continuations connection))
+      (mapc (jsonrpc-lambda (_id _method _success-fn _error-fn timer)
+              (when timer (cancel-timer timer)))
+            (jsonrpc--continuations connection))
+      (maphash (lambda (_ triplet)
+                 (pcase-let ((`(,_ ,timer ,_) triplet))
+                   (when timer (cancel-timer timer))))
+               (jsonrpc--deferred-actions connection))
       (process-put proc 'jsonrpc-sentinel-cleanup-started t)
       (unwind-protect
           ;; Call all outstanding error handlers
-          (maphash (lambda (_id triplet)
-                     (pcase-let ((`(,_success ,error ,_timeout) triplet))
-                       (funcall error '(:code -1 :message "Server died"))))
-                   (jsonrpc--request-continuations connection))
+          (mapc (jsonrpc-lambda (_id _method _success-fn error-fn _timer)
+                  (funcall error-fn '(:code -1 :message "Server died")))
+                (jsonrpc--continuations connection))
         (jsonrpc--message "Server exited with status %s" (process-exit-status 
proc))
         (delete-process proc)
+        (when-let (p (slot-value connection '-autoport-inferior)) 
(delete-process p))
         (funcall (jsonrpc--on-shutdown connection) connection)))))
 
 (defvar jsonrpc--in-process-filter nil
@@ -568,7 +696,7 @@ With optional CLEANUP, kill any associated buffers."
   "Called when new data STRING has arrived for PROC."
   (when jsonrpc--in-process-filter
     ;; Problematic recursive process filters may happen if
-    ;; `jsonrpc--connection-receive', called by us, eventually calls
+    ;; `jsonrpc-connection-receive', called by us, eventually calls
     ;; client code which calls `process-send-string' (which see) to,
     ;; say send a follow-up message.  If that happens to writes enough
     ;; bytes for pending output to be received, we will lose JSONRPC
@@ -579,9 +707,8 @@ With optional CLEANUP, kill any associated buffers."
     (cl-return-from jsonrpc--process-filter))
   (when (buffer-live-p (process-buffer proc))
     (with-current-buffer (process-buffer proc)
-      (let* ((jsonrpc--in-process-filter t)
-             (connection (process-get proc 'jsonrpc-connection))
-             (expected-bytes (jsonrpc--expected-bytes connection)))
+      (let* ((conn (process-get proc 'jsonrpc-connection))
+             (expected-bytes (jsonrpc--expected-bytes conn)))
         ;; Insert the text, advancing the process marker.
         ;;
         (save-excursion
@@ -616,24 +743,27 @@ With optional CLEANUP, kill any associated buffers."
                           expected-bytes)
                       (let* ((message-end (byte-to-position
                                            (+ (position-bytes (point))
-                                              expected-bytes))))
+                                              expected-bytes)))
+                             message
+                             )
                         (unwind-protect
                             (save-restriction
                               (narrow-to-region (point) message-end)
-                              (let* ((json-message
-                                      (condition-case-unless-debug oops
-                                          (jsonrpc--json-read)
-                                        (error
-                                         (jsonrpc--warn "Invalid JSON: %s %s"
-                                                        (cdr oops) 
(buffer-string))
-                                         nil))))
-                                (when json-message
-                                  ;; Process content in another
-                                  ;; buffer, shielding proc buffer from
-                                  ;; tamper
-                                  (with-temp-buffer
-                                    (jsonrpc-connection-receive connection
-                                                                
json-message)))))
+                              (setq message
+                                    (condition-case-unless-debug oops
+                                        (jsonrpc--json-read)
+                                      (error
+                                       (jsonrpc--warn "Invalid JSON: %s %s"
+                                                      (cdr oops) 
(buffer-string))
+                                       nil)))
+                              (when message
+                                (setq message
+                                      (plist-put message :jsonrpc-json
+                                                 (buffer-string)))
+                                (process-put proc 'jsonrpc-mqueue
+                                             (nconc (process-get proc
+                                                                 
'jsonrpc-mqueue)
+                                                    (list message)))))
                           (goto-char message-end)
                           (let ((inhibit-read-only t))
                             (delete-region (point-min) (point)))
@@ -642,9 +772,73 @@ With optional CLEANUP, kill any associated buffers."
                       ;; Message is still incomplete
                       ;;
                       (setq done 
:waiting-for-more-bytes-in-this-message))))))))
-          ;; Saved parsing state for next visit to this filter
+          ;; Saved parsing state for next visit to this filter, which
+          ;; may well be a recursive one stemming from the tail call
+          ;; to `jsonrpc-connection-receive' below (bug#60088).
           ;;
-          (setf (jsonrpc--expected-bytes connection) expected-bytes))))))
+          (setf (jsonrpc--expected-bytes conn) expected-bytes)
+          ;; Now, time to notify user code of one or more messages in
+          ;; order.  Very often `jsonrpc-connection-receive' will exit
+          ;; non-locally (typically the reply to a request), so do
+          ;; this all this processing in top-level loops timer.
+          (cl-loop
+           for msg = (pop (process-get proc 'jsonrpc-mqueue)) while msg
+           do (run-at-time 0 nil
+                           (lambda (m) (with-temp-buffer
+                                         (jsonrpc-connection-receive conn m)))
+                           msg)))))))
+
+(defun jsonrpc--remove (conn id &optional deferred-spec)
+  "Cancel CONN's continuations for ID, including its timer, if it exists.
+Also cancel \"deferred actions\" if DEFERRED-SPEC.
+Return the full continuation (ID SUCCESS-FN ERROR-FN TIMER)"
+  (with-slots ((conts -continuations) (defs -deferred-actions)) conn
+    (if deferred-spec (remhash deferred-spec defs))
+    (when-let ((ass (assq id conts)))
+      (cl-destructuring-bind (_ _ _ _ timer) ass
+        (when timer (cancel-timer timer)))
+      (setf conts (delete ass conts))
+      ass)))
+
+(defun jsonrpc--schedule (conn id method success-fn error-fn timer)
+  (push (list id method success-fn error-fn timer)
+        (jsonrpc--continuations conn)))
+
+(defun jsonrpc--continue (conn id &optional cont result error)
+  (pcase-let* ((`(,cont-id ,_method ,success-fn ,error-fn ,_timer)
+                cont)
+               (head (pop (jsonrpc--sync-request-alist conn)))
+               (anxious (cdr head)))
+    (cond
+     (anxious
+      (when (not (= (car head) id)) ; sanity check
+        (error "internal error: please report this bug"))
+      ;; If there are "anxious" `jsonrpc-request' continuations
+      ;; that should already have been run, they should run now.
+      ;; The main continuation -- if it exists -- should run
+      ;; before them.  This order is important to preserve the
+      ;; throw to the catch tags in `jsonrpc-request' in
+      ;; order (bug#67945).
+      (cl-flet ((later (f arg) (run-at-time 0 nil f arg)))
+        (when cont-id
+          (if error (later error-fn error)
+            (later success-fn result)))
+        (cl-loop
+         for (acont ares aerr) in anxious
+         for (anx-id _method success-fn error-fn) = acont
+         do (jsonrpc--event
+             conn 'internal
+             :log-text (format "anxious continuation to %s running now" 
anx-id))
+         if aerr do (later error-fn aerr)
+         else do (later success-fn ares))))
+     (cont-id
+      ;; Else, just run the normal one, with plain funcall.
+      (if error (funcall error-fn error)
+        (funcall success-fn result)))
+     (t
+      ;; For clarity.  This happens if the `jsonrpc-request' was
+      ;; canceled
+      ))))
 
 (cl-defun jsonrpc--async-request-1 (connection
                                     method
@@ -652,8 +846,9 @@ With optional CLEANUP, kill any associated buffers."
                                     &rest args
                                     &key success-fn error-fn timeout-fn
                                     (timeout jsonrpc-default-request-timeout)
-                                    (deferred nil))
-  "Does actual work for `jsonrpc-async-request'.
+                                    (deferred nil)
+                                    (sync-request nil))
+  "Helper for `jsonrpc-request' and `jsonrpc-async-request'.
 
 Return a list (ID TIMER).  ID is the new request's ID, or nil if
 the request was deferred.  TIMER is a timer object set (or nil, if
@@ -663,60 +858,69 @@ TIMEOUT is nil)."
                 (and deferred (gethash (list deferred buf)
                                        (jsonrpc--deferred-actions 
connection))))
                (id (or old-id (cl-incf (jsonrpc--next-request-id connection))))
-               (make-timer
-                (lambda ( )
+               (maybe-timer
+                (lambda ()
                   (when timeout
-                    (run-with-timer
-                     timeout nil
-                     (lambda ()
-                       (remhash id (jsonrpc--request-continuations connection))
-                       (remhash (list deferred buf)
-                                (jsonrpc--deferred-actions connection))
-                       (if timeout-fn (funcall timeout-fn)
-                         (jsonrpc--debug
-                          connection `(:timed-out ,method :id ,id
-                                                  :params ,params)))))))))
+                    (or timer
+                        (setq
+                         timer
+                         (run-with-timer
+                          timeout nil
+                          (lambda ()
+                            (jsonrpc--remove connection id (list deferred buf))
+                            (jsonrpc--event
+                             connection 'internal
+                             :log-text (format "timed-out request '%s'" method)
+                             :id id)
+                            (when timeout-fn (funcall timeout-fn))))))))))
     (when deferred
       (if (jsonrpc-connection-ready-p connection deferred)
           ;; Server is ready, we jump below and send it immediately.
           (remhash (list deferred buf) (jsonrpc--deferred-actions connection))
         ;; Otherwise, save in `jsonrpc--deferred-actions' and exit non-locally
         (unless old-id
-          (jsonrpc--debug connection `(:deferring ,method :id ,id :params
-                                                  ,params)))
+          (jsonrpc--event
+           connection 'internal
+           :log-text (format "deferring request '%s'" method)
+           :id id))
         (puthash (list deferred buf)
                  (list (lambda ()
                          (when (buffer-live-p buf)
                            (with-current-buffer buf
                              (save-excursion (goto-char point)
-                                             (apply #'jsonrpc-async-request
+                                             (apply #'jsonrpc--async-request-1
                                                     connection
                                                     method params args)))))
-                       (or timer (setq timer (funcall make-timer))) id)
+                       (funcall maybe-timer) id)
                  (jsonrpc--deferred-actions connection))
         (cl-return-from jsonrpc--async-request-1 (list id timer))))
-    ;; Really send it
+    ;; Really send it thru the wire
     ;;
     (jsonrpc-connection-send connection
                              :id id
                              :method method
                              :params params)
-    (puthash id
-             (list (or success-fn
-                       (lambda (&rest _ignored)
-                         (jsonrpc--debug
-                          connection (list :message "success ignored"
-                                           :id id))))
-                   (or error-fn
-                       (jsonrpc-lambda (&key code message &allow-other-keys)
-                         (jsonrpc--debug
-                          connection (list
-                                      :message
-                                      (format "error ignored, status set (%s)"
-                                              message)
-                                      :id id :error code))))
-                   (setq timer (funcall make-timer)))
-             (jsonrpc--request-continuations connection))
+    ;; Setup some control structures
+    ;;
+    (when sync-request
+      (push (list id) (jsonrpc--sync-request-alist connection)))
+
+    (jsonrpc--schedule
+     connection id method
+     (or success-fn
+         (lambda (&rest _ignored)
+           (jsonrpc--event
+            connection 'internal
+            :log-text (format "success ignored")
+            :id id)))
+     (or error-fn
+         (jsonrpc-lambda (&key code message &allow-other-keys)
+           (jsonrpc--event
+            connection 'internal
+            :log-text (format "error %s ignored: %s ignored"
+                              code message)
+            :id id)))
+     (funcall maybe-timer))
     (list id timer)))
 
 (defun jsonrpc--message (format &rest args)
@@ -725,10 +929,11 @@ TIMEOUT is nil)."
 
 (defun jsonrpc--debug (server format &rest args)
   "Debug message for SERVER with FORMAT and ARGS."
-  (jsonrpc--log-event
-   server (if (stringp format)
-              `(:message ,(apply #'format format args))
-            format)))
+  (with-current-buffer (jsonrpc-events-buffer server)
+    (jsonrpc--log-event
+     server 'internal
+     :log-text (apply #'format format args)
+     :type 'debug)))
 
 (defun jsonrpc--warn (format &rest args)
   "Warning message with FORMAT and ARGS."
@@ -738,44 +943,216 @@ TIMEOUT is nil)."
                      (apply #'format format args)
                      :warning)))
 
-(defun jsonrpc--log-event (connection message &optional type)
-  "Log a JSONRPC-related event.
-CONNECTION is the current connection.  MESSAGE is a JSON-like
-plist.  TYPE is a symbol saying if this is a client or server
-originated."
-  (let ((max (jsonrpc--events-buffer-scrollback-size connection)))
+(cl-defun jsonrpc--event (connection
+                          origin
+                          &rest plist
+                          &key _kind _json _message _foreign-message _log-text
+                          &allow-other-keys)
+  (with-current-buffer (jsonrpc-events-buffer connection)
+    (run-hook-wrapped 'jsonrpc-event-hook
+                      (lambda (fn)
+                        (condition-case oops
+                            (apply fn connection origin plist)
+                          (error
+                           (jsonrpc--message "event hook '%s' errored (%s).  
Removing it"
+                                             fn oops)
+                           (remove-hook 'jsonrpc-event-hook fn)))))))
+
+(defvar jsonrpc-event-hook (list #'jsonrpc--log-event)
+  "Hook run when JSON-RPC events are emitted.
+This hooks runs in the events buffer of every  `jsonrpc-connection'
+when an event is originated by either endpoint.  Each hook function
+is passed the arguments described by the lambda list:
+
+  (CONNECTION ORIGIN &key JSON KIND MESSAGE FOREIGN-MESSAGE LOG-TEXT
+                     &allow-other-keys)
+
+  CONNECTION       the `jsonrpc-connection' instance.
+  ORIGIN           one of the symbols `client' ,`server'.
+  JSON             the raw JSON string content.
+  KIND             one of the symbols `request' ,`notification',
+                   `reply'.
+  MESSAGE          a plist representing the exchanged message in
+                   jsonrpc.el's internal format
+  FOREIGN-MESSAGE  a plist representing the exchanged message in
+                   the remote endpoint's format.
+  LOG-TEXT         text used for events of `internal' origin.
+  ID               id of a message that this event refers to.
+  TYPE             `error', `debug' or the default `info'.
+
+Except for CONNECTION and ORIGIN all other keys are optional.
+Unlisted keys may appear in the plist.
+
+Do not use this hook to write JSON-RPC protocols, use other parts
+of the API instead.")
+
+(cl-defun jsonrpc--log-event (connection origin
+                                         &key _kind message
+                                         foreign-message log-text json
+                                         type ((:id ref-id))
+                                         &allow-other-keys)
+  "Log a JSONRPC-related event.  Installed in `jsonrpc-event-hook'."
+  (let* ((props (slot-value connection '-events-buffer-config))
+         (max (plist-get props :size))
+         (format (plist-get props :format)))
     (when (or (null max) (cl-plusp max))
-      (with-current-buffer (jsonrpc-events-buffer connection)
-        (cl-destructuring-bind (&key method id error &allow-other-keys) message
-          (let* ((inhibit-read-only t)
-                 (subtype (cond ((and method id)       'request)
-                                (method                'notification)
-                                (id                    'reply)
-                                (t                     'message)))
-                 (type
-                  (concat (format "%s" (or type 'internal))
-                          (if type
-                              (format "-%s" subtype)))))
-            (goto-char (point-max))
-            (prog1
-                (let ((msg (format "[%s]%s%s %s:\n%s"
-                                   type
-                                   (if id (format " (id:%s)" id) "")
-                                   (if error " ERROR" "")
-                                   (current-time-string)
-                                   (pp-to-string message))))
-                  (when error
-                    (setq msg (propertize msg 'face 'error)))
-                  (insert-before-markers msg))
-              ;; Trim the buffer if it's too large
-              (when max
-                (save-excursion
-                  (goto-char (point-min))
-                  (while (> (buffer-size) max)
-                    (delete-region (point) (progn (forward-line 1)
-                                                  (forward-sexp 1)
-                                                  (forward-line 2)
-                                                  (point)))))))))))))
+      (cl-destructuring-bind (&key method id error &allow-other-keys) message
+        (let* ((inhibit-read-only t)
+               (depth (length
+                       (jsonrpc--sync-request-alist connection)))
+               (preamble (format "[jsonrpc] %s[%s]%s "
+                                 (pcase type ('error "E") ('debug "D")
+                                        (_ (pcase origin
+                                             ('internal "i")
+                                             (_ "e"))))
+                                 (format-time-string "%H:%M:%S.%3N")
+                                 (if (eq origin 'internal)
+                                     (if ref-id (format " [%s]" ref-id) "")
+                                   (format " %s%s %s%s"
+                                           (make-string (* 2 depth) ? )
+                                           (pcase origin
+                                             ('client "-->")
+                                             ('server "<--")
+                                             (_ ""))
+                                           (or method "")
+                                           (if id (format "[%s]" id) "")))))
+               (msg
+                (pcase format
+                  ('full  (format "%s%s\n" preamble (or json log-text)))
+                  ('short (format "%s%s\n" preamble (or log-text "")))
+                  (_
+                   (format "%s%s" preamble
+                           (or (and foreign-message
+                                    (let ((lisp-indent-function ;bug#68072
+                                           #'lisp-indent-function))
+                                      (concat "\n" (pp-to-string
+                                                    foreign-message))))
+                               (concat log-text "\n")))))))
+          (goto-char (point-max))
+          ;; XXX: could use `run-at-time' to delay server logs
+          ;; slightly to play nice with verbose servers' stderr.
+          (when error
+            (setq msg (propertize msg 'face 'error)))
+          (insert-before-markers msg)
+          ;; Trim the buffer if it's too large
+          (when max
+            (save-excursion
+              (goto-char (point-min))
+              (while (> (buffer-size) max)
+                (delete-region (point) (progn (forward-line 1)
+                                              (forward-sexp 1)
+                                              (forward-line 2)
+                                              (point)))))))))))
+
+(defun jsonrpc--forwarding-buffer (name prefix conn)
+  "Helper for `jsonrpc-process-connection' helpers.
+Make a stderr buffer named NAME, forwarding lines prefixed by
+PREFIX to CONN's events buffer."
+  (with-current-buffer (get-buffer-create name)
+    (let ((inhibit-read-only t))
+      (fundamental-mode)
+      (erase-buffer)
+      (buffer-disable-undo)
+      (add-hook
+       'after-change-functions
+       (lambda (beg _end _pre-change-len)
+         (cl-loop initially (goto-char beg)
+                  do (forward-line)
+                  when (bolp)
+                  for line = (buffer-substring
+                              (line-beginning-position 0)
+                              (line-end-position 0))
+                  do (with-current-buffer (jsonrpc-events-buffer conn)
+                       (goto-char (point-max))
+                       (let ((inhibit-read-only t))
+                         (insert
+                          (propertize (format "%s %s\n" prefix line)
+                                      'face 'shadow))))
+                  until (eobp)))
+       nil t))
+    (current-buffer)))
+
+
+;;;; More convenience utils
+(cl-defun jsonrpc-autoport-bootstrap (name contact
+                                           &key connect-args)
+  "Use CONTACT to start network server, then connect to it.
+
+Return function suitable for the :PROCESS initarg of
+`jsonrpc-process-connection' (which see).
+
+CONTACT is a list where all the elements are strings except for
+one, which is usuallky the keyword `:autoport'.
+
+When the returned function is called it will start a program
+using a command based on CONTACT, where `:autoport' is
+substituted by a locally free network port.  Thereafter, a
+network is made to this port.
+
+Instead of the keyword `:autoport', a cons cell (:autoport
+FORMAT-FN) is also accepted.  In that case FORMAT-FN is passed
+the port number and should return a string used for the
+substitution.
+
+The internal processes and control buffers are named after NAME.
+
+CONNECT-ARGS are passed as additional arguments to
+`open-network-stream'."
+  (lambda (conn)
+    (let* ((port-probe (make-network-process :name "jsonrpc-port-probe-dummy"
+                                             :server t
+                                             :host "localhost"
+                                             :service 0))
+           (port-number (unwind-protect
+                            (process-contact port-probe :service)
+                          (delete-process port-probe)))
+           (inferior-buffer (jsonrpc--forwarding-buffer
+                             (format " *%s inferior output*" name)
+                             "[inferior]"
+                             conn))
+           (cmd (cl-loop for e in contact
+                         if (eq e :autoport) collect (format "%s" port-number)
+                         else if (eq (car-safe e) :autoport)
+                         collect (funcall (cdr e) port-number)
+                         else collect e))
+           inferior np)
+      (unwind-protect
+          (progn
+            (message "[jsonrpc] Attempting to start `%s'"
+                     (string-join cmd " "))
+            (setq inferior
+                  (make-process
+                   :name (format "inferior (%s)" name)
+                   :buffer inferior-buffer
+                   :noquery t
+                   :command cmd))
+            (setq np
+                  (cl-loop
+                   repeat 10 for i from 0
+                   do (accept-process-output nil 0.5)
+                   while (process-live-p inferior)
+                   do (message
+                       "[jsonrpc] %sTrying to connect to localhost:%s (attempt 
%s)"
+                       (if (zerop i) "Started.  " "")
+                       port-number (1+ i))
+                   thereis (ignore-errors
+                             (apply #'open-network-stream
+                                    (format "autostart (%s)" name)
+                                    nil
+                                    "localhost" port-number connect-args))))
+            (setf (slot-value conn '-autoport-inferior) inferior)
+            np)
+        (cond ((and (process-live-p np)
+                    (process-live-p inferior))
+               (message "[jsonrpc] Done, connected to %s!" port-number))
+              (t
+               (when inferior (delete-process inferior))
+               (when np (delete-process np))
+               (error "[jsonrpc] Could not start and/or connect")))))))
+
+(defun jsonrpc-continuation-count (conn)
+  "Number of outstanding continuations for CONN."
+  (length (jsonrpc--continuations conn)))
 
 (provide 'jsonrpc)
 ;;; jsonrpc.el ends here
diff --git a/lisp/kermit.el b/lisp/kermit.el
index 7ee75141f6c..f632e784204 100644
--- a/lisp/kermit.el
+++ b/lisp/kermit.el
@@ -1,6 +1,6 @@
 ;;; kermit.el --- additions to shell mode for use with kermit -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1988, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Jeff Norden <jeff@colgate.csnet>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/keymap.el b/lisp/keymap.el
index 7e659c42002..d2544e30ce0 100644
--- a/lisp/keymap.el
+++ b/lisp/keymap.el
@@ -1,6 +1,6 @@
 ;;; keymap.el --- Keymap functions  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
@@ -577,9 +577,15 @@ should be a MENU form as accepted by `easy-menu-define'.
           (let ((def (pop definitions)))
             (if (eq key :menu)
                 (easy-menu-define nil keymap "" def)
-              (if (member key seen-keys)
-                  (error "Duplicate definition for key: %S %s" key keymap)
-                (push key seen-keys))
+              (when (member key seen-keys)
+                ;; Since the keys can be computed dynamically, it can
+                ;; very well happen that we get duplicate definitions
+                ;; due to some unfortunate configuration rather than
+                ;; due to an actual bug.  While such duplicates are
+                ;; not desirable, they shouldn't prevent the users
+                ;; from getting their job done.
+                (message "Duplicate definition for key: %S %s" key keymap))
+              (push key seen-keys)
               (keymap-set keymap key def)))))
       keymap)))
 
diff --git a/lisp/kmacro.el b/lisp/kmacro.el
index 588b2d14943..897ebf14330 100644
--- a/lisp/kmacro.el
+++ b/lisp/kmacro.el
@@ -1,6 +1,6 @@
 ;;; kmacro.el --- enhanced keyboard macros -*- lexical-binding: t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Kim F. Storm <storm@cua.dk>
 ;; Keywords: keyboard convenience
diff --git a/lisp/language/china-util.el b/lisp/language/china-util.el
index 97301576ab8..f9533d7d480 100644
--- a/lisp/language/china-util.el
+++ b/lisp/language/china-util.el
@@ -1,6 +1,6 @@
 ;;; china-util.el --- utilities for Chinese  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/chinese.el b/lisp/language/chinese.el
index e35f3f179ad..97a8257db7e 100644
--- a/lisp/language/chinese.el
+++ b/lisp/language/chinese.el
@@ -1,6 +1,6 @@
 ;;; chinese.el --- support for Chinese -*- coding: utf-8; lexical-binding: t; 
-*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/cyril-util.el b/lisp/language/cyril-util.el
index 0095338af45..ba3df9af02f 100644
--- a/lisp/language/cyril-util.el
+++ b/lisp/language/cyril-util.el
@@ -1,6 +1,6 @@
 ;;; cyril-util.el --- utilities for Cyrillic scripts  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Keywords: mule, multilingual, Cyrillic
 
diff --git a/lisp/language/cyrillic.el b/lisp/language/cyrillic.el
index 2b32304c829..87a67915878 100644
--- a/lisp/language/cyrillic.el
+++ b/lisp/language/cyrillic.el
@@ -1,6 +1,6 @@
 ;;; cyrillic.el --- support for Cyrillic -*- coding: utf-8; lexical-binding: 
t; -*-
 
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/czech.el b/lisp/language/czech.el
index e3fe42026a5..838d024851e 100644
--- a/lisp/language/czech.el
+++ b/lisp/language/czech.el
@@ -1,6 +1,6 @@
 ;;; czech.el --- support for Czech -*- coding: utf-8; lexical-binding: t -*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Milan Zamazal <pdm@zamazal.org>
 ;; Maintainer: Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/language/english.el b/lisp/language/english.el
index b8334d90863..e223c4aa0cb 100644
--- a/lisp/language/english.el
+++ b/lisp/language/english.el
@@ -1,6 +1,6 @@
 ;;; english.el --- support for English  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/ethio-util.el b/lisp/language/ethio-util.el
index fe61a4e8560..50701f830ed 100644
--- a/lisp/language/ethio-util.el
+++ b/lisp/language/ethio-util.el
@@ -1,6 +1,6 @@
 ;;; ethio-util.el --- utilities for Ethiopic   -*- coding: utf-8-emacs; 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-1998, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2002-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/ethiopic.el b/lisp/language/ethiopic.el
index 475d569d56d..7490f5351c8 100644
--- a/lisp/language/ethiopic.el
+++ b/lisp/language/ethiopic.el
@@ -1,6 +1,6 @@
 ;;; ethiopic.el --- support for Ethiopic       -*- coding: utf-8-emacs; 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/european.el b/lisp/language/european.el
index d65acb95979..ced070410b4 100644
--- a/lisp/language/european.el
+++ b/lisp/language/european.el
@@ -1,6 +1,6 @@
 ;;; european.el --- support for European languages -*- coding: utf-8; 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/georgian.el b/lisp/language/georgian.el
index 32d9425c09a..1308b0a8efc 100644
--- a/lisp/language/georgian.el
+++ b/lisp/language/georgian.el
@@ -1,6 +1,6 @@
 ;;; georgian.el --- language support for Georgian  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: i18n
diff --git a/lisp/language/greek.el b/lisp/language/greek.el
index 0c3e5e0633f..849c45e5af8 100644
--- a/lisp/language/greek.el
+++ b/lisp/language/greek.el
@@ -1,6 +1,6 @@
 ;;; greek.el --- support for Greek  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2002, 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2013-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/hanja-util.el b/lisp/language/hanja-util.el
index b5ef9230d27..c47ceb5fc88 100644
--- a/lisp/language/hanja-util.el
+++ b/lisp/language/hanja-util.el
@@ -1,6 +1,6 @@
 ;;; hanja-util.el --- Korean Hanja util module  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Jihyun Cho <jihyun.jo@gmail.com>
 ;; Keywords: multilingual, input method, Korean, Hanja
@@ -6437,7 +6437,7 @@ character.  This variable is initialized by 
`hanja-init-load'.")
     (message "")))
 
 ;; List of current conversion status.
-;; The first element is the strating position of shown list.
+;; The first element is the starting position of shown list.
 ;; It is a group number each split by `hanja-list-width'.
 ;; The second element is the position of selected element.
 ;; The third element is a list of suitable Hanja candidate.
diff --git a/lisp/language/hebrew.el b/lisp/language/hebrew.el
index 2c0398888b2..d824901a1cb 100644
--- a/lisp/language/hebrew.el
+++ b/lisp/language/hebrew.el
@@ -1,6 +1,6 @@
 ;;; hebrew.el --- support for Hebrew -*- coding: utf-8; lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/ind-util.el b/lisp/language/ind-util.el
index 71117deef56..b4bdf8f430b 100644
--- a/lisp/language/ind-util.el
+++ b/lisp/language/ind-util.el
@@ -1,6 +1,6 @@
 ;;; ind-util.el --- Transliteration and Misc. Tools for Indian Languages -*- 
coding: utf-8-emacs; lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Keywords: multilingual, Indian, Devanagari
 
diff --git a/lisp/language/indian.el b/lisp/language/indian.el
index d5964823501..9b3e0e0584f 100644
--- a/lisp/language/indian.el
+++ b/lisp/language/indian.el
@@ -1,6 +1,6 @@
 ;;; indian.el --- Indian languages support -*- coding: utf-8; lexical-binding: 
t; -*-
 
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
 ;;   Registration Number H14PRO021
diff --git a/lisp/language/indonesian.el b/lisp/language/indonesian.el
index e0990c8320a..b8a18930f5c 100644
--- a/lisp/language/indonesian.el
+++ b/lisp/language/indonesian.el
@@ -1,6 +1,6 @@
 ;;; indonesian.el --- Indonesian languages support  -*- coding: utf-8; 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
 ;; Keywords: multilingual, input method, i18n, Indonesia
diff --git a/lisp/language/japan-util.el b/lisp/language/japan-util.el
index d60b163ae94..93e8ab24971 100644
--- a/lisp/language/japan-util.el
+++ b/lisp/language/japan-util.el
@@ -1,6 +1,6 @@
 ;;; japan-util.el --- utilities for Japanese  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/japanese.el b/lisp/language/japanese.el
index 6042ebf4511..dd65409c839 100644
--- a/lisp/language/japanese.el
+++ b/lisp/language/japanese.el
@@ -1,6 +1,6 @@
 ;;; japanese.el --- support for Japanese  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/korea-util.el b/lisp/language/korea-util.el
index 764a58bd7d2..665745c1eb0 100644
--- a/lisp/language/korea-util.el
+++ b/lisp/language/korea-util.el
@@ -1,6 +1,6 @@
 ;;; korea-util.el --- utilities for Korean  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
 ;;   2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/korean.el b/lisp/language/korean.el
index ede37d5d07c..9b04de3c6ca 100644
--- a/lisp/language/korean.el
+++ b/lisp/language/korean.el
@@ -1,6 +1,6 @@
 ;;; korean.el --- support for Korean -*- coding: utf-8; lexical-binding: t; -*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/lao-util.el b/lisp/language/lao-util.el
index 33e98a60d63..8bb767ba78f 100644
--- a/lisp/language/lao-util.el
+++ b/lisp/language/lao-util.el
@@ -1,6 +1,6 @@
 ;;; lao-util.el --- utilities for Lao -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
 ;;   2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/lao.el b/lisp/language/lao.el
index 875d5b49d52..2992e00b35b 100644
--- a/lisp/language/lao.el
+++ b/lisp/language/lao.el
@@ -1,6 +1,6 @@
 ;;; lao.el --- support for Lao -*- coding: utf-8; lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
 ;;   2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/misc-lang.el b/lisp/language/misc-lang.el
index 792155f1de5..1de424252e8 100644
--- a/lisp/language/misc-lang.el
+++ b/lisp/language/misc-lang.el
@@ -1,6 +1,6 @@
 ;;; misc-lang.el --- support for miscellaneous languages (characters)  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/philippine.el b/lisp/language/philippine.el
index e4a79b02a44..68e0e599fac 100644
--- a/lisp/language/philippine.el
+++ b/lisp/language/philippine.el
@@ -1,6 +1,6 @@
 ;;; philippine.el --- Philippine languages support  -*- coding: utf-8; 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
 ;; Keywords: multilingual, input method, i18n, Philippines
diff --git a/lisp/language/romanian.el b/lisp/language/romanian.el
index a18b7d0cda2..a76f162f445 100644
--- a/lisp/language/romanian.el
+++ b/lisp/language/romanian.el
@@ -1,6 +1,6 @@
 ;;; romanian.el --- support for Romanian -*- coding: utf-8; lexical-binding: t 
-*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dan Nicolaescu <done@ece.arizona.edu>
 ;; Keywords: multilingual, Romanian, i18n
diff --git a/lisp/language/sinhala.el b/lisp/language/sinhala.el
index bf320506001..a5c379b3aae 100644
--- a/lisp/language/sinhala.el
+++ b/lisp/language/sinhala.el
@@ -36,11 +36,11 @@
  composition-function-table
  '(#xD80 . #xDFF)
  (list (vector
-       ;; C:consonant, H:HALANT, J:ZWJ, v:vowel sign,
+       ;; C:consonant, H:HALANTA, J:ZWJ, v:vowel sign,
        ;; V:independent vowel, a:ANUSVARA .. VISARGA
        (concat
-        ;; C(HJC)*v*H?a?, or
-        
"[\u0D9A-\u0DC6]\\(?:\u0DCA\u200D[\u0D9A-\u0DC6]\\)*[\u0DCF-\u0DDF\u0DF2-\u0DF3]*\u0DCA?[\u0D82-\u0D83]?\\|"
+        ;; C(HJ|JH)C)*v*H?a?, or
+        
"[\u0D9A-\u0DC6]\\(?:\\(\u0DCA\u200D\\|\u200D\u0DCA\\)[\u0D9A-\u0DC6]\\)*[\u0DCF-\u0DDF\u0DF2-\u0DF3]*\u0DCA?[\u0D82-\u0D83]?\\|"
         ;; Va?, or
         "[\u0D85-\u0D96][\u0D82-\u0D83]?\\|"
         ;; any other singleton characters
diff --git a/lisp/language/slovak.el b/lisp/language/slovak.el
index eb49e6d598a..62cd0ecfdce 100644
--- a/lisp/language/slovak.el
+++ b/lisp/language/slovak.el
@@ -1,6 +1,6 @@
 ;;; slovak.el --- support for Slovak -*- coding: utf-8; lexical-binding: t -*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Authors:    Tibor Šimko <tibor.simko@fmph.uniba.sk>,
 ;;             Milan Zamazal <pdm@zamazal.org>
diff --git a/lisp/language/tai-viet.el b/lisp/language/tai-viet.el
index 266de0600fe..e0e0d49a06a 100644
--- a/lisp/language/tai-viet.el
+++ b/lisp/language/tai-viet.el
@@ -1,6 +1,6 @@
 ;;; tai-viet.el --- support for Tai Viet -*- coding: utf-8; lexical-binding: t 
-*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
 ;;   Registration Number H13PRO009
diff --git a/lisp/language/thai-util.el b/lisp/language/thai-util.el
index e539e8e3c9d..ab18a752cad 100644
--- a/lisp/language/thai-util.el
+++ b/lisp/language/thai-util.el
@@ -1,6 +1,6 @@
 ;;; thai-util.el --- utilities for Thai -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/thai.el b/lisp/language/thai.el
index 2e05e9b5db2..2326b983a2b 100644
--- a/lisp/language/thai.el
+++ b/lisp/language/thai.el
@@ -1,6 +1,6 @@
 ;;; thai.el --- support for Thai -*- coding: utf-8; lexical-binding: t; -*-
 
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/tibet-util.el b/lisp/language/tibet-util.el
index b38d5230f93..1f1c52e3fbd 100644
--- a/lisp/language/tibet-util.el
+++ b/lisp/language/tibet-util.el
@@ -1,6 +1,6 @@
 ;;; tibet-util.el --- utilities for Tibetan   -*- coding: utf-8-emacs; 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/tibetan.el b/lisp/language/tibetan.el
index 21b3fc03417..28f8c229d3d 100644
--- a/lisp/language/tibetan.el
+++ b/lisp/language/tibetan.el
@@ -1,6 +1,6 @@
 ;;; tibetan.el --- support for Tibetan language -*- coding: utf-8-emacs; 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/utf-8-lang.el b/lisp/language/utf-8-lang.el
index 4ecf8b8f50b..1fbd5427df2 100644
--- a/lisp/language/utf-8-lang.el
+++ b/lisp/language/utf-8-lang.el
@@ -1,6 +1,6 @@
 ;;; utf-8-lang.el --- generic UTF-8 language environment  -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: i18n
diff --git a/lisp/language/viet-util.el b/lisp/language/viet-util.el
index 40b4426399f..068a97dc492 100644
--- a/lisp/language/viet-util.el
+++ b/lisp/language/viet-util.el
@@ -1,6 +1,6 @@
 ;;; viet-util.el --- utilities for Vietnamese  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/vietnamese.el b/lisp/language/vietnamese.el
index e439a2c3851..460a4d18246 100644
--- a/lisp/language/vietnamese.el
+++ b/lisp/language/vietnamese.el
@@ -1,6 +1,6 @@
 ;;; vietnamese.el --- support for Vietnamese -*- coding: utf-8; 
lexical-binding: t -*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 ;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index 83ef1f844b0..ceef383b45a 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -302,7 +302,7 @@ usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] 
FLAG...)
 (fn FUNCTION ARGS &rest BODY)" nil t)
 (function-put 'defadvice 'doc-string-elt 3)
 (function-put 'defadvice 'lisp-indent-function 2)
-(make-obsolete 'defadvice '"use advice-add or define-advice" "30.1")
+(make-obsolete 'defadvice '"use `advice-add' or `define-advice'" "30.1")
 (register-definition-prefixes "advice" '("ad-"))
 
 
@@ -1946,7 +1946,7 @@ Major mode for editing BibTeX style files.
 (register-definition-prefixes "bibtex-style" '("bibtex-style-"))
 
 
-;;; Generated autoloads from use-package/bind-key.el
+;;; Generated autoloads from bind-key.el
 
 (push (purecopy '(bind-key 2 4 1)) package--builtin-versions)
 (autoload 'bind-key "bind-key" "\
@@ -2608,7 +2608,7 @@ used instead of `browse-url-new-window-flag'.
 (fn URL &optional NEW-WINDOW)" t)
 (make-obsolete 'browse-url-w3 'nil "29.1")
 (autoload 'browse-url-w3-gnudoit "browse-url" "\
-Ask another Emacs running gnuserv to load the URL using the W3 browser.
+Ask another Emacs running emacsclient to load the URL using the W3 browser.
 The `browse-url-gnudoit-program' program is used with options given by
 `browse-url-gnudoit-args'.  Default to the URL around or before point.
 
@@ -4668,14 +4668,14 @@ Return a string containing the `cl-prin1'-printed 
representation of OBJECT.
 (autoload 'cl-print-to-string-with-limit "cl-print" "\
 Return a string containing a printed representation of VALUE.
 Attempt to get the length of the returned string under LIMIT
-characters with appropriate settings of `print-level' and
-`print-length.'  Use PRINT-FUNCTION to print, which should take
-the arguments VALUE and STREAM and which should respect
-`print-length' and `print-level'.  LIMIT may be nil or zero in
-which case PRINT-FUNCTION will be called with `print-level' and
-`print-length' bound to nil, and it can also be t in which case
-PRINT-FUNCTION will be called with the current values of `print-level'
-and `print-length'.
+characters with appropriate settings of `print-level',
+`print-length', and `cl-print-string-length'.  Use
+PRINT-FUNCTION to print, which should take the arguments VALUE
+and STREAM and which should respect `print-length',
+`print-level', and `cl-print-string-length'.  LIMIT may be nil or
+zero in which case PRINT-FUNCTION will be called with these
+settings bound to nil, and it can also be t in which case
+PRINT-FUNCTION will be called with their current values.
 
 Use this function with `cl-prin1' to print an object,
 abbreviating it with ellipses to fit within a size limit.
@@ -4857,10 +4857,6 @@ REGEXP-GROUP is the regular expression group in REGEXP 
to use.
 ;;; Generated autoloads from emacs-lisp/comp.el
 
 (put 'no-native-compile 'safe-local-variable 'booleanp)
-(autoload 'comp-subr-trampoline-install "comp" "\
-Make SUBR-NAME effectively advice-able when called from native code.
-
-(fn SUBR-NAME)")
 (autoload 'comp-c-func-name "comp" "\
 Given NAME, return a name suitable for the native code.
 Add PREFIX in front of it.  If FIRST is not nil, pick the first
@@ -4868,42 +4864,16 @@ available name ignoring compilation context and 
potential name
 clashes.
 
 (fn NAME PREFIX &optional FIRST)")
+(autoload 'comp-trampoline-compile "comp" "\
+Synthesize compile and return a trampoline for SUBR-NAME.
+
+(fn SUBR-NAME)")
 (autoload 'comp-clean-up-stale-eln "comp" "\
 Remove all FILE*.eln* files found in `native-comp-eln-load-path'.
 The files to be removed are those produced from the original source
 filename (including FILE).
 
 (fn FILE)")
-(autoload 'native--compile-async "comp" "\
-Compile FILES asynchronously.
-FILES is one filename or a list of filenames or directories.
-
-If optional argument RECURSIVELY is non-nil, recurse into
-subdirectories of given directories.
-
-If optional argument LOAD is non-nil, request to load the file
-after compiling.
-
-The optional argument SELECTOR has the following valid values:
-
-nil -- Select all files.
-a string -- A regular expression selecting files with matching names.
-a function -- A function selecting files with matching names.
-
-The variable `native-comp-async-jobs-number' specifies the number
-of (commands) to run simultaneously.
-
-LOAD can also be the symbol `late'.  This is used internally if
-the byte code has already been loaded when this function is
-called.  It means that we request the special kind of load
-necessary in that situation, called \"late\" loading.
-
-During a \"late\" load, instead of executing all top-level forms
-of the original files, only function definitions are
-loaded (paying attention to have these effective only if the
-bytecode definition was not changed in the meantime).
-
-(fn FILES &optional RECURSIVELY LOAD SELECTOR)")
 (autoload 'comp-lookup-eln "comp" "\
 Given a Lisp source FILENAME return the corresponding .eln file if found.
 Search happens in `native-comp-eln-load-path'.
@@ -4940,9 +4910,43 @@ Force the produced .eln to be outputted in the eln system
 directory (the last entry in `native-comp-eln-load-path') unless
 `native-compile-target-directory' is non-nil.  If the environment
 variable \"NATIVE_DISABLED\" is set, only byte compile.")
-(autoload 'native-compile-async "comp" "\
+(register-definition-prefixes "comp" '("comp-" "native-comp" 
"no-native-compile"))
+
+
+;;; Generated autoloads from cedet/semantic/wisent/comp.el
+
+(register-definition-prefixes "semantic/wisent/comp" '("wisent-"))
+
+
+;;; Generated autoloads from emacs-lisp/comp-common.el
+
+(autoload 'comp-function-type-spec "comp-common" "\
+Return the type specifier of FUNCTION.
+
+This function returns a cons cell whose car is the function
+specifier, and cdr is a symbol, either `inferred' or `know'.
+If the symbol is `inferred', the type specifier is automatically
+inferred from the code itself by the native compiler; if it is
+`know', the type specifier comes from `comp-known-type-specifiers'.
+
+(fn FUNCTION)")
+(register-definition-prefixes "comp-common" '("comp-" "native-comp-"))
+
+
+;;; Generated autoloads from emacs-lisp/comp-cstr.el
+
+(register-definition-prefixes "comp-cstr" '("comp-" 
"with-comp-cstr-accessors"))
+
+
+;;; Generated autoloads from emacs-lisp/comp-run.el
+
+(autoload 'comp-subr-trampoline-install "comp-run" "\
+Make SUBR-NAME effectively advice-able when called from native code.
+
+(fn SUBR-NAME)")
+(autoload 'native--compile-async "comp-run" "\
 Compile FILES asynchronously.
-FILES is one file or a list of filenames or directories.
+FILES is one filename or a list of filenames or directories.
 
 If optional argument RECURSIVELY is non-nil, recurse into
 subdirectories of given directories.
@@ -4959,28 +4963,38 @@ a function -- A function selecting files with matching 
names.
 The variable `native-comp-async-jobs-number' specifies the number
 of (commands) to run simultaneously.
 
+LOAD can also be the symbol `late'.  This is used internally if
+the byte code has already been loaded when this function is
+called.  It means that we request the special kind of load
+necessary in that situation, called \"late\" loading.
+
+During a \"late\" load, instead of executing all top-level forms
+of the original files, only function definitions are
+loaded (paying attention to have these effective only if the
+bytecode definition was not changed in the meantime).
+
 (fn FILES &optional RECURSIVELY LOAD SELECTOR)")
-(autoload 'comp-function-type-spec "comp" "\
-Return the type specifier of FUNCTION.
+(autoload 'native-compile-async "comp-run" "\
+Compile FILES asynchronously.
+FILES is one file or a list of filenames or directories.
 
-This function returns a cons cell whose car is the function
-specifier, and cdr is a symbol, either `inferred' or `know'.
-If the symbol is `inferred', the type specifier is automatically
-inferred from the code itself by the native compiler; if it is
-`know', the type specifier comes from `comp-known-type-specifiers'.
+If optional argument RECURSIVELY is non-nil, recurse into
+subdirectories of given directories.
 
-(fn FUNCTION)")
-(register-definition-prefixes "comp" '("comp-" "make-comp-edge" "native-comp" 
"no-native-compile"))
+If optional argument LOAD is non-nil, request to load the file
+after compiling.
 
-
-;;; Generated autoloads from cedet/semantic/wisent/comp.el
+The optional argument SELECTOR has the following valid values:
 
-(register-definition-prefixes "semantic/wisent/comp" '("wisent-"))
+nil -- Select all files.
+a string -- A regular expression selecting files with matching names.
+a function -- A function selecting files with matching names.
 
-
-;;; Generated autoloads from emacs-lisp/comp-cstr.el
+The variable `native-comp-async-jobs-number' specifies the number
+of (commands) to run simultaneously.
 
-(register-definition-prefixes "comp-cstr" '("comp-" 
"with-comp-cstr-accessors"))
+(fn FILES &optional RECURSIVELY LOAD SELECTOR)")
+(register-definition-prefixes "comp-run" '("comp-" "native-comp"))
 
 
 ;;; Generated autoloads from vc/compare-w.el
@@ -5239,6 +5253,24 @@ or call the function `dynamic-completion-mode'.")
 (autoload 'dynamic-completion-mode "completion" "\
 Toggle dynamic word-completion on or off.
 
+When this minor mode is turned on, typing \\`M-RET' or \\`C-RET'
+invokes the command `complete', which completes the word or
+symbol at point using the record of words/symbols you used
+previously and the previously-inserted completions.  Typing
+a word or moving point across it constitutes \"using\" the
+word.
+
+By default, the database of all the dynamic completions that
+were inserted by \\[complete] is saved on the file specified
+by `save-completions-file-name' when you exit Emacs, and will
+be loaded from that file when this mode is enabled in a future
+Emacs session.
+
+The following important options control the various aspects of
+this mode: `enable-completion', `save-completions-flag', and
+`save-completions-retention-time'.  Few other less important
+options can be found in the `completion' group.
+
 This is a global minor mode.  If called interactively, toggle the
 `Dynamic-Completion mode' mode.  If the prefix argument is
 positive, enable the mode, and if it is zero or negative, disable
@@ -5258,6 +5290,38 @@ it is disabled.
 (register-definition-prefixes "completion" '("*c-def-regexp*" 
"*lisp-def-regexp*" "accept-completion" "add-" "cdabbrev-" 
"check-completion-length" "clear-all-completions" "cmpl-" "complet" 
"current-completion-source" "delete-completion" "enable-completion" "find-" 
"inside-locate-completion-entry" "interactive-completion-string-reader" "kill-" 
"list-all-completions" "load-completions-from-file" "make-c" "next-cdabbrev" 
"num-cmpl-sources" "reset-cdabbrev" "save" "set-c" "symbol-" "use-comp [...]
 
 
+;;; Generated autoloads from completion-preview.el
+
+(autoload 'completion-preview-mode "completion-preview" "\
+Show in-buffer completion suggestions in a preview as you type.
+
+This mode automatically shows and updates the completion preview
+according to the text around point.
+\\<completion-preview-active-mode-map>When the preview is visible, 
\\[completion-preview-insert]
+accepts the completion suggestion,
+\\[completion-preview-next-candidate] cycles forward to the next
+completion suggestion, and \\[completion-preview-prev-candidate]
+cycles backward.
+
+This is a minor mode.  If called interactively, toggle the
+`Completion-Preview mode' mode.  If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'.  Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `completion-preview-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t)
+(register-definition-prefixes "completion-preview" '("completion-preview-"))
+
+
 ;;; Generated autoloads from textmodes/conf-mode.el
 
 (autoload 'conf-mode "conf-mode" "\
@@ -5555,30 +5619,21 @@ into
 
 \\{cperl-mode-map}
 
-Setting the variable `cperl-font-lock' to t switches on `font-lock-mode'
-(even with older Emacsen), `cperl-electric-lbrace-space' to t switches
-on electric space between $ and {, `cperl-electric-parens-string' is
-the string that contains parentheses that should be electric in CPerl
-(see also `cperl-electric-parens-mark' and `cperl-electric-parens'),
-setting `cperl-electric-keywords' enables electric expansion of
-control structures in CPerl.  `cperl-electric-linefeed' governs which
-one of two linefeed behavior is preferable.  You can enable all these
-options simultaneously (recommended mode of use) by setting
-`cperl-hairy' to t.  In this case you can switch separate options off
-by setting them to `null'.  Note that one may undo the extra
-whitespace inserted by semis and braces in `auto-newline'-mode by
-consequent \\[cperl-electric-backspace].
-
-If your site has perl5 documentation in info format, you can use commands
-\\[cperl-info-on-current-command] and \\[cperl-info-on-command] to access it.
-These keys run commands `cperl-info-on-current-command' and
-`cperl-info-on-command', which one is which is controlled by variable
-`cperl-info-on-command-no-prompt' and `cperl-clobber-lisp-bindings'
-(in turn affected by `cperl-hairy').
-
-Even if you have no info-format documentation, short one-liner-style
-help is available on \\[cperl-get-help], and one can run perldoc or
-man via menu.
+Setting the variable `cperl-font-lock' to t switches on `font-lock-mode',
+`cperl-electric-lbrace-space' to t switches on electric space between $
+and {, `cperl-electric-parens-string' is the string that contains
+parentheses that should be electric in CPerl (see also
+`cperl-electric-parens-mark' and `cperl-electric-parens'), setting
+`cperl-electric-keywords' enables electric expansion of control
+structures in CPerl.  `cperl-electric-linefeed' governs which one of two
+linefeed behavior is preferable.  You can enable all these options
+simultaneously by setting `cperl-hairy' to t.  In this case you can
+switch separate options off by setting them to `null'.  Note that one may
+undo the extra whitespace inserted by semis and braces in
+`auto-newline'-mode by consequent \\[cperl-electric-backspace].
+
+Short one-liner-style help is available on \\[cperl-get-help],
+and one can run perldoc or man via menu.
 
 It is possible to show this help automatically after some idle time.
 This is regulated by variable `cperl-lazy-help-time'.  Default with
@@ -5669,7 +5724,7 @@ Run `perldoc' on WORD.
 (fn WORD)" t)
 (autoload 'cperl-perldoc-at-point "cperl-mode" "\
 Run a `perldoc' on the word around point." t)
-(register-definition-prefixes "cperl-mode" '("cperl-" "imenu-max-items"))
+(register-definition-prefixes "cperl-mode" '("cperl-"))
 
 
 ;;; Generated autoloads from progmodes/cpp.el
@@ -6249,6 +6304,13 @@ This stores EXP (without evaluating it) as the saved 
spec for SYMBOL.
 (fn &rest ARGS)")
 (autoload 'custom-save-icons "cus-edit" "\
 Save all customized icons in `custom-file'.")
+(autoload 'customize-dirlocals "cus-edit" "\
+Customize Directory Local Variables in the current directory.
+
+With optional argument FILENAME non-nil, customize the `.dir-locals.el' file
+that FILENAME specifies.
+
+(fn &optional FILENAME)" t)
 (register-definition-prefixes "cus-edit" '("Custom-" "cus" "widget-"))
 
 
@@ -6278,7 +6340,7 @@ When called from Lisp, BUFFER should be the buffer to 
use; if
 omitted, a buffer named *Custom Themes* is used.
 
 (fn &optional BUFFER)" t)
-(register-definition-prefixes "cus-theme" '("custom-" "describe-theme-1"))
+(register-definition-prefixes "cus-theme" '("custom-" "describe-theme-"))
 
 
 ;;; Generated autoloads from cedet/ede/custom.el
@@ -6634,6 +6696,13 @@ There is some minimal font-lock support (see vars
 
 (autoload 'debug "debug" "\
 Enter debugger.  \\<debugger-mode-map>`\\[debugger-continue]' returns from the 
debugger.
+
+In interactive sessions, this switches to a backtrace buffer and shows
+the Lisp backtrace of function calls there.  In batch mode (more accurately,
+when `noninteractive' is non-nil), it shows the Lisp backtrace on the
+standard error stream (unless `backtrace-on-error-noninteractive' is nil),
+and then kills Emacs, causing it to exit with a negative exit code.
+
 Arguments are mainly for use when this is called from the internals
 of the evaluator.
 
@@ -7263,29 +7332,36 @@ Major mode for editing the diary file.
 
 (autoload 'dictionary-mode "dictionary" "\
 Mode for searching a dictionary.
+
 This is a mode for searching a dictionary server implementing the
 protocol defined in RFC 2229.
 
 This is a quick reference to this mode describing the default key bindings:
 \\<dictionary-mode-map>
-* \\[dictionary-close] close the dictionary buffer
-* \\[describe-mode] display this help information
-* \\[dictionary-search] ask for a new word to search
-* \\[dictionary-lookup-definition] search the word at point
-* \\[forward-button] or TAB place point to the next link
-* \\[backward-button] or S-TAB place point to the prev link
-
-* \\[dictionary-match-words] ask for a pattern and list all matching words.
-* \\[dictionary-select-dictionary] select the default dictionary
-* \\[dictionary-select-strategy] select the default search strategy
-
-* \\`RET' or \\`<mouse-2>' visit that link")
+ \\[dictionary-close]  close the dictionary buffer
+ \\[describe-mode]     display this help
+ \\[dictionary-search] ask for a new word to search
+ \\[dictionary-lookup-definition]      search for word at point
+ \\[forward-button] or \\`TAB' move point to the next link
+ \\[backward-button] or \\`S-TAB'      move point to the previous link
+
+ \\[dictionary-match-words]    ask for a pattern and list all matching words
+ \\[dictionary-select-dictionary]      select the default dictionary
+ \\[dictionary-select-strategy]        select the default search strategy
+
+ \\`RET'       visit link at point
+ \\`<mouse-2>' visit clicked link
+
+(fn)" t)
 (autoload 'dictionary "dictionary" "\
 Create a new dictionary buffer and install `dictionary-mode'." t)
 (autoload 'dictionary-search "dictionary" "\
-Search the WORD in DICTIONARY if given or in all if nil.
-It presents the selection or word at point as default input and
-allows editing it.
+Search for WORD in all the known dictionaries.
+Interactively, prompt for WORD, and offer the word at point as default.
+
+Optional argument DICTIONARY means restrict the search to only
+that one dictionary.  Interactively, with prefix argument,
+prompt for DICTIONARY.
 
 (fn WORD &optional DICTIONARY)" t)
 (autoload 'dictionary-lookup-definition "dictionary" "\
@@ -7493,7 +7569,9 @@ each option.
 
 On systems such as MS-DOS and MS-Windows, which use `ls' emulation in Lisp,
 some of the `ls' switches are not supported; see the doc string of
-`insert-directory' in `ls-lisp.el' for more details.")
+`insert-directory' in `ls-lisp.el' for more details.
+
+For remote Dired buffers, this option supports connection-local values.")
 (custom-autoload 'dired-listing-switches "dired" t)
 (defvar-local dired-directory nil "\
 The directory name or wildcard spec that this Dired directory lists.
@@ -7622,7 +7700,7 @@ Like \\[dired-jump] (`dired-jump') but in other window.
 
 ;;; Generated autoloads from dired-aux.el
 
-(register-definition-prefixes "dired-aux" '("dired-"))
+(register-definition-prefixes "dired-aux" '("dired-" "shell-command-guess"))
 
 
 ;;; Generated autoloads from dired-x.el
@@ -7679,7 +7757,7 @@ If OBJECT is not already compiled, we compile it, but do 
not
 redefine OBJECT if it is a symbol.
 
 (fn OBJECT &optional BUFFER INDENT INTERACTIVE-P)" t)
-(register-definition-prefixes "disass" '("disassemble-"))
+(register-definition-prefixes "disass" '("disassemble-" "re-disassemble"))
 
 
 ;;; Generated autoloads from disp-table.el
@@ -8024,13 +8102,15 @@ Default is 2.
 
 ;;; Generated autoloads from dnd.el
 
-(defvar dnd-protocol-alist `((,(purecopy "^file:///") . dnd-open-local-file) 
(,(purecopy "^file://") . dnd-open-file) (,(purecopy "^file:") . 
dnd-open-local-file) (,(purecopy "^\\(https?\\|ftp\\|file\\|nfs\\)://") . 
dnd-open-file)) "\
+(defvar dnd-protocol-alist `((,(purecopy "^file:///") . dnd-open-local-file) 
(,(purecopy "^file://[^/]") . dnd-open-file) (,(purecopy "^file:/[^/]") . 
dnd-open-local-file) (,(purecopy "^file:[^/]") . dnd-open-local-file) 
(,(purecopy "^\\(https?\\|ftp\\|nfs\\)://") . dnd-open-file)) "\
 The functions to call for different protocols when a drop is made.
-This variable is used by `dnd-handle-one-url' and `dnd-handle-file-name'.
+This variable is used by `dnd-handle-multiple-urls'.
 The list contains of (REGEXP . FUNCTION) pairs.
 The functions shall take two arguments, URL, which is the URL dropped and
 ACTION which is the action to be performed for the drop (move, copy, link,
 private or ask).
+If a function's `dnd-multiple-handler' property is set, it is provided
+a list of each URI dropped instead.
 If no match is found here, and the value of `browse-url-browser-function'
 is a pair of (REGEXP . FUNCTION), those regexps are tried for a match.
 If no match is found, the URL is inserted as text by calling `dnd-insert-text'.
@@ -8669,7 +8749,7 @@ A second call of this function without changing point 
inserts the next match.
 A call with prefix PREFIX reads the symbol to insert from the minibuffer with
 completion.
 
-(fn PREFIX)" t)
+(fn PREFIX)" '("P"))
 (autoload 'ebrowse-tags-loop-continue "ebrowse" "\
 Repeat last operation on files in tree.
 FIRST-TIME non-nil means this is not a repetition, but the first time.
@@ -8979,7 +9059,7 @@ MERGE-AUTOSTORE-DIR is the directory in which to store 
merged files.
 (autoload 'ediff-windows-wordwise "ediff" "\
 Compare WIND-A and WIND-B, which are selected by clicking, wordwise.
 This compares the portions of text visible in each of the two windows.
-With prefix argument, DUMB-MODE, or on a non-windowing display, works as
+With prefix argument, DUMB-MODE, or on a non-graphical display, works as
 follows:
 If WIND-A is nil, use selected window.
 If WIND-B is nil, use window next to WIND-A.
@@ -8990,7 +9070,7 @@ arguments after setting up the Ediff buffers.
 (autoload 'ediff-windows-linewise "ediff" "\
 Compare WIND-A and WIND-B, which are selected by clicking, linewise.
 This compares the portions of text visible in each of the two windows.
-With prefix argument, DUMB-MODE, or on a non-windowing display, works as
+With prefix argument, DUMB-MODE, or on a non-graphical display, works as
 follows:
 If WIND-A is nil, use selected window.
 If WIND-B is nil, use window next to WIND-A.
@@ -9224,14 +9304,14 @@ Edit a keyboard macro which has been given a name by 
`name-last-kbd-macro'.
 (fn &optional PREFIX)" t)
 (autoload 'read-kbd-macro "edmacro" "\
 Read the region as a keyboard macro definition.
-The region is interpreted as spelled-out keystrokes, e.g., \"M-x abc RET\".
-See documentation for `edmacro-mode' for details.
+The region between START and END is interpreted as spelled-out keystrokes,
+e.g., \"M-x abc RET\".  See documentation for `edmacro-mode' for details.
 Leading/trailing \"C-x (\" and \"C-x )\" in the text are allowed and ignored.
 The resulting macro is installed as the \"current\" keyboard macro.
 
 In Lisp, may also be called with a single STRING argument in which case
 the result is returned rather than being installed as the current macro.
-The result will be a string if possible, otherwise an event vector.
+The result is a vector of input events.
 Second argument NEED-VECTOR means to return an event vector always.
 
 (fn START &optional END)" t)
@@ -9281,7 +9361,8 @@ Turn on EDT Emulation." t)
 
 ;;; Generated autoloads from progmodes/eglot.el
 
-(push (purecopy '(eglot 1 15)) package--builtin-versions)
+(push (purecopy '(eglot 1 16)) package--builtin-versions)
+(define-obsolete-function-alias 'eglot-update #'eglot-upgrade-eglot "29.1")
 (autoload 'eglot "eglot" "\
 Start LSP server for PROJECT's buffers under MANAGED-MAJOR-MODES.
 
@@ -9324,13 +9405,23 @@ INTERACTIVE is ignored and provided for backward 
compatibility.
 
 (fn MANAGED-MAJOR-MODES PROJECT CLASS CONTACT LANGUAGE-IDS &optional 
INTERACTIVE)" t)
 (autoload 'eglot-ensure "eglot" "\
-Start Eglot session for current buffer if there isn't one.")
+Start Eglot session for current buffer if there isn't one.
+
+Only use this function (in major mode hooks, etc) if you are
+confident that Eglot can be started safely and efficiently for
+*every* buffer visited where these hooks may execute.
+
+Since it is difficult to establish this confidence fully, it's
+often wise to use the interactive command `eglot' instead.  This
+command only needs to be invoked once per project, as all other
+files of a given major mode visited within the same project will
+automatically become managed with no further user intervention
+needed.")
 (autoload 'eglot-upgrade-eglot "eglot" "\
 Update Eglot to latest version.
 
 (fn &rest _)" t)
-(define-obsolete-function-alias 'eglot-update 'eglot-upgrade-eglot "29.1")
-(put 'eglot-workspace-configuration 'safe-local-variable 'listp)
+(put 'eglot-workspace-configuration 'safe-local-variable #'listp)
 (put 'eglot--debbugs-or-github-bug-uri 'bug-reference-url-format t)
 (defun eglot--debbugs-or-github-bug-uri nil (format (if (string= (match-string 
2) "github") "https://github.com/joaotavora/eglot/issues/%s"; 
"https://debbugs.gnu.org/%s";) (match-string 3)))
 (register-definition-prefixes "eglot" '("eglot-"))
@@ -9457,7 +9548,7 @@ Describe CTR if it is a class constructor.
 
 ;;; Generated autoloads from emacs-lisp/eldoc.el
 
-(push (purecopy '(eldoc 1 14 0)) package--builtin-versions)
+(push (purecopy '(eldoc 1 15 0)) package--builtin-versions)
 
 
 ;;; Generated autoloads from elec-pair.el
@@ -9639,7 +9730,7 @@ displayed." t)
 
 ;;; Generated autoloads from eshell/em-basic.el
 
-(register-definition-prefixes "em-basic" '("eshell"))
+(register-definition-prefixes "em-basic" '("eshell" 
"pcomplete/eshell-mode/eshell-debug"))
 
 
 ;;; Generated autoloads from eshell/em-cmpl.el
@@ -9861,7 +9952,7 @@ Emerge two RCS revisions of a file, with another revision 
as ancestor.
  (autoload 'emoji-recent "emoji" nil t)
  (autoload 'emoji-search "emoji" nil t)
 (autoload 'emoji-list "emoji" "\
-List emojis and insert the one that's selected.
+List emojis and allow selecting and inserting one of them.
 Select the emoji by typing \\<emoji-list-mode-map>\\[emoji-list-select] on its 
picture.
 The glyph will be inserted into the buffer that was current
 when the command was invoked." t)
@@ -10298,7 +10389,7 @@ for the values of the other parameters.
 
 See `erc-tls' for the meaning of ID.
 
-(fn &key SERVER PORT NICK USER PASSWORD FULL-NAME ID)" t)
+(fn &key SERVER PORT NICK USER PASSWORD FULL-NAME ID)" '((let 
((erc--display-context `((erc-interactive-display . erc) 
,@erc--display-context))) (erc-select-read-args))))
 (defalias 'erc-select #'erc)
 (autoload 'erc-tls "erc" "\
 ERC is a powerful, modular, and extensible IRC client.
@@ -10346,7 +10437,7 @@ See Info node `(erc) Network Identifier' for details.  
Like
 CLIENT-CERTIFICATE, this parameter cannot be specified
 interactively.
 
-(fn &key SERVER PORT NICK USER PASSWORD FULL-NAME CLIENT-CERTIFICATE ID)" t)
+(fn &key SERVER PORT NICK USER PASSWORD FULL-NAME CLIENT-CERTIFICATE ID)" 
'((let ((erc-default-port erc-default-port-tls) (erc--display-context 
`((erc-interactive-display . erc-tls) ,@erc--display-context))) 
(erc-select-read-args))))
 (autoload 'erc-handle-irc-url "erc" "\
 Use ERC to IRC on HOST:PORT in CHANNEL.
 If ERC is already connected to HOST:PORT, simply /join CHANNEL.
@@ -10546,7 +10637,7 @@ server name and search for a match in 
`erc-networks-alist'.")
 
 ;;; Generated autoloads from erc/erc-truncate.el
 
-(register-definition-prefixes "erc-truncate" '("erc-max-buffer-size"))
+(register-definition-prefixes "erc-truncate" '("erc-"))
 
 
 ;;; Generated autoloads from erc/erc-xdcc.el
@@ -10562,8 +10653,8 @@ Define NAME (a symbol) as a test.
 BODY is evaluated as a `progn' when the test is run.  It should
 signal a condition on failure or just return if the test passes.
 
-`should', `should-not', `should-error' and `skip-unless' are
-useful for assertions in BODY.
+`should', `should-not', `should-error', `skip-when', and
+`skip-unless' are useful for assertions in BODY.
 
 Use `ert' to run tests interactively.
 
@@ -10578,9 +10669,7 @@ it has to be wrapped in `(eval (quote ...))'.
 If NAME is already defined as a test and Emacs is running
 in batch mode, an error is signaled.
 
-(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] 
BODY...)" nil t)
-(function-put 'ert-deftest 'doc-string-elt 3)
-(function-put 'ert-deftest 'lisp-indent-function 2)
+(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] 
BODY...)" nil 'macro)
 (autoload 'ert-run-tests-batch "ert" "\
 Run the tests specified by SELECTOR, printing results to the terminal.
 
@@ -10641,7 +10730,7 @@ This mode mainly provides some font locking.
 
 ;;; Generated autoloads from eshell/esh-cmd.el
 
-(register-definition-prefixes "esh-cmd" '("eshell" 
"pcomplete/eshell-mode/eshell-debug"))
+(register-definition-prefixes "esh-cmd" '("eshell"))
 
 
 ;;; Generated autoloads from eshell/esh-ext.el
@@ -10805,6 +10894,8 @@ which is important if that buffer has a local value of 
`tags-file-name'.
 Returns t if it visits a tags table, or nil if there are no more in the list.
 
 (fn &optional CONT CBUF)")
+(autoload 'tags-reset-tags-tables "etags" "\
+Reset tags state to cancel effect of any previous \\[visit-tags-table] or 
\\[find-tag]." t)
 (autoload 'tags-table-files "etags" "\
 Return a list of files in the current tags table.
 Assumes the tags table is the current buffer.  The file names are returned
@@ -12167,13 +12258,30 @@ Delete all settings of file-local VARIABLE from the 
-*- line.
 (autoload 'add-dir-local-variable "files-x" "\
 Add directory-local VARIABLE with its VALUE and MODE to .dir-locals.el.
 
-(fn MODE VARIABLE VALUE)" t)
+With a prefix argument, prompt for the file to modify.
+
+When called from Lisp, FILE may be the expanded name of the dir-locals file
+where to add VARIABLE.
+
+(fn MODE VARIABLE VALUE &optional FILE)" t)
 (autoload 'delete-dir-local-variable "files-x" "\
-Delete all MODE settings of file-local VARIABLE from .dir-locals.el.
+Delete all MODE settings of dir-local VARIABLE from .dir-locals.el.
+
+With a prefix argument, prompt for the file to modify.
 
-(fn MODE VARIABLE)" t)
+When called from Lisp, FILE may be the expanded name of the dir-locals file
+from where to delete VARIABLE.
+
+(fn MODE VARIABLE &optional FILE)" t)
 (autoload 'copy-file-locals-to-dir-locals "files-x" "\
-Copy file-local variables to .dir-locals.el." t)
+Copy file-local variables to .dir-locals.el.
+
+With a prefix argument, prompt for the file to modify.
+
+When called from Lisp, FILE may be the expanded name of the dir-locals file
+where to copy the file-local variables.
+
+(fn &optional FILE)" t)
 (autoload 'copy-dir-locals-to-file-locals "files-x" "\
 Copy directory-local variables to the Local Variables list." t)
 (autoload 'copy-dir-locals-to-file-locals-prop-line "files-x" "\
@@ -12218,6 +12326,14 @@ function preserves the values of any existing variable
 definitions that aren't listed in VARIABLES.
 
 (fn PROFILE VARIABLES)")
+(autoload 'hack-connection-local-variables "files-x" "\
+Read connection-local variables according to CRITERIA.
+Store the connection-local variables in buffer local
+variable `connection-local-variables-alist'.
+
+This does nothing if `enable-connection-local-variables' is nil.
+
+(fn CRITERIA)")
 (autoload 'hack-connection-local-variables-apply "files-x" "\
 Apply connection-local variables identified by CRITERIA.
 Other local variables, like file-local and dir-local variables,
@@ -12261,11 +12377,25 @@ earlier in the `setq-connection-local'.  The return 
value of the
 `setq-connection-local' form is the value of the last VALUE.
 
 (fn [VARIABLE VALUE]...)" nil t)
+(autoload 'connection-local-p "files-x" "\
+Non-nil if VARIABLE has a connection-local binding in `default-directory'.
+If APPLICATION is nil, the value of
+`connection-local-default-application' is used.
+
+(fn VARIABLE &optional APPLICATION)" nil t)
+(autoload 'connection-local-value "files-x" "\
+Return connection-local VARIABLE for APPLICATION in `default-directory'.
+If APPLICATION is nil, the value of
+`connection-local-default-application' is used.
+If VARIABLE does not have a connection-local binding, the return
+value is the default binding of the variable.
+
+(fn VARIABLE &optional APPLICATION)" nil t)
 (autoload 'path-separator "files-x" "\
 The connection-local value of `path-separator'.")
 (autoload 'null-device "files-x" "\
 The connection-local value of `null-device'.")
-(register-definition-prefixes "files-x" '("connection-local-" 
"dir-locals-to-string" "hack-connection-local-variables" "modify-" 
"read-file-local-variable"))
+(register-definition-prefixes "files-x" '("connection-local-" 
"dir-locals-to-string" "modify-" "read-"))
 
 
 ;;; Generated autoloads from filesets.el
@@ -12687,7 +12817,7 @@ lines.
 
 ;;; Generated autoloads from progmodes/flymake.el
 
-(push (purecopy '(flymake 1 3 4)) package--builtin-versions)
+(push (purecopy '(flymake 1 3 7)) package--builtin-versions)
 (autoload 'flymake-log "flymake" "\
 Log, at level LEVEL, the message MSG formatted with ARGS.
 LEVEL is passed to `display-warning', which is used to display
@@ -12868,7 +12998,7 @@ it is disabled.
 Unconditionally turn on Flyspell mode.")
 (autoload 'turn-off-flyspell "flyspell" "\
 Unconditionally turn off Flyspell mode.")
-(autoload 'flyspell-mode-off "flyspell" "\
+(autoload 'flyspell--mode-off "flyspell" "\
 Turn Flyspell mode off.")
 (autoload 'flyspell-region "flyspell" "\
 Flyspell text between BEG and END.
@@ -15015,6 +15145,29 @@ The mode's hook is called both when the mode is 
enabled and when
 it is disabled.
 
 (fn &optional ARG)" t)
+(autoload 'lldb "gud" "\
+Run LLDB passing it COMMAND-LINE as arguments.
+If COMMAND-LINE names a program FILE to debug, LLDB will run in
+a buffer named *gud-FILE*, and the directory containing FILE
+becomes the initial working directory and source-file directory
+for the debug session.  If you don't want `default-directory' to
+change to the directory of FILE, specify FILE without leading
+directories, in which case FILE should reside either in the
+directory of the buffer from which this command is invoked, or
+it can be found by searching PATH.
+
+If COMMAND-LINE requests that LLDB attaches to a process PID, LLDB
+will run in *gud-PID*, otherwise it will run in *gud*; in these
+cases the initial working directory is the `default-directory' of
+the buffer in which this command was invoked.
+
+Please note that completion framework that complete while you
+type, like Corfu, do not work well with this mode.  You should
+consider to turn them off in this mode.
+
+This command runs functions from `lldb-mode-hook'.
+
+(fn COMMAND-LINE)" t)
 (register-definition-prefixes "gud" '("gdb-" "gud-"))
 
 
@@ -15952,7 +16105,7 @@ it is disabled.
 
 ;;; Generated autoloads from progmodes/hideshow.el
 
-(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))) "\
+(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) (lua-ts-mode 
"{\\|\\[\\[" "}\\|\\]\\]" "--" nil) (mhtml-mode "{\\|<[^/>]*?" 
"}\\|</[^/>]*[^/]>" "<!--" mhtml-forward nil))) "\
 Alist for initializing the hideshow variables for different modes.
 Each element has the form
   (MODE START END COMMENT-START FORWARD-SEXP-FUNC ADJUST-BEG-FUNC
@@ -16452,8 +16605,7 @@ inlined into the compiled format versions.  This means 
that if you
 change its definition, you should explicitly call
 `ibuffer-recompile-formats'.
 
-(fn SYMBOL (&key NAME INLINE PROPS SUMMARIZER) &rest BODY)" nil t)
-(function-put 'define-ibuffer-column 'lisp-indent-function 'defun)
+(fn SYMBOL (&key NAME INLINE PROPS SUMMARIZER) &rest BODY)" nil 'macro)
 (autoload 'define-ibuffer-sorter "ibuf-macs" "\
 Define a method of sorting named NAME.
 DOCUMENTATION is the documentation of the function, which will be called
@@ -16464,9 +16616,7 @@ For sorting, the forms in BODY will be evaluated with 
`a' bound to one
 buffer object, and `b' bound to another.  BODY should return a non-nil
 value if and only if `a' is \"less than\" `b'.
 
-(fn NAME DOCUMENTATION (&key DESCRIPTION) &rest BODY)" nil t)
-(function-put 'define-ibuffer-sorter 'lisp-indent-function 1)
-(function-put 'define-ibuffer-sorter 'doc-string-elt 2)
+(fn NAME DOCUMENTATION (&key DESCRIPTION) &rest BODY)" nil 'macro)
 (autoload 'define-ibuffer-op "ibuf-macs" "\
 Generate a function which operates on a buffer.
 OP becomes the name of the function; if it doesn't begin with
@@ -16505,9 +16655,7 @@ BODY define the operation; they are forms to evaluate 
per each
 marked buffer.  BODY is evaluated with `buf' bound to the
 buffer object.
 
-(fn OP ARGS DOCUMENTATION (&key INTERACTIVE MARK MODIFIER-P DANGEROUS OPSTRING 
ACTIVE-OPSTRING BEFORE AFTER COMPLEX) &rest BODY)" nil t)
-(function-put 'define-ibuffer-op 'lisp-indent-function 2)
-(function-put 'define-ibuffer-op 'doc-string-elt 3)
+(fn OP ARGS DOCUMENTATION (&key INTERACTIVE MARK MODIFIER-P DANGEROUS OPSTRING 
ACTIVE-OPSTRING BEFORE AFTER COMPLEX) &rest BODY)" nil 'macro)
 (autoload 'define-ibuffer-filter "ibuf-macs" "\
 Define a filter named NAME.
 DOCUMENTATION is the documentation of the function.
@@ -16522,9 +16670,7 @@ not a particular buffer should be displayed or not.  
The forms in BODY
 will be evaluated with BUF bound to the buffer object, and QUALIFIER
 bound to the current value of the filter.
 
-(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)" nil t)
-(function-put 'define-ibuffer-filter 'lisp-indent-function 2)
-(function-put 'define-ibuffer-filter 'doc-string-elt 2)
+(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)" nil 'macro)
 (register-definition-prefixes "ibuf-macs" '("ibuffer-"))
 
 
@@ -17785,9 +17931,8 @@ it is disabled.
 
 (fn &optional ARG)" t)
 (autoload 'image-mode-to-text "image-mode" "\
-Set a non-image mode as major mode in combination with image minor mode.
-A non-mage major mode found from `auto-mode-alist' or fundamental mode
-displays an image file as text.")
+Set current buffer's modes be a non-image major mode, plus `image-minor-mode'.
+A non-image major mode displays an image file as text.")
 (autoload 'image-bookmark-jump "image-mode" "\
 
 
@@ -17965,6 +18110,42 @@ Convert old Emacs Devanagari characters to UCS.
 (register-definition-prefixes "ind-util" '("combinatorial" "indian-" 
"is13194-"))
 
 
+;;; Generated autoloads from indent-aux.el
+
+(defvar kill-ring-deindent-mode nil "\
+Non-nil if Kill-Ring-Deindent mode is enabled.
+See the `kill-ring-deindent-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `kill-ring-deindent-mode'.")
+(custom-autoload 'kill-ring-deindent-mode "indent-aux" nil)
+(autoload 'kill-ring-deindent-mode "indent-aux" "\
+Toggle removal of indentation from text saved to the kill ring.
+
+When this minor mode is enabled, text saved into the kill ring is
+indented towards the left by the column number at the start of
+that text.
+
+This is a global minor mode.  If called interactively, toggle the
+`Kill-Ring-Deindent mode' mode.  If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'.  Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='kill-ring-deindent-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t)
+(register-definition-prefixes "indent-aux" 
'("kill-ring-deindent-buffer-substring-function"))
+
+
 ;;; Generated autoloads from leim/quail/indian.el
 
 (register-definition-prefixes "quail/indian" '("indian-mlm-mozhi-u" 
"inscript-" "quail-" "tamil"))
@@ -18612,6 +18793,8 @@ If APPEND is non-nil, don't erase previous debugging 
output.
 (fn &optional APPEND)" t)
 (autoload 'ispell-continue "ispell" "\
 Continue a halted spelling session beginning with the current word." t)
+(autoload 'ispell-completion-at-point "ispell" "\
+Word completion function for use in `completion-at-point-functions'.")
 (autoload 'ispell-complete-word "ispell" "\
 Try to complete the word before or at point.
 If optional INTERIOR-FRAG is non-nil, then the word may be a character
@@ -18868,7 +19051,7 @@ Major mode for editing JSON, powered by tree-sitter.
 
 ;;; Generated autoloads from jsonrpc.el
 
-(push (purecopy '(jsonrpc 1 0 17)) package--builtin-versions)
+(push (purecopy '(jsonrpc 1 0 23)) package--builtin-versions)
 (register-definition-prefixes "jsonrpc" '("jsonrpc-"))
 
 
@@ -19269,6 +19452,13 @@ the variables of the outer one.  You can, however, 
access alists
 inside the original alist by using dots inside the symbol, as
 displayed in the example above.
 
+Note that there is no way to differentiate the case where a key
+is missing from when it is present, but its value is nil.  Thus,
+the following form evaluates to nil:
+
+    (let-alist \\='((some-key . nil))
+      .some-key)
+
 (fn ALIST &rest BODY)" nil t)
 (function-put 'let-alist 'lisp-indent-function 1)
 (register-definition-prefixes "let-alist" '("let-alist--"))
@@ -19317,6 +19507,7 @@ sleep in seconds.
 
 ;;; Generated autoloads from emacs-lisp/loaddefs-gen.el
 
+(put 'autoload-compute-prefixes 'safe-local-variable #'booleanp)
 (put 'generated-autoload-file 'safe-local-variable 'stringp)
 (put 'generated-autoload-load-name 'safe-local-variable 'stringp)
 (autoload 'loaddefs-generate "loaddefs-gen" "\
@@ -19382,7 +19573,7 @@ remove symbols from it in the event that the package 
has done
 something strange, such as redefining an Emacs function.
 
 (fn FEATURE &optional FORCE)" t)
-(register-definition-prefixes "loadhist" '("feature-" "file-" "loadhist-" 
"read-feature" "unload-"))
+(register-definition-prefixes "loadhist" '("feature-" "file-" 
"loadhist-unload-filename" "read-feature" "unload-"))
 
 
 ;;; Generated autoloads from cedet/ede/locate.el
@@ -19572,6 +19763,19 @@ Otherwise they are treated as Emacs regexps (for 
backward compatibility).")
 (register-definition-prefixes "ls-lisp" '("ls-lisp-"))
 
 
+;;; Generated autoloads from progmodes/lua-ts-mode.el
+
+(autoload 'lua-ts-inferior-lua "lua-ts-mode" "\
+Run a Lua interpreter in an inferior process." t)
+(autoload 'lua-ts-mode "lua-ts-mode" "\
+Major mode for editing Lua files, powered by tree-sitter.
+
+\\{lua-ts-mode-map}
+
+(fn)" t)
+(register-definition-prefixes "lua-ts-mode" '("lua-ts-"))
+
+
 ;;; Generated autoloads from calendar/lunar.el
 
 (autoload 'lunar-phases "lunar" "\
@@ -19995,15 +20199,8 @@ dependency, despite the colon.
 
 \\{makefile-mode-map}
 
-In the browser, use the following keys:
-
-\\{makefile-browser-map}
-
 Makefile mode can be configured by modifying the following variables:
 
-`makefile-browser-buffer-name':
-    Name of the macro- and target browser buffer.
-
 `makefile-target-colon':
     The string that gets appended to all target names
     inserted by `makefile-insert-target'.
@@ -20021,24 +20218,6 @@ Makefile mode can be configured by modifying the 
following variables:
    If you want a TAB (instead of a space) to be appended after the
    target colon, then set this to a non-nil value.
 
-`makefile-browser-leftmost-column':
-   Number of blanks to the left of the browser selection mark.
-
-`makefile-browser-cursor-column':
-   Column in which the cursor is positioned when it moves
-   up or down in the browser.
-
-`makefile-browser-selected-mark':
-   String used to mark selected entries in the browser.
-
-`makefile-browser-unselected-mark':
-   String used to mark unselected entries in the browser.
-
-`makefile-browser-auto-advance-after-selection-p':
-   If this variable is set to a non-nil value the cursor
-   will automagically advance to the next line after an item
-   has been selected in the browser.
-
 `makefile-pickup-everything-picks-up-filenames-p':
    If this variable is set to a non-nil value then
    `makefile-pickup-everything' also picks up filenames as targets
@@ -20054,10 +20233,6 @@ Makefile mode can be configured by modifying the 
following variables:
    IMPORTANT: Please note that enabling this option causes Makefile mode
    to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\".
 
-`makefile-browser-hook':
-   A function or list of functions to be called just before the
-   browser is entered. This is executed in the makefile buffer.
-
 `makefile-special-targets-list':
    List of special targets. You will be offered to complete
    on one of those in the minibuffer whenever you enter a `.'.
@@ -20141,6 +20316,11 @@ Note that in some cases you will need to use 
\\[quoted-insert] to quote the
 SPC character in the above examples, because this command attempts
 to auto-complete your input based on the installed manual pages.
 
+If `default-directory' is remote, and `Man-support-remote-systems'
+is non-nil, this command formats the man page on the remote system.
+A prefix argument reverses the value of `Man-support-remote-systems'
+for the current invocation.
+
 (fn MAN-ARGS)" t)
 (autoload 'man-follow "man" "\
 Get a Un*x manual page of the item under point and put it in a buffer.
@@ -20359,7 +20539,15 @@ for \"x-scheme-handler/mailto;\" to \"emacs -f 
message-mailto %u\"
 will then start up Emacs ready to compose mail.  For emacsclient use
   emacsclient -e \\='(message-mailto \"%u\")'
 
-(fn &optional URL)" t)
+To facilitate the use of this function within window systems that
+provide message subject, body and attachments independent of URL
+itself, the arguments SUBJECT, BODY and FILE-ATTACHMENTS may also
+provide alternative message subject and body text, which is
+inserted in lieu of nothing if URL does not incorporate such
+information itself, and a list of files to insert as attachments
+to the E-mail.
+
+(fn &optional URL SUBJECT BODY FILE-ATTACHMENTS)" t)
 (register-definition-prefixes "message" '("message-"))
 
 
@@ -20899,7 +21087,21 @@ With a prefix argument, ask for a wildcard, and search 
in file buffers
 whose file names match the specified wildcard.
 
 (fn FILES)" t)
-(register-definition-prefixes "misearch" '("misearch-unload-function" 
"multi-isearch-"))
+(autoload 'multi-file-replace-regexp-as-diff "misearch" "\
+Show as diffs replacements of REGEXP with TO-STRING in FILES.
+DELIMITED has the same meaning as in `replace-regexp'.
+The replacements are displayed in the buffer *replace-diff* that
+you can later apply as a patch after reviewing the changes.
+
+(fn FILES REGEXP TO-STRING &optional DELIMITED)" t)
+(autoload 'replace-regexp-as-diff "misearch" "\
+Show as diffs replacements of REGEXP with TO-STRING in the current buffer.
+DELIMITED has the same meaning as in `replace-regexp'.
+The replacements are displayed in the buffer *replace-diff* that
+you can later apply as a patch after reviewing the changes.
+
+(fn REGEXP TO-STRING &optional DELIMITED)" t)
+(register-definition-prefixes "misearch" '("misearch-unload-function" 
"multi-"))
 
 
 ;;; Generated autoloads from progmodes/mixal-mode.el
@@ -22563,7 +22765,7 @@ Coloring:
 
 ;;; Generated autoloads from org/org.el
 
-(push (purecopy '(org 9 6 7)) package--builtin-versions)
+(push (purecopy '(org 9 6 13)) package--builtin-versions)
 (autoload 'org-babel-do-load-languages "org" "\
 Load the languages defined in `org-babel-load-languages'.
 
@@ -23529,8 +23731,7 @@ that code in the early init-file.
 (fn &optional NO-ACTIVATE)" t)
 (defun package-activate-all nil "\
 Activate all installed packages.
-The variable `package-load-list' controls which packages to load." (setq 
package--activated t) (let* ((elc (concat package-quickstart-file "c")) (qs (if 
(file-readable-p elc) elc (if (file-readable-p package-quickstart-file) 
package-quickstart-file)))) (if (and qs (not (bound-and-true-p 
package-activated-list))) (let ((load-source-file-function nil)) (unless 
(boundp 'package-activated-list) (setq package-activated-list nil)) (load qs 
nil 'nomessage)) (require 'package) (package--activate [...]
-(autoload 'package--activate-all "package")
+The variable `package-load-list' controls which packages to load." (setq 
package--activated t) (let* ((elc (concat package-quickstart-file "c")) (qs (if 
(file-readable-p elc) elc (if (file-readable-p package-quickstart-file) 
package-quickstart-file)))) (or (and qs (not (bound-and-true-p 
package-activated-list)) (with-demoted-errors "Error during quickstart: %S" 
(let ((load-source-file-function nil)) (unless (boundp 'package-activated-list) 
(setq package-activated-list nil)) (load qs nil  [...]
 (autoload 'package-import-keyring "package" "\
 Import keys from FILE.
 
@@ -23672,40 +23873,59 @@ DESC must be a `package-desc' object.
 (autoload 'package-vc-install-selected-packages "package-vc" "\
 Ensure packages specified in `package-vc-selected-packages' are installed." t)
 (autoload 'package-vc-upgrade-all "package-vc" "\
-Attempt to upgrade all installed VC packages." t)
+Upgrade all installed VC packages.
+
+This may fail if the local VCS state of one of the packages
+conflicts with its remote repository state." t)
 (autoload 'package-vc-upgrade "package-vc" "\
-Attempt to upgrade the package PKG-DESC.
+Upgrade the package described by PKG-DESC from package's VC repository.
+
+This may fail if the local VCS state of the package conflicts
+with the remote repository state.
 
 (fn PKG-DESC)" t)
 (autoload 'package-vc-install "package-vc" "\
-Fetch a PACKAGE and set it up for using with Emacs.
-
-If PACKAGE is a string containing an URL, download the package
-from the repository at that URL; the function will try to guess
-the name of the package from the URL.  This can be overridden by
-passing the optional argument NAME.  If PACKAGE is a cons-cell,
-it should have the form (NAME . SPEC), where NAME is a symbol
-indicating the package name and SPEC is a plist as described in
-`package-vc-selected-packages'.  Otherwise PACKAGE should be a
-symbol whose name is the package name, and the URL for the
-package will be taken from the package's metadata.
+Fetch a package described by PACKAGE and set it up for use with Emacs.
+
+PACKAGE specifies which package to install, where to find its
+source repository and how to build it.
+
+If PACKAGE is a symbol, install the package with that name
+according to metadata that package archives provide for it.  This
+is the simplest way to call this function, but it only works if
+the package you want to install is listed in a package archive
+you have configured.
+
+If PACKAGE is a string, it specifies the URL of the package
+repository.  In this case, optional argument BACKEND specifies
+the VC backend to use for cloning the repository; if it's nil,
+this function tries to infer which backend to use according to
+the value of `package-vc-heuristic-alist' and if that fails it
+uses `package-vc-default-backend'.  Optional argument NAME
+specifies the package name in this case; if it's nil, this
+package uses `file-name-base' on the URL to obtain the package
+name, otherwise NAME is the package name as a symbol.
+
+PACKAGE can also be a cons cell (PNAME . SPEC) where PNAME is the
+package name as a symbol, and SPEC is a plist that specifies how
+to fetch and build the package.  For possible values, see the
+subsection \"Specifying Package Sources\" in the Info
+node `(emacs)Fetching Package Sources'.
 
 By default, this function installs the last revision of the
 package available from its repository.  If REV is a string, it
-describes the revision to install, as interpreted by the VC
-backend.  The special value `:last-release' (interactively, the
-prefix argument), will use the commit of the latest release, if
-it exists.  The last release is the latest revision which changed
-the \"Version:\" header of the package's main Lisp file.
-
-Optional argument BACKEND specifies the VC backend to use for cloning
-the package's repository; this is only possible if NAME-OR-URL is a URL,
-a string.  If BACKEND is omitted or nil, the function
-uses `package-vc-heuristic-alist' to guess the backend.
-Note that by default, a VC package will be prioritized over a
-regular package, but it will not remove a VC package.
-
-(fn PACKAGE &optional REV BACKEND)" t)
+describes the revision to install, as interpreted by the relevant
+VC backend.  The special value `:last-release' (interactively,
+the prefix argument), says to use the commit of the latest
+release, if it exists.  The last release is the latest revision
+which changed the \"Version:\" header of the package's main Lisp
+file.
+
+If you use this function to install a package that you also have
+installed from a package archive, the version this function
+installs takes precedence.
+
+(fn PACKAGE &optional REV BACKEND NAME)" t)
 (autoload 'package-vc-checkout "package-vc" "\
 Clone the sources for PKG-DESC into DIRECTORY and visit that directory.
 Unlike `package-vc-install', this does not yet set up the package
@@ -23719,14 +23939,14 @@ for the last released version of the package.
 
 (fn PKG-DESC DIRECTORY &optional REV)" t)
 (autoload 'package-vc-install-from-checkout "package-vc" "\
-Set up the package NAME in DIR by linking it into the ELPA directory.
+Install the package NAME from its source directory DIR.
+NAME defaults to the base name of DIR.
 Interactively, prompt the user for DIR, which should be a directory
 under version control, typically one created by `package-vc-checkout'.
 If invoked interactively with a prefix argument, prompt the user
-for the NAME of the package to set up.  Otherwise infer the package
-name from the base name of DIR.
+for the NAME of the package to set up.
 
-(fn DIR NAME)" t)
+(fn DIR &optional NAME)" t)
 (autoload 'package-vc-rebuild "package-vc" "\
 Rebuild the installation for package given by PKG-DESC.
 Rebuilding an installation means scraping for new autoload
@@ -23738,14 +23958,18 @@ prompt for the name of the package to rebuild.
 
 (fn PKG-DESC)" t)
 (autoload 'package-vc-prepare-patch "package-vc" "\
-Send patch for REVISIONS to maintainer of the package PKG using SUBJECT.
-The function uses `vc-prepare-patch', passing SUBJECT and
-REVISIONS directly.  PKG-DESC must be a package description.
+Email patches for REVISIONS to maintainer of package PKG-DESC using SUBJECT.
+
+PKG-DESC is a package descriptor and SUBJECT is the subject of
+the message.
+
 Interactively, prompt for PKG-DESC, SUBJECT, and REVISIONS.  When
 invoked with a numerical prefix argument, use the last N
 revisions.  When invoked interactively in a Log View buffer with
 marked revisions, use those.
 
+See also `vc-prepare-patch'.
+
 (fn PKG-DESC SUBJECT REVISIONS)" t)
 (register-definition-prefixes "package-vc" '("package-vc-"))
 
@@ -23774,6 +23998,11 @@ archive).
 (register-definition-prefixes "page-ext" '("pages-"))
 
 
+;;; Generated autoloads from leim/quail/pakistan.el
+
+(register-definition-prefixes "quail/pakistan" '("pakistan-"))
+
+
 ;;; Generated autoloads from calendar/parse-time.el
 
 (put 'parse-time-rules 'risky-local-variable t)
@@ -24107,7 +24336,7 @@ Completion for checksum commands.")
 (defalias 'pcomplete/sha224sum 'pcomplete/md5sum)
 (defalias 'pcomplete/sha256sum 'pcomplete/md5sum)
 (defalias 'pcomplete/sha384sum 'pcomplete/md5sum)
-(defalias 'pcomplete/sha521sum 'pcomplete/md5sum)
+(defalias 'pcomplete/sha512sum 'pcomplete/md5sum)
 (autoload 'pcomplete/sort "pcmpl-unix" "\
 Completion for the `sort' command.")
 (autoload 'pcomplete/shuf "pcmpl-unix" "\
@@ -24236,6 +24465,8 @@ Includes files as well as host names followed by a 
colon.")
 (autoload 'pcomplete/telnet "pcmpl-unix")
 (autoload 'pcomplete/sudo "pcmpl-unix" "\
 Completion for the `sudo' command.")
+(autoload 'pcomplete/doas "pcmpl-unix" "\
+Completion for the `doas' command.")
 (register-definition-prefixes "pcmpl-unix" '("pcmpl-" "pcomplete/"))
 
 
@@ -24544,6 +24775,11 @@ they are not by default assigned to keys." t)
 (register-definition-prefixes "picture" '("picture-"))
 
 
+;;; Generated autoloads from language/pinyin.el
+
+(register-definition-prefixes "pinyin" '("pinyin-character-map"))
+
+
 ;;; Generated autoloads from textmodes/pixel-fill.el
 
 (register-definition-prefixes "pixel-fill" '("pixel-fill-"))
@@ -24600,7 +24836,7 @@ or call the function `pixel-scroll-precision-mode'.")
 (autoload 'pixel-scroll-precision-mode "pixel-scroll" "\
 Toggle pixel scrolling.
 
-When enabled, this minor mode allows to scroll the display
+When enabled, this minor mode allows you to scroll the display
 precisely, according to the turning of the mouse wheel.
 
 This is a global minor mode.  If called interactively, toggle the
@@ -25316,7 +25552,7 @@ Open profile FILENAME.
 
 ;;; Generated autoloads from progmodes/project.el
 
-(push (purecopy '(project 0 9 8)) package--builtin-versions)
+(push (purecopy '(project 0 10 0)) package--builtin-versions)
 (autoload 'project-current "project" "\
 Return the project instance in DIRECTORY, defaulting to `default-directory'.
 
@@ -25337,12 +25573,12 @@ See the doc string of `project-find-functions' for 
the general form
 of the project instance object.
 
 (fn &optional MAYBE-PROMPT DIRECTORY)")
-(put 'project-vc-ignores 'safe-local-variable #'listp)
+(put 'project-vc-ignores 'safe-local-variable (lambda (val) (and (listp val) 
(not (memq nil (mapcar #'stringp val))))))
 (put 'project-vc-merge-submodules 'safe-local-variable #'booleanp)
 (put 'project-vc-include-untracked 'safe-local-variable #'booleanp)
 (put 'project-vc-name 'safe-local-variable #'stringp)
 (put 'project-vc-extra-root-markers 'safe-local-variable (lambda (val) (and 
(listp val) (not (memq nil (mapcar #'stringp val))))))
-(defvar project-prefix-map (let ((map (make-sparse-keymap))) (define-key map 
"!" 'project-shell-command) (define-key map "&" 'project-async-shell-command) 
(define-key map "f" 'project-find-file) (define-key map "F" 
'project-or-external-find-file) (define-key map "b" 'project-switch-to-buffer) 
(define-key map "s" 'project-shell) (define-key map "d" 'project-find-dir) 
(define-key map "D" 'project-dired) (define-key map "v" 'project-vc-dir) 
(define-key map "c" 'project-compile) (define-key  [...]
+(defvar project-prefix-map (let ((map (make-sparse-keymap))) (define-key map 
"!" 'project-shell-command) (define-key map "&" 'project-async-shell-command) 
(define-key map "f" 'project-find-file) (define-key map "F" 
'project-or-external-find-file) (define-key map "b" 'project-switch-to-buffer) 
(define-key map "s" 'project-shell) (define-key map "d" 'project-find-dir) 
(define-key map "D" 'project-dired) (define-key map "v" 'project-vc-dir) 
(define-key map "c" 'project-compile) (define-key  [...]
 Keymap for project commands.")
  (define-key ctl-x-map "p" project-prefix-map)
 (autoload 'project-other-window-command "project" "\
@@ -25388,7 +25624,8 @@ pattern to search for.
 Visit a file (with completion) in the current project.
 
 The filename at point (determined by `thing-at-point'), if any,
-is available as part of \"future history\".
+is available as part of \"future history\".  If none, the current
+buffer's file name is used.
 
 If INCLUDE-ALL is non-nil, or with prefix argument when called
 interactively, include all files under the project root, except
@@ -25399,7 +25636,8 @@ for VCS directories listed in 
`vc-directory-exclusion-list'.
 Visit a file (with completion) in the current project or external roots.
 
 The filename at point (determined by `thing-at-point'), if any,
-is available as part of \"future history\".
+is available as part of \"future history\".  If none, the current
+buffer's file name is used.
 
 If INCLUDE-ALL is non-nil, or with prefix argument when called
 interactively, include all files under the project root, except
@@ -25407,7 +25645,10 @@ for VCS directories listed in 
`vc-directory-exclusion-list'.
 
 (fn &optional INCLUDE-ALL)" t)
 (autoload 'project-find-dir "project" "\
-Start Dired in a directory inside the current project." t)
+Start Dired in a directory inside the current project.
+
+The current buffer's `default-directory' is available as part of
+\"future history\"." t)
 (autoload 'project-dired "project" "\
 Start Dired in the current project's root." t)
 (autoload 'project-vc-dir "project" "\
@@ -25522,6 +25763,24 @@ Return the list of root directories of all known 
projects.")
 (autoload 'project-execute-extended-command "project" "\
 Execute an extended command in project root." t)
 (function-put 'project-execute-extended-command 'interactive-only 
'command-execute)
+(autoload 'project-any-command "project" "\
+Run the next command in the current project.
+
+If the command name starts with `project-', or its symbol has
+property `project-aware', it gets passed the project to use
+with the variable `project-current-directory-override'.
+Otherwise, `default-directory' is temporarily set to the current
+project's root.
+
+If OVERRIDING-MAP is non-nil, it will be used as
+`overriding-local-map' to provide shorter bindings from that map
+which will take priority over the global ones.
+
+(fn &optional OVERRIDING-MAP PROMPT-FORMAT)" t)
+(autoload 'project-prefix-or-any-command "project" "\
+Run the next command in the current project.
+Works like `project-any-command', but also mixes in the shorter
+bindings from `project-prefix-map'." t)
 (autoload 'project-switch-project "project" "\
 \"Switch\" to another project by running an Emacs command.
 The available commands are presented as a dispatch menu
@@ -25540,6 +25799,12 @@ the buffer's directory name when buffers from two 
different projects
 would otherwise have the same name.
 
 (fn DIRNAME)")
+(defvar project-mode-line nil "\
+Whether to show current project name and Project menu on the mode line.
+This feature requires the presence of the following item in
+`mode-line-format': `(project-mode-line project-mode-line-format)'; it
+is part of the default mode line beginning with Emacs 30.")
+(custom-autoload 'project-mode-line "project" t)
 (register-definition-prefixes "project" '("project-"))
 
 
@@ -26578,7 +26843,7 @@ This enforces rescanning the buffer on next use.")
 (put 'reftex-vref-is-default 'safe-local-variable (lambda (x) (or (stringp x) 
(symbolp x))))
 (put 'reftex-fref-is-default 'safe-local-variable (lambda (x) (or (stringp x) 
(symbolp x))))
 (put 'reftex-level-indent 'safe-local-variable 'integerp)
-(put 'reftex-guess-label-type 'safe-local-variable (lambda (x) (memq x '(nil 
t))))
+(put 'reftex-guess-label-type 'safe-local-variable #'booleanp)
 (register-definition-prefixes "reftex-vars" '("reftex-"))
 
 
@@ -28441,7 +28706,7 @@ Like `mail' command, but display mail buffer in another 
frame.
 
 ;;; Generated autoloads from emacs-lisp/seq.el
 
-(push (purecopy '(seq 2 23)) package--builtin-versions)
+(push (purecopy '(seq 2 24)) package--builtin-versions)
 
 
 ;;; Generated autoloads from server.el
@@ -30477,6 +30742,8 @@ but with the twist that BODY can evaluate itself 
recursively by
 calling NAME, where the arguments passed to NAME are used
 as the new values of the bound variables in the recursive invocation.
 
+This construct can only be used with lexical binding.
+
 (fn NAME BINDINGS &rest BODY)" nil t)
 (function-put 'named-let 'lisp-indent-function 2)
 (autoload 'string-pixel-width "subr-x" "\
@@ -32308,7 +32575,10 @@ Convert SECONDS to a proper time, like `current-time' 
would.
 
 (fn SECONDS)")
 (autoload 'days-to-time "time-date" "\
-Convert DAYS into a time value.
+Convert Emacs-epoch DAYS into a time value.
+Note that this does not use the same epoch as `time-to-days'; you
+must subtract (time-to-days 0) first to convert, and may get nil
+if the result is before the start.
 
 (fn DAYS)")
 (autoload 'time-since "time-date" "\
@@ -32337,7 +32607,7 @@ Return the day number within the year corresponding to 
TIME.
 
 (fn TIME)")
 (autoload 'time-to-days "time-date" "\
-The absolute date corresponding to TIME, a time value.
+The absolute pseudo-Gregorian date for TIME, a time value.
 The absolute date is the number of days elapsed since the imaginary
 Gregorian date Sunday, December 31, 1 BC.
 
@@ -32654,20 +32924,14 @@ and done items are always shown on visiting a 
category.
 (autoload 'todo-mode "todo-mode" "\
 Major mode for displaying, navigating and editing todo lists.
 
-\\{todo-mode-map}
-
 (fn)" t)
 (autoload 'todo-archive-mode "todo-mode" "\
 Major mode for archived todo categories.
 
-\\{todo-archive-mode-map}
-
 (fn)" t)
 (autoload 'todo-filtered-items-mode "todo-mode" "\
 Mode for displaying and reprioritizing top priority Todo.
 
-\\{todo-filtered-items-mode-map}
-
 (fn)" t)
 (register-definition-prefixes "todo-mode" '("todo-"))
 
@@ -32968,6 +33232,7 @@ Add archive file name handler to 
`file-name-handler-alist'." (when (and tramp-ar
 
 ;;; Generated autoloads from transient.el
 
+(push (purecopy '(transient 0 5 2)) package--builtin-versions)
 (autoload 'transient-define-prefix "transient" "\
 Define NAME as a transient prefix command.
 
@@ -33060,7 +33325,7 @@ See info node `(transient)Modifying Existing 
Transients'.
 
 (fn PREFIX LOC)")
 (function-put 'transient-remove-suffix 'lisp-indent-function 'defun)
-(register-definition-prefixes "transient" '("transient"))
+(register-definition-prefixes "transient" '("static-if" "transient"))
 
 
 ;;; Generated autoloads from tree-widget.el
@@ -33309,7 +33574,9 @@ FRAC should be the inverse of the fractional value; for 
example, a value of
 ;;; Generated autoloads from progmodes/typescript-ts-mode.el
 
 (autoload 'typescript-ts-base-mode "typescript-ts-mode" "\
-Major mode for editing TypeScript.
+Generic major mode for editing TypeScript.
+
+This mode is intended to be inherited by concrete major modes.
 
 (fn)" t)
 (autoload 'typescript-ts-mode "typescript-ts-mode" "\
@@ -33328,7 +33595,7 @@ The JSX-specific faces are used when 
`treesit-font-lock-level' is
 at least 3 (which is the default value).
 
 (fn)" t)
-(register-definition-prefixes "typescript-ts-mode" '("tsx-ts-mode--" 
"typescript-ts-mode-"))
+(register-definition-prefixes "typescript-ts-mode" '("tsx-ts-" 
"typescript-ts-"))
 
 
 ;;; Generated autoloads from international/ucs-normalize.el
@@ -33612,6 +33879,7 @@ Handle file: and ftp: URLs.
 Attempt to resolve the given HOST using nslookup if possible.
 
 (fn HOST)" t)
+(make-obsolete 'url-gateway-nslookup-host 'nil "30.1")
 (autoload 'url-open-stream "url-gw" "\
 Open a stream to HOST, possibly via a gateway.
 Args per `open-network-stream'.
@@ -34379,18 +34647,23 @@ responsible for the given file.
 (autoload 'vc-next-action "vc" "\
 Do the next logical version control operation on the current fileset.
 This requires that all files in the current VC fileset be in the
-same state.  If not, signal an error.
-
-For merging-based version control systems:
-  If every file in the VC fileset is not registered for version
-   control, register the fileset (but don't commit).
-  If every work file in the VC fileset is added or changed, pop
-   up a *vc-log* buffer to commit the fileset.
+same state.  If they are not, signal an error.  Also signal an error if
+files in the fileset are missing (removed, but tracked by version control),
+or are ignored by the version control system.
+
+For modern merging-based version control systems:
+  If every file in the fileset is not registered for version
+   control, register the fileset (but don't commit).  If VERBOSE is
+   non-nil (interactively, the prefix argument), ask for the VC
+   backend with which to register the fileset.
+  If every work file in the VC fileset is either added or modified,
+   pop up a *vc-log* buffer to commit the fileset changes.
   For a centralized version control system, if any work file in
    the VC fileset is out of date, offer to update the fileset.
 
 For old-style locking-based version control systems, like RCS:
-  If every file is not registered, register the file(s).
+  If every file is not registered, register the file(s); with a prefix
+   argument, allow to specify the VC backend for registration.
   If every file is registered and unlocked, check out (lock)
    the file(s) for editing.
   If every file is locked by you and has changes, pop up a
@@ -34398,14 +34671,21 @@ For old-style locking-based version control systems, 
like RCS:
    read-only copy of each changed file after checking in.
   If every file is locked by you and unchanged, unlock them.
   If every file is locked by someone else, offer to steal the lock.
+  If files are unlocked, but have changes, offer to either claim the
+   lock or revert to the last checked-in version.
+
+If this command is invoked from a patch buffer under `diff-mode', it
+will apply the diffs from the patch and pop up a *vc-log* buffer to
+check-in the resulting changes.
 
 When using this command to register a new file (or files), it
 will automatically deduce which VC repository to register it
 with, using the most specific one.
 
 If VERBOSE is non-nil (interactively, the prefix argument),
-you can specify a VC backend or (for centralized VCS only)
-the revision ID or branch ID.
+you can specify another VC backend for the file(s),
+or (for centralized VCS only) the revision ID or branch ID
+from which to check out the file(s).
 
 (fn VERBOSE)" t)
 (autoload 'vc-register "vc" "\
@@ -34709,7 +34989,7 @@ On a non-distributed version control system, this 
signals an error.
 It also signals an error in a Bazaar bound branch.
 
 (fn &optional ARG)" t)
-(autoload 'vc-switch-backend "vc" "\
+(autoload 'vc-change-backend "vc" "\
 Make BACKEND the current version control system for FILE.
 FILE must already be registered in BACKEND.  The change is not
 permanent, only for the current session.  This function only changes
@@ -34718,7 +34998,6 @@ By default, this command cycles through the registered 
backends.
 To get a prompt, use a prefix argument.
 
 (fn FILE BACKEND)" t)
-(make-obsolete 'vc-switch-backend 'nil "28.1")
 (autoload 'vc-transfer-file "vc" "\
 Transfer FILE to another version control system NEW-BACKEND.
 If NEW-BACKEND has a higher precedence than FILE's current backend
@@ -34774,7 +35053,7 @@ When invoked interactively in a Log View buffer with
 marked revisions, use those.
 
 (fn ADDRESSEE SUBJECT REVISIONS)" t)
-(register-definition-prefixes "vc" '("vc-" "with-vc-properties"))
+(register-definition-prefixes "vc" '("log-view-vc-prev-" "vc-" 
"with-vc-properties"))
 
 
 ;;; Generated autoloads from vc/vc-annotate.el
@@ -36109,6 +36388,18 @@ so the value of `wallpaper-commands' is ignored.
 
 ;;; Generated autoloads from emacs-lisp/warnings.el
 
+(defvar warning-suppress-types nil "\
+List of warning types not to display immediately.
+If any element of this list matches the TYPE argument to `display-warning',
+the warning is logged nonetheless, but the warnings buffer is
+not immediately displayed.
+The element must match an initial segment of the list TYPE.
+Thus, (foo bar) as an element matches (foo bar)
+or (foo bar ANYTHING...) as TYPE.
+If TYPE is a symbol FOO, that is equivalent to the list (FOO),
+so only the element (FOO) will match it.
+See also `warning-suppress-log-types'.")
+(custom-autoload 'warning-suppress-types "warnings" t)
 (defvar warning-prefix-function nil "\
 Function to generate warning prefixes.
 This function, if non-nil, is called with two arguments,
@@ -36973,6 +37264,10 @@ updated (e.g. to re-interpret the current directory).
 Used non-interactively, arguments are optional: if given then TOPIC
 should be a topic string and non-nil RE-CACHE forces re-caching.
 
+Note that `M-x woman' doesn’t yet support the latest features of
+modern man pages, so we recommend using `M-x man' if that is
+available on your system.
+
 (fn &optional TOPIC RE-CACHE)" t)
 (autoload 'woman-dired-find-file "woman" "\
 In dired, run the WoMan man-page browser on this file." t)
@@ -37357,6 +37652,102 @@ run a specific program.  The program must be a member 
of
 
 (fn &optional PGM)" t)
 (register-definition-prefixes "zone" '("zone-"))
+
+
+;;; Generated autoloads from emacs-lisp/ert-font-lock.el
+
+(autoload 'ert-font-lock-deftest "ert-font-lock" "\
+Define test NAME (a symbol) using assertions from TEST-STR.
+
+Other than MAJOR-MODE and TEST-STR parameters, this macro accepts
+the same parameters and keywords as `ert-deftest' and is intended
+to be used through `ert'.
+
+(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] 
MAJOR-MODE TEST-STR)" nil t)
+(function-put 'ert-font-lock-deftest 'doc-string-elt 3)
+(function-put 'ert-font-lock-deftest 'lisp-indent-function 2)
+(autoload 'ert-font-lock-deftest-file "ert-font-lock" "\
+Define test NAME (a symbol) using assertions from FILE.
+
+FILE - path to a file with assertions in ERT resource director as
+return by `ert-resource-directory'.
+
+Other than MAJOR-MODE and FILE parameters, this macro accepts the
+same parameters and keywords as `ert-deftest' and is intended to
+be used through `ert'.
+
+(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] 
MAJOR-MODE FILE)" nil t)
+(function-put 'ert-font-lock-deftest-file 'doc-string-elt 3)
+(function-put 'ert-font-lock-deftest-file 'lisp-indent-function 2)
+(autoload 'ert-font-lock-test-string "ert-font-lock" "\
+Check font faces in TEST-STRING set by MODE.
+
+The function is meant to be run from within an ERT test.
+
+(fn TEST-STRING MODE)")
+(autoload 'ert-font-lock-test-file "ert-font-lock" "\
+Check font faces in FILENAME set by MODE.
+
+The function is meant to be run from within an ERT test.
+
+(fn FILENAME MODE)")
+(register-definition-prefixes "ert-font-lock" '("ert-font-lock--"))
+
+
+;;; Generated autoloads from touch-screen.el
+
+(autoload 'touch-screen-hold "touch-screen" "\
+Handle a long press EVENT.
+Ding and select the window at EVENT, then activate the mark.  If
+`touch-screen-word-select' is enabled, try to select the whole
+word around EVENT; otherwise, set point to the location of EVENT.
+
+(fn EVENT)" t)
+(autoload 'touch-screen-track-tap "touch-screen" "\
+Track a single tap starting from EVENT.
+EVENT should be a `touchscreen-begin' event.
+
+Read touch screen events until a `touchscreen-end' event is
+received with the same ID as in EVENT.  If UPDATE is non-nil and
+a `touchscreen-update' event is received in the mean time and
+contains a touch point with the same ID as in EVENT, call UPDATE
+with that event and DATA.
+
+If THRESHOLD is non-nil, enforce a threshold of movement that is
+either itself or 10 pixels when it is not a number.  If the
+aforementioned touch point moves beyond that threshold on any
+axis, return nil immediately, and further resume mouse event
+translation for the touch point at hand.
+
+Return nil immediately if any other kind of event is received;
+otherwise, return t once the `touchscreen-end' event arrives.
+
+(fn EVENT &optional UPDATE DATA THRESHOLD)")
+(autoload 'touch-screen-track-drag "touch-screen" "\
+Track a single drag starting from EVENT.
+EVENT should be a `touchscreen-begin' event.
+
+Read touch screen events until a `touchscreen-end' event is
+received with the same ID as in EVENT.  For each
+`touchscreen-update' event received in the mean time containing a
+touch point with the same ID as in EVENT, call UPDATE with the
+touch point in event and DATA, once the touch point has moved
+significantly by at least 5 pixels from where it was in EVENT.
+
+Return nil immediately if any other kind of event is received;
+otherwise, return either t or `no-drag' once the
+`touchscreen-end' event arrives; return `no-drag' returned if the
+touch point in EVENT did not move significantly, and t otherwise.
+
+(fn EVENT UPDATE &optional DATA)")
+(autoload 'touch-screen-inhibit-drag "touch-screen" "\
+Inhibit subsequent `touchscreen-drag' events from being sent.
+Prevent `touchscreen-drag' and translated mouse events from being
+sent until the touch sequence currently being translated ends.
+Must be called from a command bound to a `touchscreen-hold' or
+`touchscreen-drag' event.")
+(register-definition-prefixes "touch-screen" '("touch-screen-"))
+
 
 ;;; End of scraped data
 
diff --git a/lisp/leim/quail/arabic.el b/lisp/leim/quail/arabic.el
index 83a7c12147f..7c693190d89 100644
--- a/lisp/leim/quail/arabic.el
+++ b/lisp/leim/quail/arabic.el
@@ -1,6 +1,6 @@
 ;;; arabic.el --- Quail package for inputting Arabic   -*- coding: utf-8; 
lexical-binding:t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Cloos <cloos@jhcloos.com>
 ;; Keywords: mule, input method, Arabic
diff --git a/lisp/leim/quail/cham.el b/lisp/leim/quail/cham.el
index 1778fa312c8..b5101ccbebf 100644
--- a/lisp/leim/quail/cham.el
+++ b/lisp/leim/quail/cham.el
@@ -1,6 +1,6 @@
 ;;; cham.el --- Quail package for inputting Cham characters  -*- coding: 
utf-8; lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Eli Zaretskii <eliz@gnu.org>
 ;; Keywords: i18n
diff --git a/lisp/leim/quail/compose.el b/lisp/leim/quail/compose.el
index 3200943f724..bc52c8efae3 100644
--- a/lisp/leim/quail/compose.el
+++ b/lisp/leim/quail/compose.el
@@ -1,6 +1,6 @@
 ;;; compose.el --- Quail package for Multi_key character composition 
-*-coding: utf-8; lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Juri Linkov <juri@linkov.net>
 ;; Keywords: multilingual, input method, i18n
diff --git a/lisp/leim/quail/croatian.el b/lisp/leim/quail/croatian.el
index 84dd8b1e459..2524013fbe9 100644
--- a/lisp/leim/quail/croatian.el
+++ b/lisp/leim/quail/croatian.el
@@ -1,6 +1,6 @@
 ;;; croatian.el --- Quail package for inputting Croatian  -*-coding: utf-8; 
lexical-binding:t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Hrvoje Nikšić <hrvoje.niksic@avl.com>
 ;; Keywords: i18n
diff --git a/lisp/leim/quail/cyril-jis.el b/lisp/leim/quail/cyril-jis.el
index f25cc0efe25..4cce8369905 100644
--- a/lisp/leim/quail/cyril-jis.el
+++ b/lisp/leim/quail/cyril-jis.el
@@ -1,6 +1,6 @@
 ;;; cyril-jis.el --- Quail package for inputting JISX0208 Cyrillic letters  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/cyrillic.el b/lisp/leim/quail/cyrillic.el
index 5ba1c4801fd..60c88221a65 100644
--- a/lisp/leim/quail/cyrillic.el
+++ b/lisp/leim/quail/cyrillic.el
@@ -1,6 +1,6 @@
 ;;; cyrillic.el --- Quail package for inputting Cyrillic characters  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
@@ -1101,9 +1101,9 @@ as follows.
 ;; Ognyan Kulev <ogi@fmi.uni-sofia.bg> wrote:
 
 ;; I would suggest future `cyrillic-translit' to be with the
-;; modification of `cyrillic-translit-bulgarian' applied and the
+;; modification of `cyrillic-translit-bulgarian' (now deleted) applied and the
 ;; latter to disappear.  It could be used by people who write
-;; bulgarian e-mails with latin letters for kick start (phonetic input
+;; Bulgarian e-mails with latin letters for kick start (phonetic input
 ;; method is not so obvious as translit input method but each letter
 ;; is one keypress and a *lot* of people know it).
 
diff --git a/lisp/leim/quail/czech.el b/lisp/leim/quail/czech.el
index 90ee15ad3b4..5c5390fe6e4 100644
--- a/lisp/leim/quail/czech.el
+++ b/lisp/leim/quail/czech.el
@@ -1,6 +1,6 @@
 ;;; czech.el --- Quail package for inputting Czech -*-coding: utf-8; 
lexical-binding:t -*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Milan Zamazal <pdm@zamazal.org>
 ;; Maintainer: Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/leim/quail/emoji.el b/lisp/leim/quail/emoji.el
index 553b0f8d966..c270898f75c 100644
--- a/lisp/leim/quail/emoji.el
+++ b/lisp/leim/quail/emoji.el
@@ -1,6 +1,6 @@
 ;;; emoji.el --- Quail package for emoji character composition -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Juri Linkov <juri@linkov.net>
 ;; Keywords: multilingual, input method, i18n
diff --git a/lisp/leim/quail/georgian.el b/lisp/leim/quail/georgian.el
index 54501c80bd6..d3a21107ce8 100644
--- a/lisp/leim/quail/georgian.el
+++ b/lisp/leim/quail/georgian.el
@@ -1,6 +1,6 @@
 ;;; georgian.el --- Quail package for inputting Georgian characters  -*- 
coding: utf-8; lexical-binding:t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: i18n
diff --git a/lisp/leim/quail/greek.el b/lisp/leim/quail/greek.el
index 0829097af5f..7cf839f2f58 100644
--- a/lisp/leim/quail/greek.el
+++ b/lisp/leim/quail/greek.el
@@ -1,6 +1,6 @@
 ;;; greek.el --- Quail package for inputting Greek -*- coding: utf-8; 
lexical-binding:t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/hangul.el b/lisp/leim/quail/hangul.el
index f399a20a41c..79526fa5aa8 100644
--- a/lisp/leim/quail/hangul.el
+++ b/lisp/leim/quail/hangul.el
@@ -1,6 +1,6 @@
 ;;; hangul.el --- Korean Hangul input method  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Jihyun Cho <jihyun.jo@gmail.com>
 ;; Keywords: multilingual, input method, Korean, Hangul
diff --git a/lisp/leim/quail/hanja.el b/lisp/leim/quail/hanja.el
index 5aa76ad1e82..644c4c3eb53 100644
--- a/lisp/leim/quail/hanja.el
+++ b/lisp/leim/quail/hanja.el
@@ -1,6 +1,6 @@
 ;;; hanja.el --- Quail-package for Korean Hanja (KSC5601)  -*-coding: utf-8; 
lexical-binding: t -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/hanja3.el b/lisp/leim/quail/hanja3.el
index 7b5caa66615..cfcda4fb274 100644
--- a/lisp/leim/quail/hanja3.el
+++ b/lisp/leim/quail/hanja3.el
@@ -1,6 +1,6 @@
 ;;; hanja3.el --- Quail-package for Korean Hanja (KSC5601)  -*-coding: utf-8; 
lexical-binding: t -*-
 
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Koaunghi Un <koaunghi.un@zdv.uni-tuebingen.de>
 ;; Keywords: mule, quail, multilingual, input method, Korean, Hanja
diff --git a/lisp/leim/quail/indian.el b/lisp/leim/quail/indian.el
index 70ea9290662..9ea23ec087c 100644
--- a/lisp/leim/quail/indian.el
+++ b/lisp/leim/quail/indian.el
@@ -1,6 +1,6 @@
 ;;; indian.el --- Quail packages for inputting Indian  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: KAWABATA, Taichi <kawabata@m17n.org>
 
@@ -476,7 +476,7 @@ Full key sequences are listed below:"
 (defgroup tamil-input nil
   "Translation rules for the Tamil input method."
   :prefix "tamil-"
-  :group 'leim)
+  :group 'quail)
 
 (defcustom tamil-translation-rules
   ;; Vowels.
diff --git a/lisp/leim/quail/indonesian.el b/lisp/leim/quail/indonesian.el
index 6da2e9a6e86..f486d86479a 100644
--- a/lisp/leim/quail/indonesian.el
+++ b/lisp/leim/quail/indonesian.el
@@ -1,6 +1,6 @@
 ;;; indonesian.el --- Quail package for inputting Indonesian characters  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
 ;; Keywords: multilingual, input method, i18n, Indonesia
diff --git a/lisp/leim/quail/ipa-praat.el b/lisp/leim/quail/ipa-praat.el
index 58d2f5e55fb..be8115e006a 100644
--- a/lisp/leim/quail/ipa-praat.el
+++ b/lisp/leim/quail/ipa-praat.el
@@ -1,6 +1,6 @@
 ;;; ipa-praat.el --- Inputting IPA characters with the conventions of Praat  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Oliver Scholz <epameinondas@gmx.de>
 ;; Keywords: multilingual, input method, IPA
diff --git a/lisp/leim/quail/ipa.el b/lisp/leim/quail/ipa.el
index 704d18ddc5f..a6a012fd434 100644
--- a/lisp/leim/quail/ipa.el
+++ b/lisp/leim/quail/ipa.el
@@ -1,6 +1,6 @@
 ;;; ipa.el --- Quail package for inputting IPA characters  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/japanese.el b/lisp/leim/quail/japanese.el
index 1caaf9d93da..c3dabd68fcd 100644
--- a/lisp/leim/quail/japanese.el
+++ b/lisp/leim/quail/japanese.el
@@ -1,6 +1,6 @@
 ;;; japanese.el --- Quail package for inputting Japanese  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/latin-alt.el b/lisp/leim/quail/latin-alt.el
index e269a47fb02..6d3731ba264 100644
--- a/lisp/leim/quail/latin-alt.el
+++ b/lisp/leim/quail/latin-alt.el
@@ -1,6 +1,6 @@
 ;;; latin-alt.el --- Quail package for inputting various European characters 
-*-coding: utf-8; lexical-binding: t -*-
 
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
 ;;   2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/latin-ltx.el b/lisp/leim/quail/latin-ltx.el
index 9be3d722504..54c3121873e 100644
--- a/lisp/leim/quail/latin-ltx.el
+++ b/lisp/leim/quail/latin-ltx.el
@@ -1,6 +1,6 @@
 ;;; latin-ltx.el --- Quail package for TeX-style input -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
 ;;   2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/latin-post.el b/lisp/leim/quail/latin-post.el
index 453bea49026..0d2c1888426 100644
--- a/lisp/leim/quail/latin-post.el
+++ b/lisp/leim/quail/latin-post.el
@@ -1,6 +1,6 @@
 ;;; latin-post.el --- Quail packages for inputting various European characters 
 -*-coding: utf-8; lexical-binding: t -*-
 
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/latin-pre.el b/lisp/leim/quail/latin-pre.el
index fd38084e645..91164df0c72 100644
--- a/lisp/leim/quail/latin-pre.el
+++ b/lisp/leim/quail/latin-pre.el
@@ -1,6 +1,6 @@
 ;;; latin-pre.el --- Quail packages for inputting various European characters  
-*-coding: utf-8; lexical-binding: t -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/lrt.el b/lisp/leim/quail/lrt.el
index 4e45a951d9f..aa16e5a0982 100644
--- a/lisp/leim/quail/lrt.el
+++ b/lisp/leim/quail/lrt.el
@@ -1,6 +1,6 @@
 ;;; lrt.el --- Quail package for inputting Lao characters by LRT method  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/misc-lang.el b/lisp/leim/quail/misc-lang.el
index e40bccc14f0..fc8fa79243b 100644
--- a/lisp/leim/quail/misc-lang.el
+++ b/lisp/leim/quail/misc-lang.el
@@ -1,6 +1,6 @@
 ;;; misc-lang.el --- Quail package for inputting Miscellaneous characters  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
 ;; Keywords: multilingual, input method, i18n, Miscellaneous
diff --git a/lisp/leim/quail/pakistan.el b/lisp/leim/quail/pakistan.el
index ff9257722e0..7cde2fde3aa 100644
--- a/lisp/leim/quail/pakistan.el
+++ b/lisp/leim/quail/pakistan.el
@@ -1,6 +1,6 @@
 ;;; pakistan.el --- Input methods for some languages from Pakistan -*- 
lexical-binding: t; -*-
 ;;
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: Rahguzar <rahguzar@zohomail.eu>
 ;; Keywords: convenience, multilingual, input method, Urdu, Balochi, Pashto, 
Sindhi, Hindko, Brahui
diff --git a/lisp/leim/quail/persian.el b/lisp/leim/quail/persian.el
index 758d2951292..676b3ab5c2e 100644
--- a/lisp/leim/quail/persian.el
+++ b/lisp/leim/quail/persian.el
@@ -1,6 +1,6 @@
 ;;; persian.el --- Quail package for inputting Persian/Farsi keyboard  -*- 
coding: utf-8; lexical-binding: t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Mohsen BANAN <emacs@mohsen.1.banan.byname.net>
 ;; URL: http://mohsen.1.banan.byname.net/contact
@@ -500,7 +500,7 @@
  ;; RIGHT-TO-LEFT EMBEDDING (sets base dir to RTL but allows embedded text)
  ("&rle;" ?\u202B)   ;; (ucs-insert #x202B)   named: زیرمتنِ راست‌به‌چپ
  ;; POP DIRECTIONAL FORMATTING (used for RLE or LRE and RLO or LRO)
- ;; EMACS ANOMOLY --- Why does &pdf not show up in (describe-input-method 
'farsi-transliterate-banan)
+ ;; EMACS ANOMALY --- Why does &pdf not show up in (describe-input-method 
'farsi-transliterate-banan)
  ("&pdf;" ?\u202C)   ;; (ucs-insert #x202C)   named: پایانِ زیرمتن
  ("P" ?\u202C)
  ;; LEFT-TO-RIGHT OVERRIDE (overrides the bidirectional algorithm, display LTR)
diff --git a/lisp/leim/quail/philippine.el b/lisp/leim/quail/philippine.el
index 8ed6e570b7d..2d063e7b0a4 100644
--- a/lisp/leim/quail/philippine.el
+++ b/lisp/leim/quail/philippine.el
@@ -1,6 +1,6 @@
 ;;; philippine.el --- Quail package for inputting Philippine characters  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
 ;; Keywords: multilingual, input method, i18n, Philippines
diff --git a/lisp/leim/quail/programmer-dvorak.el 
b/lisp/leim/quail/programmer-dvorak.el
index eb12bd9dd22..719a85b0e51 100644
--- a/lisp/leim/quail/programmer-dvorak.el
+++ b/lisp/leim/quail/programmer-dvorak.el
@@ -1,6 +1,6 @@
 ;;; programmer-dvorak.el --- Quail package for the programmer Dvorak layout  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Joakim Jalap <joakim.jalap@fastmail.com>
 
diff --git a/lisp/leim/quail/py-punct.el b/lisp/leim/quail/py-punct.el
index 71ed55bd5f5..3cc6739ba0b 100644
--- a/lisp/leim/quail/py-punct.el
+++ b/lisp/leim/quail/py-punct.el
@@ -1,6 +1,6 @@
 ;;; py-punct.el --- Quail packages for Chinese (pinyin + extra symbols)  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/rfc1345.el b/lisp/leim/quail/rfc1345.el
index 0aba396b111..a635fd2568b 100644
--- a/lisp/leim/quail/rfc1345.el
+++ b/lisp/leim/quail/rfc1345.el
@@ -1,6 +1,6 @@
 ;;; rfc1345.el --- Quail method for RFC 1345 mnemonics -*- coding: utf-8; 
lexical-binding: t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: i18n
diff --git a/lisp/leim/quail/sami.el b/lisp/leim/quail/sami.el
index 7e878f780fc..8620577c968 100644
--- a/lisp/leim/quail/sami.el
+++ b/lisp/leim/quail/sami.el
@@ -1,6 +1,6 @@
 ;;; sami.el --- Quail package for inputting Sámi  -*-coding: utf-8; 
lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Wojciech S. Gac <wojciech.s.gac@gmail.com>
 ;; Keywords: i18n, multilingual, input method, Sámi
diff --git a/lisp/leim/quail/sgml-input.el b/lisp/leim/quail/sgml-input.el
index 66f6658db3e..c411d781a2f 100644
--- a/lisp/leim/quail/sgml-input.el
+++ b/lisp/leim/quail/sgml-input.el
@@ -1,6 +1,6 @@
 ;;; sgml-input.el --- Quail method for Unicode entered as SGML entities -*- 
coding: utf-8; lexical-binding: t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: i18n
diff --git a/lisp/leim/quail/sisheng.el b/lisp/leim/quail/sisheng.el
index 0961799c4ac..2f6db572b99 100644
--- a/lisp/leim/quail/sisheng.el
+++ b/lisp/leim/quail/sisheng.el
@@ -1,6 +1,6 @@
 ;;; sisheng.el --- sisheng input method for Chinese pinyin transliteration  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Werner LEMBERG <wl@gnu.org>
 
diff --git a/lisp/leim/quail/slovak.el b/lisp/leim/quail/slovak.el
index 8996575fe78..dc0591f4f84 100644
--- a/lisp/leim/quail/slovak.el
+++ b/lisp/leim/quail/slovak.el
@@ -1,6 +1,6 @@
 ;;; slovak.el --- Quail package for inputting Slovak  -*-coding: utf-8; 
lexical-binding: t -*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Authors: Tibor Šimko <tibor.simko@fmph.uniba.sk>
 ;;          Milan Zamazal <pdm@zamazal.org>
diff --git a/lisp/leim/quail/symbol-ksc.el b/lisp/leim/quail/symbol-ksc.el
index 7588922dc07..78334055127 100644
--- a/lisp/leim/quail/symbol-ksc.el
+++ b/lisp/leim/quail/symbol-ksc.el
@@ -1,6 +1,6 @@
 ;;; symbol-ksc.el --- Quail-package for Korean Symbol (KSC5601) -*-coding: 
utf-8; lexical-binding: t -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/tamil-dvorak.el b/lisp/leim/quail/tamil-dvorak.el
index 7b4be6b7a43..7d8f7969d45 100644
--- a/lisp/leim/quail/tamil-dvorak.el
+++ b/lisp/leim/quail/tamil-dvorak.el
@@ -1,6 +1,6 @@
 ;;; tamil-dvorak.el --- Quail package for Tamil input with Dvorak keyboard  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Shakthi Kannan <author@shakthimaan.com>
 
diff --git a/lisp/leim/quail/tibetan.el b/lisp/leim/quail/tibetan.el
index d28d7be3b95..1cc7c22d12c 100644
--- a/lisp/leim/quail/tibetan.el
+++ b/lisp/leim/quail/tibetan.el
@@ -1,6 +1,6 @@
 ;;; tibetan.el --- Quail package for inputting Tibetan characters -*-coding: 
utf-8-emacs; lexical-binding: t; -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 ;;   2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/uni-input.el b/lisp/leim/quail/uni-input.el
index 46cc5d043fc..59ac47fffac 100644
--- a/lisp/leim/quail/uni-input.el
+++ b/lisp/leim/quail/uni-input.el
@@ -1,6 +1,6 @@
 ;;; uni-input.el --- Hex Unicode input method  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
 ;;   Registration Number H14PRO021
diff --git a/lisp/leim/quail/vntelex.el b/lisp/leim/quail/vntelex.el
index 4f412090cfc..d37baa4007c 100644
--- a/lisp/leim/quail/vntelex.el
+++ b/lisp/leim/quail/vntelex.el
@@ -1,6 +1,6 @@
 ;;; vntelex.el --- Quail package for Vietnamese by Telex method  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Werner Lemberg <wl@gnu.org>
 ;; Keywords: multilingual, input method, Vietnamese
diff --git a/lisp/leim/quail/vnvni.el b/lisp/leim/quail/vnvni.el
index b9b0f77e032..59d1a82eb21 100644
--- a/lisp/leim/quail/vnvni.el
+++ b/lisp/leim/quail/vnvni.el
@@ -1,6 +1,6 @@
 ;;; vnvni.el --- Quail package for Vietnamese by VNI method  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author:   Werner Lemberg <wl@gnu.org>
 ;;           Nguyen Thai Ngoc Duy <pclouds@gmail.com>
diff --git a/lisp/leim/quail/welsh.el b/lisp/leim/quail/welsh.el
index a7799b6e5c3..349667d2df0 100644
--- a/lisp/leim/quail/welsh.el
+++ b/lisp/leim/quail/welsh.el
@@ -1,6 +1,6 @@
 ;;; welsh.el --- Quail package for inputting Welsh characters  -*- coding: 
utf-8; lexical-binding: t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: i18n
diff --git a/lisp/loadhist.el b/lisp/loadhist.el
index 8a571661e89..ece95ed619b 100644
--- a/lisp/loadhist.el
+++ b/lisp/loadhist.el
@@ -1,6 +1,6 @@
 ;;; loadhist.el --- lisp functions for working with feature groups  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric S. Raymond <esr@thyrsus.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/loadup.el b/lisp/loadup.el
index 4d3fafb8140..f2f0897853c 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -1,6 +1,6 @@
 ;;; loadup.el --- load up standardly loaded Lisp files for Emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1985-1986, 1992, 1994, 2001-2023 Free Software
+;; Copyright (C) 1985-1986, 1992, 1994, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -376,12 +376,9 @@
 (if (featurep 'dynamic-setting)
     (load "dynamic-setting"))
 
-;; touch-screen.el is tiny and is used liberally throughout the button
-;; code etc, so it may as well be preloaded everywhere.
-(load "touch-screen")
-
 (if (featurep 'x)
     (progn
+      (load "touch-screen")
       (load "x-dnd")
       (load "term/common-win")
       (load "term/x-win")))
@@ -394,6 +391,7 @@
 (if (featurep 'android)
     (progn
       (load "ls-lisp")
+      (load "touch-screen")
       (load "term/common-win")
       (load "term/android-win")))
 
@@ -467,6 +465,9 @@
     (load "tooltip"))
 (load "international/iso-transl") ; Binds Alt-[ and friends.
 
+;; Used by `kill-buffer', for instance.
+(load "emacs-lisp/rmc")
+
 ;; This file doesn't exist when building a development version of Emacs
 ;; from the repository.  It is generated just after temacs is built.
 (load "leim/leim-list.el" t)
@@ -486,8 +487,17 @@
       (message "Warning: Change in load-path due to site-load will be \
 lost after dumping")))
 
-;; Used by `kill-buffer', for instance.
-(load "emacs-lisp/rmc")
+;; Actively check for advised functions during preload since:
+;; - advices in Emacs's core are generally considered bad style;
+;; - `Snarf-documentation' looses docstrings of primitives advised
+;;   during preload (bug#66032#20).
+(mapatoms
+ (lambda (f)
+   (and (advice--p (symbol-function f))
+        ;; Don't make it an error because it's not serious enough and
+        ;; it can be annoying during development.  Also there are still
+        ;; circumstances where we use advice on preloaded functions.
+        (message "Warning: Advice installed on preloaded function %S" f))))
 
 ;; Make sure default-directory is unibyte when dumping.  This is
 ;; because we cannot decode and encode it correctly (since the locale
@@ -587,9 +597,9 @@ This to have it working when installed or if Emacs source
 directory got moved.  This is set to be a pair in the form of:
 \(rel-filename-from-install-bin . rel-filename-from-local-bin)."
   (when (and load--bin-dest-dir load--eln-dest-dir)
-    (setq eln-dest-dir
+      (setq eln-dest-dir
           (concat load--eln-dest-dir "native-lisp/" comp-native-version-dir 
"/"))
-    (maphash (lambda (_ cu)
+      (maphash (lambda (_ cu)
                (when (stringp (native-comp-unit-file cu))
                  (let* ((file (native-comp-unit-file cu))
                         (preloaded (equal (substring (file-name-directory file)
@@ -615,7 +625,7 @@ directory got moved.  This is set to be a pair in the form 
of:
 (defvar comp-subr-arities-h)
 (when (featurep 'native-compile)
   ;; Save the arity for all primitives so the compiler can always
-  ;; retrive it even in case of redefinition.
+  ;; retrieve it even in case of redefinition.
   (mapatoms (lambda (f)
               (when (subr-primitive-p (symbol-function f))
                 (puthash f (func-arity f) comp-subr-arities-h))))
diff --git a/lisp/locate.el b/lisp/locate.el
index caccf644c02..d86e7fa678f 100644
--- a/lisp/locate.el
+++ b/lisp/locate.el
@@ -1,6 +1,6 @@
 ;;; locate.el --- interface to the locate command  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Peter Breton <pbreton@cs.umb.edu>
 ;; Keywords: unix files
diff --git a/lisp/lpr.el b/lisp/lpr.el
index 6b8343b695d..c860c633b73 100644
--- a/lisp/lpr.el
+++ b/lisp/lpr.el
@@ -1,6 +1,6 @@
 ;;; lpr.el --- print Emacs buffer on line printer  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985, 1988, 1992, 1994, 2001-2023 Free Software
+;; Copyright (C) 1985, 1988, 1992, 1994, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el
index c576819c5d0..89f0238cf74 100644
--- a/lisp/ls-lisp.el
+++ b/lisp/ls-lisp.el
@@ -1,6 +1,6 @@
 ;;; ls-lisp.el --- emulate insert-directory completely in Emacs Lisp  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1992, 1994, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1994, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
 ;; Modified by: Francis J. Wright <F.J.Wright@maths.qmw.ac.uk>
@@ -249,89 +249,69 @@ to fail to line up, e.g. if month names are not all of 
the same length."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defun ls-lisp--insert-directory (orig-fun file switches &optional wildcard 
full-directory-p)
+(defun ls-lisp--insert-directory (file switches wildcard full-directory-p)
   "Insert directory listing for FILE, formatted according to SWITCHES.
-Leaves point after the inserted text.
-SWITCHES may be a string of options, or a list of strings.
-Optional third arg WILDCARD means treat FILE as shell wildcard.
-Optional fourth arg FULL-DIRECTORY-P means file is a directory and
-switches do not contain `d', so that a full listing is expected.
-
-This version of the function comes from `ls-lisp.el'.
-If the value of `ls-lisp-use-insert-directory-program' is non-nil then
-this advice just delegates the work to ORIG-FUN (the normal `insert-directory'
-function from `files.el').
-But if the value of `ls-lisp-use-insert-directory-program' is nil
-then it runs a Lisp emulation.
-
-The Lisp emulation does not run any external programs or shells.  It
-supports ordinary shell wildcards if `ls-lisp-support-shell-wildcards'
+This implementation of `insert-directory' works using Lisp functions rather
+than `insert-directory-program'.
+
+This Lisp emulation does not run any external programs or shells.
+ It supports ordinary shell wildcards if `ls-lisp-support-shell-wildcards'
 is non-nil; otherwise, it interprets wildcards as regular expressions
 to match file names.  It does not support all `ls' switches -- those
 that work are: A a B C c F G g h i n R r S s t U u v X.  The l switch
 is assumed to be always present and cannot be turned off.
 Long variants of the above switches, as documented for GNU `ls',
 are also supported; unsupported long options are silently ignored."
-  (if ls-lisp-use-insert-directory-program
-      (funcall orig-fun
-              file switches wildcard full-directory-p)
-    ;; We need the directory in order to find the right handler.
-    (setq switches (or switches ""))
-    (let ((handler (find-file-name-handler (expand-file-name file)
-                                          'insert-directory))
-         (orig-file file)
-         wildcard-regexp
-         (ls-lisp-dirs-first
-           (or ls-lisp-dirs-first
-               (string-match "--group-directories-first" switches))))
-      (if handler
-         (funcall handler 'insert-directory file switches
-                  wildcard full-directory-p)
-        (when (string-match "--group-directories-first" switches)
-            ;; if ls-lisp-dirs-first is nil, dirs are grouped but come out in
-            ;; reverse order:
-            (setq ls-lisp-dirs-first t)
-            (setq switches (replace-match "" nil nil switches)))
-       ;; Remove unrecognized long options, and convert the
-       ;; recognized ones to their short variants.
-        (setq switches (ls-lisp--sanitize-switches switches))
-       ;; Convert SWITCHES to a list of characters.
-       (setq switches (delete ?\  (delete ?- (append switches nil))))
-       ;; Sometimes we get ".../foo*/" as FILE.  While the shell and
-       ;; `ls' don't mind, we certainly do, because it makes us think
-       ;; there is no wildcard, only a directory name.
-       (if (and ls-lisp-support-shell-wildcards
-                (string-match "[[?*]" file)
-                ;; Prefer an existing file to wildcards, like
-                ;; dired-noselect does.
-                (not (file-exists-p file)))
-           (progn
-             (or (not (eq (aref file (1- (length file))) ?/))
-                 (setq file (substring file 0 (1- (length file)))))
-             (setq wildcard t)))
-       (if wildcard
-           (setq wildcard-regexp
-                 (if ls-lisp-support-shell-wildcards
-                     (wildcard-to-regexp (file-name-nondirectory file))
-                   (file-name-nondirectory file))
-                 file (file-name-directory file))
-         (if (memq ?B switches) (setq wildcard-regexp "[^~]\\'")))
-       (condition-case err
-           (ls-lisp-insert-directory
-            file switches (ls-lisp-time-index switches)
-            wildcard-regexp full-directory-p)
-         (invalid-regexp
-          ;; Maybe they wanted a literal file that just happens to
-          ;; use characters special to shell wildcards.
-          (if (equal (cadr err) "Unmatched [ or [^")
-              (progn
-                (setq wildcard-regexp (if (memq ?B switches) "[^~]\\'")
-                      file (file-relative-name orig-file))
-                (ls-lisp-insert-directory
-                 file switches (ls-lisp-time-index switches)
-                 nil full-directory-p))
-            (signal (car err) (cdr err)))))))))
-(advice-add 'insert-directory :around #'ls-lisp--insert-directory)
+  (setq switches (or switches ""))
+  (let ((orig-file file)
+       wildcard-regexp
+       (ls-lisp-dirs-first
+         (or ls-lisp-dirs-first
+             (string-match "--group-directories-first" switches))))
+    (when (string-match "--group-directories-first" switches)
+      ;; if ls-lisp-dirs-first is nil, dirs are grouped but come out in
+      ;; reverse order:
+      (setq ls-lisp-dirs-first t)
+      (setq switches (replace-match "" nil nil switches)))
+    ;; Remove unrecognized long options, and convert the
+    ;; recognized ones to their short variants.
+    (setq switches (ls-lisp--sanitize-switches switches))
+    ;; Convert SWITCHES to a list of characters.
+    (setq switches (delete ?\  (delete ?- (append switches nil))))
+    ;; Sometimes we get ".../foo*/" as FILE.  While the shell and
+    ;; `ls' don't mind, we certainly do, because it makes us think
+    ;; there is no wildcard, only a directory name.
+    (if (and ls-lisp-support-shell-wildcards
+            (string-match "[[?*]" file)
+            ;; Prefer an existing file to wildcards, like
+            ;; dired-noselect does.
+            (not (file-exists-p file)))
+       (progn
+         (or (not (eq (aref file (1- (length file))) ?/))
+             (setq file (substring file 0 (1- (length file)))))
+         (setq wildcard t)))
+    (if wildcard
+       (setq wildcard-regexp
+             (if ls-lisp-support-shell-wildcards
+                 (wildcard-to-regexp (file-name-nondirectory file))
+               (file-name-nondirectory file))
+             file (file-name-directory file))
+      (if (memq ?B switches) (setq wildcard-regexp "[^~]\\'")))
+    (condition-case err
+       (ls-lisp-insert-directory
+        file switches (ls-lisp-time-index switches)
+        wildcard-regexp full-directory-p)
+      (invalid-regexp
+       ;; Maybe they wanted a literal file that just happens to
+       ;; use characters special to shell wildcards.
+       (if (equal (cadr err) "Unmatched [ or [^")
+          (progn
+            (setq wildcard-regexp (if (memq ?B switches) "[^~]\\'")
+                  file (file-relative-name orig-file))
+            (ls-lisp-insert-directory
+             file switches (ls-lisp-time-index switches)
+             nil full-directory-p))
+        (signal (car err) (cdr err)))))))
 
 (defun ls-lisp-insert-directory
   (file switches time-index wildcard-regexp full-directory-p)
@@ -469,50 +449,6 @@ not contain `d', so that a full listing is expected."
                       "Directory doesn't exist or is inaccessible"
                       file))))))
 
-(declare-function dired-read-dir-and-switches "dired" (str))
-(declare-function dired-goto-next-file "dired" ())
-
-(defun ls-lisp--dired (orig-fun dir-or-list &optional switches)
-  (interactive (dired-read-dir-and-switches ""))
-  (unless dir-or-list
-    (setq dir-or-list default-directory))
-  (if (consp dir-or-list)
-      (funcall orig-fun dir-or-list switches)
-    (let ((dir-wildcard (insert-directory-wildcard-in-dir-p
-                         (expand-file-name dir-or-list))))
-      (if (not dir-wildcard)
-          (funcall orig-fun dir-or-list switches)
-        (let* ((default-directory (car dir-wildcard))
-               (wildcard (cdr dir-wildcard))
-               (files (file-expand-wildcards wildcard))
-               (dir (car dir-wildcard)))
-          ;; When the wildcard ends in a slash, file-expand-wildcards
-          ;; returns nil; fix that by treating the wildcards as
-          ;; specifying only directories whose names match the
-          ;; widlcard.
-          (if (and (null files)
-                   (directory-name-p wildcard))
-              (setq files
-                    (delq nil
-                          (mapcar (lambda (fname)
-                                   (if (file-accessible-directory-p fname)
-                                        fname))
-                                 (file-expand-wildcards
-                                   (directory-file-name wildcard))))))
-          (if files
-              (let ((inhibit-read-only t)
-                    (buf
-                     (apply orig-fun (nconc (list dir) files) (and switches 
(list switches)))))
-                (with-current-buffer buf
-                  (save-excursion
-                    (goto-char (point-min))
-                    (dired-goto-next-file)
-                    (forward-line 0)
-                    (insert "  wildcard " (cdr dir-wildcard) "\n"))))
-            (user-error "No files matching wildcard")))))))
-
-(advice-add 'dired :around #'ls-lisp--dired)
-
 (defun ls-lisp-sanitize (file-alist)
   "Sanitize the elements in FILE-ALIST.
 Fixes any elements in the alist for directory entries whose file
@@ -900,13 +836,6 @@ All ls time options, namely c, t and u, are handled."
              file-size)
     (format " %7s" (file-size-human-readable file-size))))
 
-(defun ls-lisp-unload-function ()
-  "Unload ls-lisp library."
-  (advice-remove 'insert-directory #'ls-lisp--insert-directory)
-  (advice-remove 'dired #'ls-lisp--dired)
-  ;; Continue standard unloading.
-  nil)
-
 (defun ls-lisp--sanitize-switches (switches)
   "Convert long options of GNU \"ls\" to their short form.
 Conversion is done only for flags supported by ls-lisp.
diff --git a/lisp/macros.el b/lisp/macros.el
index 98ee3dc52f9..7108a027ca6 100644
--- a/lisp/macros.el
+++ b/lisp/macros.el
@@ -1,6 +1,6 @@
 ;;; macros.el --- non-primitive commands for keyboard macros -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1985-1987, 1992, 1994-1995, 2001-2023 Free Software
+;; Copyright (C) 1985-1987, 1992, 1994-1995, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -197,7 +197,7 @@ For example, in Usenet articles, sections of text quoted 
from another
 author are indented, or have each line start with `>'.  To quote a
 section of text, define a keyboard macro which inserts `>', put point
 and mark at opposite ends of the quoted section, and use
-`\\[apply-macro-to-region-lines]' to mark the entire section.
+\\[apply-macro-to-region-lines] to mark the entire section.
 
 Suppose you wanted to build a keyword table in C where each entry
 looked like this:
@@ -219,7 +219,7 @@ and write a macro to massage a word into a table entry:
     \\C-x )
 
 and then select the region of un-tablified names and use
-`\\[apply-macro-to-region-lines]' to build the table from the names."
+\\[apply-macro-to-region-lines] to build the table from the names."
   (interactive "r")
   (or macro
       (progn
diff --git a/lisp/mail/binhex.el b/lisp/mail/binhex.el
index 15f598fa224..2eac5dacc77 100644
--- a/lisp/mail/binhex.el
+++ b/lisp/mail/binhex.el
@@ -1,6 +1,6 @@
 ;;; binhex.el --- decode BinHex-encoded text  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
 ;; Keywords: binhex news
diff --git a/lisp/mail/blessmail.el b/lisp/mail/blessmail.el
index a9f9828926c..47e9bb58e06 100644
--- a/lisp/mail/blessmail.el
+++ b/lisp/mail/blessmail.el
@@ -1,6 +1,6 @@
 ;;; blessmail.el --- decide whether movemail needs special privileges -*- 
no-byte-compile: t; lexical-binding: t; -*-
 
-;; Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
diff --git a/lisp/mail/emacsbug.el b/lisp/mail/emacsbug.el
index 409ef7165fe..e89e66cc7cb 100644
--- a/lisp/mail/emacsbug.el
+++ b/lisp/mail/emacsbug.el
@@ -1,6 +1,6 @@
 ;;; emacsbug.el --- command to report Emacs bugs to appropriate mailing list  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Author: K. Shane Hartman
 ;; Maintainer: emacs-devel@gnu.org
@@ -233,9 +233,11 @@ Already submitted bugs can be found in the Emacs bug 
tracker:
           (set-frame-parameter nil 'unsplittable nil))
       (error nil))
     (compose-mail report-emacs-bug-address topic)
+    (rfc822-goto-eoh)
+    (insert "X-Debbugs-Cc: \n")
     ;; The rest of this does not execute if the user was asked to
     ;; confirm and said no.
-    (when (eq major-mode 'message-mode)
+    (when (derived-mode-p 'message-mode)
       ;; Message-mode sorts the headers before sending.  We sort now so
       ;; that report-emacs-bug-orig-text remains valid.  (Bug#5178)
       (message-sort-headers)
diff --git a/lisp/mail/flow-fill.el b/lisp/mail/flow-fill.el
index 7136e186ff1..919490ec5aa 100644
--- a/lisp/mail/flow-fill.el
+++ b/lisp/mail/flow-fill.el
@@ -1,6 +1,6 @@
 ;;; flow-fill.el --- interpret RFC2646 "flowed" text  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <jas@pdc.kth.se>
 ;; Keywords: mail
diff --git a/lisp/mail/footnote.el b/lisp/mail/footnote.el
index 4b2770ee3a1..dda099ac013 100644
--- a/lisp/mail/footnote.el
+++ b/lisp/mail/footnote.el
@@ -1,6 +1,6 @@
 ;;; footnote.el --- footnote support for message mode  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Steven L Baur <steve@xemacs.org> (1997-2011)
 ;;         Boruch Baum <boruch_baum@gmx.com> (2017-)
diff --git a/lisp/mail/hashcash.el b/lisp/mail/hashcash.el
index ecc03bfb537..cf7ad006c31 100644
--- a/lisp/mail/hashcash.el
+++ b/lisp/mail/hashcash.el
@@ -1,6 +1,6 @@
 ;;; hashcash.el --- Add hashcash payments to email  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Written by: Paul Foley <mycroft@actrix.gen.nz> (1997-2002)
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/ietf-drums-date.el b/lisp/mail/ietf-drums-date.el
index 68ba88e89ec..ef8e9f8f32e 100644
--- a/lisp/mail/ietf-drums-date.el
+++ b/lisp/mail/ietf-drums-date.el
@@ -1,6 +1,6 @@
 ;;; ietf-drums-date.el --- parse time/date for ietf-drums.el -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Bob Rogers <rogers@rgrjr.com>
 ;; Package: ietf-drums
diff --git a/lisp/mail/ietf-drums.el b/lisp/mail/ietf-drums.el
index aa714292bcc..eaccbff0b13 100644
--- a/lisp/mail/ietf-drums.el
+++ b/lisp/mail/ietf-drums.el
@@ -1,6 +1,6 @@
 ;;; ietf-drums.el --- Functions for parsing RFC 2822 headers  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
diff --git a/lisp/mail/mail-extr.el b/lisp/mail/mail-extr.el
index 71621f588e7..668cae05521 100644
--- a/lisp/mail/mail-extr.el
+++ b/lisp/mail/mail-extr.el
@@ -1,6 +1,6 @@
 ;;; mail-extr.el --- extract full name and address from email header  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
 
 ;; Author: Joe Wells <jbw@cs.bu.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/mail-hist.el b/lisp/mail/mail-hist.el
index 40be8d0f350..01ea5bb9617 100644
--- a/lisp/mail/mail-hist.el
+++ b/lisp/mail/mail-hist.el
@@ -1,6 +1,6 @@
 ;;; mail-hist.el --- headers and message body history for outgoing mail  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Karl Fogel <kfogel@red-bean.com>
 ;; Created: March, 1994
diff --git a/lisp/mail/mail-parse.el b/lisp/mail/mail-parse.el
index 7a6b351bff3..efaecc37b7d 100644
--- a/lisp/mail/mail-parse.el
+++ b/lisp/mail/mail-parse.el
@@ -1,6 +1,6 @@
 ;;; mail-parse.el --- Interface functions for parsing mail  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
diff --git a/lisp/mail/mail-prsvr.el b/lisp/mail/mail-prsvr.el
index 1487c32e9ed..7a261e64b24 100644
--- a/lisp/mail/mail-prsvr.el
+++ b/lisp/mail/mail-prsvr.el
@@ -1,6 +1,6 @@
 ;;; mail-prsvr.el --- Interface variables for parsing mail  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
diff --git a/lisp/mail/mail-utils.el b/lisp/mail/mail-utils.el
index a6a4545cf04..c9e4d0b3812 100644
--- a/lisp/mail/mail-utils.el
+++ b/lisp/mail/mail-utils.el
@@ -1,6 +1,6 @@
 ;;; mail-utils.el --- utility functions used both by rmail and rnews  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: mail, news
diff --git a/lisp/mail/mailabbrev.el b/lisp/mail/mailabbrev.el
index 8b95820cdf8..68d325ea261 100644
--- a/lisp/mail/mailabbrev.el
+++ b/lisp/mail/mailabbrev.el
@@ -1,6 +1,6 @@
 ;;; mailabbrev.el --- abbrev-expansion of mail aliases  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1985-1987, 1992-1993, 1996-1997, 2000-2023 Free
+;; Copyright (C) 1985-1987, 1992-1993, 1996-1997, 2000-2024 Free
 ;; Software Foundation, Inc.
 
 ;; Author: Jamie Zawinski <jwz@lucid.com; now jwz@jwz.org>
diff --git a/lisp/mail/mailalias.el b/lisp/mail/mailalias.el
index e3e4122039b..cce2fcb104d 100644
--- a/lisp/mail/mailalias.el
+++ b/lisp/mail/mailalias.el
@@ -1,6 +1,6 @@
 ;;; mailalias.el --- expand and complete mailing address aliases -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985, 1987, 1995-1997, 2001-2023 Free Software
+;; Copyright (C) 1985, 1987, 1995-1997, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/mailclient.el b/lisp/mail/mailclient.el
index 613541e5dc4..1233d9ace95 100644
--- a/lisp/mail/mailclient.el
+++ b/lisp/mail/mailclient.el
@@ -1,6 +1,6 @@
 ;;; mailclient.el --- mail sending via system's mail client.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: David Reitter <david.reitter@gmail.com>
 ;; Keywords: mail
diff --git a/lisp/mail/mailheader.el b/lisp/mail/mailheader.el
index 92ea13a11f1..fd212d35a57 100644
--- a/lisp/mail/mailheader.el
+++ b/lisp/mail/mailheader.el
@@ -1,6 +1,6 @@
 ;;; mailheader.el --- mail header parsing, merging, formatting  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Erik Naggum <erik@naggum.no>
 ;; Keywords: tools, mail, news
diff --git a/lisp/mail/mspools.el b/lisp/mail/mspools.el
index b5e4efa6be8..d20bab206c4 100644
--- a/lisp/mail/mspools.el
+++ b/lisp/mail/mspools.el
@@ -1,6 +1,6 @@
 ;;; mspools.el --- show mail spools waiting to be read  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Stephen Eglen <stephen@gnu.org>
 ;; Created: 22 Jan 1997
diff --git a/lisp/mail/qp.el b/lisp/mail/qp.el
index 08f843e28f8..9e92eb635d2 100644
--- a/lisp/mail/qp.el
+++ b/lisp/mail/qp.el
@@ -1,6 +1,6 @@
 ;;; qp.el --- Quoted-Printable functions  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: mail, extensions
diff --git a/lisp/mail/reporter.el b/lisp/mail/reporter.el
index 1271be16151..c35d109b928 100644
--- a/lisp/mail/reporter.el
+++ b/lisp/mail/reporter.el
@@ -1,6 +1,6 @@
 ;;; reporter.el --- customizable bug reporting of lisp programs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author:          1993-1998 Barry A. Warsaw
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/rfc2045.el b/lisp/mail/rfc2045.el
index 123519ad777..0b498b306c1 100644
--- a/lisp/mail/rfc2045.el
+++ b/lisp/mail/rfc2045.el
@@ -1,6 +1,6 @@
 ;;; rfc2045.el --- Functions for decoding rfc2045 headers  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
diff --git a/lisp/mail/rfc2047.el b/lisp/mail/rfc2047.el
index b30a3779aa7..e122fe8c9b5 100644
--- a/lisp/mail/rfc2047.el
+++ b/lisp/mail/rfc2047.el
@@ -1,6 +1,6 @@
 ;;; rfc2047.el --- functions for encoding and decoding rfc2047 messages  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;     MORIOKA Tomohiko <morioka@jaist.ac.jp>
diff --git a/lisp/mail/rfc2231.el b/lisp/mail/rfc2231.el
index 8c156927589..33324cafb5b 100644
--- a/lisp/mail/rfc2231.el
+++ b/lisp/mail/rfc2231.el
@@ -1,6 +1,6 @@
 ;;; rfc2231.el --- Functions for decoding rfc2231 headers  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
diff --git a/lisp/mail/rfc6068.el b/lisp/mail/rfc6068.el
index a0d03ac7908..06fe92f0ca7 100644
--- a/lisp/mail/rfc6068.el
+++ b/lisp/mail/rfc6068.el
@@ -1,6 +1,6 @@
 ;;; rfc6068.el --- support for rfc6068  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Keywords: mail
 
diff --git a/lisp/mail/rfc822.el b/lisp/mail/rfc822.el
index 866e5d7a1cc..e0145c4043b 100644
--- a/lisp/mail/rfc822.el
+++ b/lisp/mail/rfc822.el
@@ -1,6 +1,6 @@
 ;;; rfc822.el --- hairy RFC 822 (or later) parser for mail, news, etc.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1986-1987, 1990, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1986-1987, 1990, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Richard Mlynarik <mly@eddie.mit.edu>
diff --git a/lisp/mail/rmail-spam-filter.el b/lisp/mail/rmail-spam-filter.el
index dd7fad0ad9c..98d54c25035 100644
--- a/lisp/mail/rmail-spam-filter.el
+++ b/lisp/mail/rmail-spam-filter.el
@@ -1,6 +1,6 @@
 ;;; rmail-spam-filter.el --- spam filter for Rmail, the Emacs mail reader  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 ;; Keywords: email, spam, filter, rmail
 ;; Author: Eli Tziperman <eli AT deas.harvard.edu>
 ;; Package: rmail
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el
index f76600000c9..85eaec33660 100644
--- a/lisp/mail/rmail.el
+++ b/lisp/mail/rmail.el
@@ -1,6 +1,7 @@
 ;;; rmail.el --- main code of "RMAIL" mail reader for Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1988, 1993-1998, 2000-2024 Free Software
+;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: mail
@@ -2711,7 +2712,9 @@ N defaults to the current message."
          (and (string-match text-regexp content-type-header) t)))))
 
 (defcustom rmail-show-message-verbose-min 200000
-  "Message size at which to show progress messages for displaying it."
+  "Message size at which to show progress messages for displaying it.
+Messages longer than this (in characters) will produce echo-area
+messages when Rmail processes such a message for display."
   :type 'integer
   :group 'rmail
   :version "23.1")
@@ -4610,6 +4613,16 @@ Argument MIME is non-nil if this is a mime message."
     ;; Decode any base64-encoded material in what we just decrypted.
     (rmail-epa-decode armor-start after-end)
 
+    ;; If this is in a MIME part, convert CRLF into just LF (newline)
+    (when mime
+      (save-restriction
+        (narrow-to-region armor-start  (- (point-max) after-end))
+        (goto-char (point-min))
+        (let ((inhibit-read-only t))
+          (while (search-forward "\r\n" nil t)
+            (delete-region (- (point) 2) (- (point) 1)))))
+      )
+
     (list armor-start (- (point-max) after-end) mime
           armor-end-regexp
           (buffer-substring armor-start (- (point-max) after-end)))))
@@ -4653,7 +4666,33 @@ Argument MIME is non-nil if this is a mime message."
              (push (rmail-epa-decrypt-1 mime) decrypts))))
 
       (when (and decrypts (rmail-buffers-swapped-p))
-       (when (y-or-n-p "Replace the original message? ")
+       (if (not (y-or-n-p "Replace the original message? "))
+            ;; User wants to decrypt only temporarily.
+           ;; Find, in the view buffer, the armors
+           ;; that we made decrypts for, and replace each one
+            ;; with its decrypt.  In a mime part, replace CRLF with NL.
+            (dolist (d decrypts)
+             (if (re-search-forward "-----BEGIN PGP MESSAGE-----$" nil t)
+                 (let (armor-start armor-end armor-end-regexp)
+                   (setq armor-start (match-beginning 0)
+                         armor-end-regexp (nth 3 d)
+                         armor-end (re-search-forward
+                                    armor-end-regexp
+                                    nil t))
+
+                   ;; Found as expected -- now replace it with the decrypt.
+                   (when armor-end
+                      (if (null (nth 2 d))
+                          nil
+                        ;; In a mime part --
+                        ;; replace CRLF with NL in it.
+                        (save-restriction
+                          (narrow-to-region armor-start armor-end)
+                          (goto-char (point-min))
+                          (while (search-forward "\r\n" nil t)
+                            (delete-region (- (point) 2) (- (point) 1))))))
+                     )))
+          ;; User wants to decrypt the message permanently.
           (when (eq major-mode 'rmail-mode)
             (rmail-add-label "decrypt"))
          (setq decrypts (nreverse decrypts))
diff --git a/lisp/mail/rmailedit.el b/lisp/mail/rmailedit.el
index b65777acc34..0c4b74c97da 100644
--- a/lisp/mail/rmailedit.el
+++ b/lisp/mail/rmailedit.el
@@ -1,6 +1,6 @@
 ;;; rmailedit.el --- "RMAIL edit mode"  Edit the current message  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1985, 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: mail
diff --git a/lisp/mail/rmailkwd.el b/lisp/mail/rmailkwd.el
index 82d91ff7870..d9c4cb8cfee 100644
--- a/lisp/mail/rmailkwd.el
+++ b/lisp/mail/rmailkwd.el
@@ -1,6 +1,6 @@
 ;;; rmailkwd.el --- part of the "RMAIL" mail reader for Emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1985, 1988, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985, 1988, 1994, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/rmailmm.el b/lisp/mail/rmailmm.el
index d2688118b97..422fe3a7227 100644
--- a/lisp/mail/rmailmm.el
+++ b/lisp/mail/rmailmm.el
@@ -1,6 +1,6 @@
 ;;; rmailmm.el --- MIME decoding and display stuff for RMAIL  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Alexander Pohoyda
 ;;     Alex Schroeder
diff --git a/lisp/mail/rmailmsc.el b/lisp/mail/rmailmsc.el
index b8258d584fc..01962bf79e0 100644
--- a/lisp/mail/rmailmsc.el
+++ b/lisp/mail/rmailmsc.el
@@ -1,6 +1,6 @@
 ;;; rmailmsc.el --- miscellaneous support functions for the RMAIL mail reader  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: mail
diff --git a/lisp/mail/rmailout.el b/lisp/mail/rmailout.el
index 6d61dcd8208..1aa430c18c9 100644
--- a/lisp/mail/rmailout.el
+++ b/lisp/mail/rmailout.el
@@ -1,6 +1,6 @@
 ;;; rmailout.el --- "RMAIL" mail reader for Emacs: output message to a file  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1985, 1987, 1993-1994, 2001-2023 Free Software
+;; Copyright (C) 1985, 1987, 1993-1994, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -453,7 +453,7 @@ display message number MSG."
       (narrow-to-region (point-max) (point-max)))
     (insert-buffer-substring tembuf)
     (rmail-count-new-messages t)
-    ;; FIXME should re-use existing windows.
+    ;; FIXME should reuse existing windows.
     (if (rmail-summary-exists)
        (rmail-select-summary (rmail-update-summary)))
     (rmail-show-message-1 msg)))
diff --git a/lisp/mail/rmailsort.el b/lisp/mail/rmailsort.el
index c2e358c5524..d897b0e76d9 100644
--- a/lisp/mail/rmailsort.el
+++ b/lisp/mail/rmailsort.el
@@ -1,6 +1,6 @@
 ;;; rmailsort.el --- Rmail: sort messages  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1990, 1993-1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1990, 1993-1994, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
diff --git a/lisp/mail/rmailsum.el b/lisp/mail/rmailsum.el
index 661bfee4ab3..48c5cb70b33 100644
--- a/lisp/mail/rmailsum.el
+++ b/lisp/mail/rmailsum.el
@@ -1,6 +1,6 @@
 ;;; rmailsum.el --- make summary buffers for the mail reader  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1985, 1993-1996, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1985, 1993-1996, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -436,19 +436,19 @@ headers of the messages."
     (unless (and rmail-summary-message-parents-vector
                 (= (length rmail-summary-message-parents-vector)
                    (1+ rmail-total-messages)))
-      (rmail-summary-fill-message-parents-and-descs-vectors))
-    (let ((enc-msgs (make-bool-vector (1+ rmail-total-messages) nil)))
-      (rmail-summary--walk-thread-message-recursively msgnum enc-msgs)
-      (rmail-new-summary (format "thread containing message %d" msgnum)
-                        (list 'rmail-summary-by-thread msgnum)
-                        (if (and rmail-summary-progressively-narrow
-                                 (rmail-summary--exists-1))
-                            (lambda (msg _msgnum)
-                              (and (aref 
rmail-summary-currently-displayed-msgs msg)
-                                   (aref enc-msgs msg)))
+      (rmail-summary-fill-message-parents-and-descs-vectors)))
+  (let ((enc-msgs (make-bool-vector (1+ rmail-total-messages) nil)))
+    (rmail-summary--walk-thread-message-recursively msgnum enc-msgs)
+    (rmail-new-summary (format "thread containing message %d" msgnum)
+                      (list 'rmail-summary-by-thread msgnum)
+                      (if (and rmail-summary-progressively-narrow
+                               (rmail-summary--exists-1))
                           (lambda (msg _msgnum)
-                             (aref enc-msgs msg)))
-                        msgnum))))
+                            (and (aref rmail-summary-currently-displayed-msgs 
msg)
+                                 (aref enc-msgs msg)))
+                        (lambda (msg _msgnum)
+                           (aref enc-msgs msg)))
+                      msgnum)))
 
 ;;;###autoload
 (defun rmail-summary-by-labels (labels)
diff --git a/lisp/mail/sendmail.el b/lisp/mail/sendmail.el
index b5dd5322ec1..d54fb51dfd3 100644
--- a/lisp/mail/sendmail.el
+++ b/lisp/mail/sendmail.el
@@ -1,6 +1,6 @@
 ;;; sendmail.el --- mail sending commands for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1986, 1992-1996, 1998, 2000-2023 Free Software
+;; Copyright (C) 1985-1986, 1992-1996, 1998, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el
index e30c69f2441..ed21e777b28 100644
--- a/lisp/mail/smtpmail.el
+++ b/lisp/mail/smtpmail.el
@@ -1,6 +1,6 @@
 ;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Tomoji Kagatani <kagatani@rbc.ncl.omron.co.jp>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/supercite.el b/lisp/mail/supercite.el
index 8d9cb5511ed..9104feb6219 100644
--- a/lisp/mail/supercite.el
+++ b/lisp/mail/supercite.el
@@ -1,6 +1,6 @@
 ;;; supercite.el --- minor mode for citing mail and news replies  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
 ;; Author: 1993 Barry A. Warsaw <bwarsaw@python.org>
 ;; Maintainer: emacs-devel@gnu.org
@@ -817,7 +817,7 @@ If there was no mail header with FIELD as its key, return 
the value of
 
 (defun sc-mail-field-query (arg)
   "View the value of a mail field.
-With `\\[universal-argument]', prompts for action on mail field.
+With \\[universal-argument], prompts for action on mail field.
 Action can be one of: View, Modify, Add, or Delete."
   (interactive "P")
   (let* ((alist '(("view" . ?v) ("modify" . ?m) ("add" . ?a) ("delete" . ?d)))
@@ -1710,7 +1710,7 @@ Numeric ARG indicates which header style from 
`sc-rewrite-header-list'
 to use when rewriting the header.  No supplied ARG indicates use of
 `sc-preferred-header-style'.
 
-With just `\\[universal-argument]', electric reference insert mode is
+With just \\[universal-argument], electric reference insert mode is
 entered, regardless of the value of `sc-electric-references-p'.  See
 `sc-electric-mode' for more information."
   (interactive "P")
@@ -1930,7 +1930,7 @@ With numeric ARG, inserts that many new lines."
 
 (defun sc-insert-citation (arg)
   "Insert citation string at beginning of current line if not already cited.
-With `\\[universal-argument]' insert citation even if line is already
+With \\[universal-argument] insert citation even if line is already
 cited."
   (interactive "P")
   (save-excursion
diff --git a/lisp/mail/undigest.el b/lisp/mail/undigest.el
index 39e047eee72..98ac17a99ed 100644
--- a/lisp/mail/undigest.el
+++ b/lisp/mail/undigest.el
@@ -1,6 +1,6 @@
 ;;; undigest.el --- digest-cracking support for the RMAIL mail reader  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1985-1986, 1994, 1996, 2001-2023 Free Software
+;; Copyright (C) 1985-1986, 1994, 1996, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/unrmail.el b/lisp/mail/unrmail.el
index 7e0304c824c..a0bea65f017 100644
--- a/lisp/mail/unrmail.el
+++ b/lisp/mail/unrmail.el
@@ -1,6 +1,6 @@
 ;;; unrmail.el --- convert Rmail Babyl files to mbox files  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: mail
diff --git a/lisp/mail/uudecode.el b/lisp/mail/uudecode.el
index 4b9acd922d8..dd717a161d1 100644
--- a/lisp/mail/uudecode.el
+++ b/lisp/mail/uudecode.el
@@ -1,6 +1,6 @@
 ;;; uudecode.el --- elisp native uudecode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
 ;; Keywords: uudecode news
diff --git a/lisp/mail/yenc.el b/lisp/mail/yenc.el
index a836f5b71bd..e7aac0a10d8 100644
--- a/lisp/mail/yenc.el
+++ b/lisp/mail/yenc.el
@@ -1,6 +1,6 @@
 ;;; yenc.el --- elisp native yenc decoder  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Jesper Harder <harder@ifa.au.dk>
 ;; Keywords: yenc news
diff --git a/lisp/man.el b/lisp/man.el
index 3efa29d7aad..d96396483d3 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -1,6 +1,6 @@
 ;;; man.el --- browse UNIX manual pages -*- lexical-binding: t -*-
 
-;; Copyright (C) 1993-1994, 1996-1997, 2001-2023 Free Software
+;; Copyright (C) 1993-1994, 1996-1997, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Barry A. Warsaw <bwarsaw@cen.com>
@@ -579,7 +579,7 @@ Otherwise, the value is whatever the function
 (defun Man-shell-file-name ()
   "Return a proper shell file name, respecting remote directories."
   (or ; This works also in the local case.
-      (with-connection-local-variables shell-file-name)
+      (connection-local-value shell-file-name)
       "/bin/sh"))
 
 (defun Man-header-file-path ()
@@ -761,7 +761,11 @@ and the `Man-section-translations-alist' variables)."
       (setq name (match-string 2 ref)
            section (match-string 1 ref))))
     (if (string= name "")
-       ref                             ; Return the reference as is
+        ;; see Bug#66390
+       (mapconcat 'identity
+                   (mapcar #'shell-quote-argument
+                           (split-string ref "\\s-+"))
+                   " ")                 ; Return the reference as is
       (if Man-downcase-section-letters-flag
          (setq section (downcase section)))
       (while slist
diff --git a/lisp/master.el b/lisp/master.el
index 8c77bcfbcf7..0caf4d7963f 100644
--- a/lisp/master.el
+++ b/lisp/master.el
@@ -1,6 +1,6 @@
 ;;; master.el --- make a buffer the master over another buffer  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <alex@gnu.org>
 ;; Old-Version: 1.0.2
diff --git a/lisp/mb-depth.el b/lisp/mb-depth.el
index 0727dd33ab8..d8cef7999ea 100644
--- a/lisp/mb-depth.el
+++ b/lisp/mb-depth.el
@@ -1,6 +1,6 @@
 ;;; mb-depth.el --- Indicate minibuffer-depth in prompt -*- lexical-binding: t 
-*-
 ;;
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Miles Bader <miles@gnu.org>
 ;; Keywords: convenience
diff --git a/lisp/md4.el b/lisp/md4.el
index 12ea672c7e6..72ba72f9103 100644
--- a/lisp/md4.el
+++ b/lisp/md4.el
@@ -1,6 +1,6 @@
 ;;; md4.el --- MD4 Message Digest Algorithm. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2001, 2004, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2004, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Taro Kawagishi <tarok@transpulse.org>
 ;; Keywords: MD4
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
index 94c2b50c724..47c6a8f0613 100644
--- a/lisp/menu-bar.el
+++ b/lisp/menu-bar.el
@@ -1,6 +1,6 @@
 ;;; menu-bar.el --- define a default menu bar  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Richard M. Stallman
 ;; Maintainer: emacs-devel@gnu.org
@@ -1438,6 +1438,14 @@ mail status in mode line"))
 (defvar menu-bar-line-wrapping-menu
   (let ((menu (make-sparse-keymap "Line Wrapping")))
 
+    (bindings--define-key menu [visual-wrap]
+      '(menu-item "Visual Wrap Prefix mode" visual-wrap-prefix-mode
+                  :help "Display continuation lines with visual 
context-dependent prefix"
+                  :visible (menu-bar-menu-frame-live-and-visible-p)
+                  :button (:toggle
+                           . (bound-and-true-p visual-wrap-prefix-mode))
+                  :enable t))
+
     (bindings--define-key menu [word-wrap]
       '(menu-item "Word Wrap (Visual Line mode)"
                   menu-bar--visual-line-mode-enable
diff --git a/lisp/mh-e/ChangeLog.1 b/lisp/mh-e/ChangeLog.1
index f918ab8fe74..10a19fdc49f 100644
--- a/lisp/mh-e/ChangeLog.1
+++ b/lisp/mh-e/ChangeLog.1
@@ -7534,7 +7534,7 @@
        (mh-yank-cur-msg): Add a space between sexprs.
 
        * mh-utils.el (mh-mark-active-p): New macro which papers over
-       diffences between GNU Emacs and XEmacs. The variables mark-active
+       differences between GNU Emacs and XEmacs. The variables mark-active
        and transient-mark-mode are used in GNU Emacs while zmacs-regions
        and region-active-p are used in XEmacs.
 
@@ -11419,7 +11419,7 @@
        (dist): Leave release in current directory.
 
 
-  Copyright (C) 2003-2023 Free Software Foundation, Inc.
+  Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/mh-e/ChangeLog.2 b/lisp/mh-e/ChangeLog.2
index f0032e9db19..e632bcf1858 100644
--- a/lisp/mh-e/ChangeLog.2
+++ b/lisp/mh-e/ChangeLog.2
@@ -2576,7 +2576,7 @@
        use function mh-variants instead.
        (mh-variant-info, mh-variant-mh-info, mh-variant-mu-mh-info)
        (mh-variant-nmh-info): Co-locate next to mh-variants, which uses
-       them.  Updated to use mh-file-command-p which is more accurrate
+       them.  Updated to use mh-file-command-p which is more accurate
        than file-executable-p which returns t for directories.
        (mh-file-command-p): Move here from mh-utils, since
        mh-variant-*-info are the only functions to use it.
@@ -3673,7 +3673,7 @@
 
 See ChangeLog.1 for earlier changes.
 
-  Copyright (C) 2005-2023 Free Software Foundation, Inc.
+  Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/mh-e/mh-acros.el b/lisp/mh-e/mh-acros.el
index a8730b4bc42..8f582df128d 100644
--- a/lisp/mh-e/mh-acros.el
+++ b/lisp/mh-e/mh-acros.el
@@ -1,6 +1,6 @@
 ;;; mh-acros.el --- macros used in MH-E  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
@@ -42,83 +42,8 @@
 
 
 
-;;; Compatibility
-
-;;;###mh-autoload
-(defmacro mh-do-in-gnu-emacs (&rest body)
-  "Execute BODY if in GNU Emacs."
-  (declare (obsolete progn "29.1") (debug t) (indent defun))
-  (unless (featurep 'xemacs) `(progn ,@body)))
-
-;;;###mh-autoload
-(defmacro mh-do-in-xemacs (&rest body)
-  "Execute BODY if in XEmacs."
-  (declare (obsolete ignore "29.1") (debug t) (indent defun))
-  (when (featurep 'xemacs) `(progn ,@body)))
-
-;;;###mh-autoload
-(defmacro mh-funcall-if-exists (function &rest args)
-  "Call FUNCTION with ARGS as parameters if it exists."
-  (declare (obsolete "use `(when (fboundp 'foo) (foo))' instead." "29.1")
-           (debug (symbolp body)))
-  ;; FIXME: Not clear when this should be used.  If the function happens
-  ;; not to exist at compile-time (e.g. because the corresponding package
-  ;; wasn't loaded), then it won't ever be used :-(
-  (when (fboundp function)
-    `(when (fboundp ',function)
-       (funcall ',function ,@args))))
-
-;;;###mh-autoload
-(defmacro defun-mh (name function arg-list &rest body)
-  "Create function NAME.
-If FUNCTION exists, then NAME becomes an alias for FUNCTION.
-Otherwise, create function NAME with ARG-LIST and BODY."
-  (declare (obsolete defun "29.1")
-           (indent defun) (doc-string 4)
-           (defining-symbol name)
-           (debug (&define name symbolp sexp def-body)))
-  `(defalias ',name
-     (if (fboundp ',function)
-         ',function
-       (lambda ,arg-list ,@body))))
-
-;;;###mh-autoload
-(defmacro defmacro-mh (name macro arg-list &rest body)
-  "Create macro NAME.
-If MACRO exists, then NAME becomes an alias for MACRO.
-Otherwise, create macro NAME with ARG-LIST and BODY."
-  (declare (obsolete defmacro "29.1")
-           (indent defun) (doc-string 4)
-           (defining-symbol name)
-           (debug (&define name symbolp sexp def-body)))
-  (let ((defined-p (fboundp macro)))
-    (if defined-p
-        `(defalias ',name ',macro)
-      `(defmacro ,name ,arg-list ,@body))))
-
-
 ;;; Miscellaneous
 
-;;;###mh-autoload
-(defmacro mh-make-local-hook (hook)
-  "Make HOOK local if needed.
-XEmacs and versions of GNU Emacs before 21.1 require
-`make-local-hook' to be called."
-  (declare (obsolete nil "29.1"))
-  (when (and (fboundp 'make-local-hook)
-             (not (get 'make-local-hook 'byte-obsolete-info)))
-    `(make-local-hook ,hook)))
-
-;;;###mh-autoload
-(defmacro mh-mark-active-p (check-transient-mark-mode-flag)
-  "If CHECK-TRANSIENT-MARK-MODE-FLAG is non-nil then check if
-variable `transient-mark-mode' is active."
-  (declare (obsolete nil "29.1"))
-  (cond ((not check-transient-mark-mode-flag)
-         'mark-active)
-        (t
-         '(and transient-mark-mode mark-active))))
-
 ;;;###mh-autoload
 (defmacro with-mh-folder-updating (save-modification-flag &rest body)
   "Format is (with-mh-folder-updating (SAVE-MODIFICATION-FLAG) &body BODY).
diff --git a/lisp/mh-e/mh-alias.el b/lisp/mh-e/mh-alias.el
index 2b567411e0f..023bccad71a 100644
--- a/lisp/mh-e/mh-alias.el
+++ b/lisp/mh-e/mh-alias.el
@@ -1,6 +1,6 @@
 ;;; mh-alias.el --- MH-E mail alias completion and expansion  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1994-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Peter S. Galbraith <psg@debian.org>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-buffers.el b/lisp/mh-e/mh-buffers.el
index b0f2e1963d6..e757f330675 100644
--- a/lisp/mh-e/mh-buffers.el
+++ b/lisp/mh-e/mh-buffers.el
@@ -1,6 +1,6 @@
 ;;; mh-buffers.el --- MH-E buffer constants and utilities  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993, 1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-comp.el b/lisp/mh-e/mh-comp.el
index 92d31bf1826..df2ca6ebd08 100644
--- a/lisp/mh-e/mh-comp.el
+++ b/lisp/mh-e/mh-comp.el
@@ -1,6 +1,6 @@
 ;;; mh-comp.el --- MH-E functions for composing and sending messages  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993, 1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
@@ -574,7 +574,7 @@ See also `mh-compose-forward-as-mime-flag',
         (setq orig-subject (mh-get-header-field "Subject:")))
       (let ((forw-subject
              (mh-forwarded-letter-subject orig-from orig-subject)))
-        (mh-insert-fields "Subject:" forw-subject)
+        (mh-modify-header-field "Subject" forw-subject t)
         (goto-char (point-min))
         ;; Set the local value of mh-mail-header-separator according to what is
         ;; present in the buffer...
diff --git a/lisp/mh-e/mh-e.el b/lisp/mh-e/mh-e.el
index 34c809a5ecd..1a535620602 100644
--- a/lisp/mh-e/mh-e.el
+++ b/lisp/mh-e/mh-e.el
@@ -1,6 +1,6 @@
 ;;; mh-e.el --- GNU Emacs interface to the MH mail system  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1985-1988, 1990, 1992-1995, 1997, 1999-2023 Free
+;; Copyright (C) 1985-1988, 1990, 1992-1995, 1997, 1999-2024 Free
 ;; Software Foundation, Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-folder.el b/lisp/mh-e/mh-folder.el
index 68f72a6e0cf..1dae9a600fd 100644
--- a/lisp/mh-e/mh-folder.el
+++ b/lisp/mh-e/mh-folder.el
@@ -1,6 +1,6 @@
 ;;; mh-folder.el --- MH-Folder mode  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
 ;; Keywords: mail
diff --git a/lisp/mh-e/mh-funcs.el b/lisp/mh-e/mh-funcs.el
index df128c8f709..bb3e67467d5 100644
--- a/lisp/mh-e/mh-funcs.el
+++ b/lisp/mh-e/mh-funcs.el
@@ -1,6 +1,6 @@
 ;;; mh-funcs.el --- MH-E functions not everyone will use right away  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993, 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
 ;; Keywords: mail
@@ -108,7 +108,7 @@ folder. This is useful for folders that are easily 
regenerated."
             (window-config mh-previous-window-config))
         (mh-set-folder-modified-p t)    ; lock folder to kill it
         (mh-exec-cmd-daemon "rmf" 'mh-rmf-daemon folder)
-        (when (boundp 'mh-speed-folder-map)
+        (when (and (boundp 'speedbar-buffer) speedbar-buffer)
           (mh-speed-invalidate-map folder))
         (mh-remove-from-sub-folders-cache folder)
         (mh-set-folder-modified-p nil)  ; so kill-buffer doesn't complain
diff --git a/lisp/mh-e/mh-gnus.el b/lisp/mh-e/mh-gnus.el
index 4bc7119cb80..2053dcc708a 100644
--- a/lisp/mh-e/mh-gnus.el
+++ b/lisp/mh-e/mh-gnus.el
@@ -1,6 +1,6 @@
 ;;; mh-gnus.el --- make MH-E compatible with various versions of Gnus  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-identity.el b/lisp/mh-e/mh-identity.el
index 307c7fcf9c7..bfd0a1c0277 100644
--- a/lisp/mh-e/mh-identity.el
+++ b/lisp/mh-e/mh-identity.el
@@ -1,6 +1,6 @@
 ;;; mh-identity.el --- multiple identify support for MH-E  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Peter S. Galbraith <psg@debian.org>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-inc.el b/lisp/mh-e/mh-inc.el
index e4e88b36e3d..acb0474a8f9 100644
--- a/lisp/mh-e/mh-inc.el
+++ b/lisp/mh-e/mh-inc.el
@@ -1,6 +1,6 @@
 ;;; mh-inc.el --- MH-E "inc" and separate mail spool handling  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Peter S. Galbraith <psg@debian.org>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-junk.el b/lisp/mh-e/mh-junk.el
index c01ecc69285..9eb4f8d500c 100644
--- a/lisp/mh-e/mh-junk.el
+++ b/lisp/mh-e/mh-junk.el
@@ -1,6 +1,6 @@
 ;;; mh-junk.el --- MH-E interface to anti-spam measures  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Satyaki Das <satyaki@theforce.stanford.edu>,
 ;;         Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-letter.el b/lisp/mh-e/mh-letter.el
index f75e2b9b80d..8e0241f345e 100644
--- a/lisp/mh-e/mh-letter.el
+++ b/lisp/mh-e/mh-letter.el
@@ -1,6 +1,6 @@
 ;;; mh-letter.el --- MH-Letter mode  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993, 1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-limit.el b/lisp/mh-e/mh-limit.el
index 845b6f99cf7..7af7f768b60 100644
--- a/lisp/mh-e/mh-limit.el
+++ b/lisp/mh-e/mh-limit.el
@@ -1,6 +1,6 @@
 ;;; mh-limit.el --- MH-E display limits  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2003, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2003, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Peter S. Galbraith <psg@debian.org>
 ;; Keywords: mail
diff --git a/lisp/mh-e/mh-mime.el b/lisp/mh-e/mh-mime.el
index b493f7d86dd..b0920d524a7 100644
--- a/lisp/mh-e/mh-mime.el
+++ b/lisp/mh-e/mh-mime.el
@@ -1,6 +1,6 @@
 ;;; mh-mime.el --- MH-E MIME support  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993, 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
 ;; Keywords: mail
diff --git a/lisp/mh-e/mh-print.el b/lisp/mh-e/mh-print.el
index eeea94a69e5..b7c07d4239c 100644
--- a/lisp/mh-e/mh-print.el
+++ b/lisp/mh-e/mh-print.el
@@ -1,6 +1,6 @@
 ;;; mh-print.el --- MH-E printing support  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Jeffrey C Honig <jch@honig.net>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-scan.el b/lisp/mh-e/mh-scan.el
index d0a279eac97..b076ff5dbec 100644
--- a/lisp/mh-e/mh-scan.el
+++ b/lisp/mh-e/mh-scan.el
@@ -1,6 +1,6 @@
 ;;; mh-scan.el --- MH-E scan line constants and utilities  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993, 1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-search.el b/lisp/mh-e/mh-search.el
index 63b4304985c..59dad161c11 100644
--- a/lisp/mh-e/mh-search.el
+++ b/lisp/mh-e/mh-search.el
@@ -1,6 +1,6 @@
 ;;; mh-search.el --- MH-Search mode  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993, 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Indexed search by Satyaki Das <satyaki@theforce.stanford.edu>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
@@ -1569,7 +1569,7 @@ If the folder returned doesn't exist then it is created."
     (save-excursion (mh-exec-cmd-quiet nil "rmf" chosen-name))
     (mh-exec-cmd-quiet nil "folder" "-create" "-fast" chosen-name)
     (mh-remove-from-sub-folders-cache chosen-name)
-    (when (boundp 'mh-speed-folder-map)
+    (when (and (boundp 'speedbar-buffer) speedbar-buffer)
       (mh-speed-add-folder chosen-name))
     chosen-name))
 
diff --git a/lisp/mh-e/mh-seq.el b/lisp/mh-e/mh-seq.el
index f5716fe968f..0251d4875d4 100644
--- a/lisp/mh-e/mh-seq.el
+++ b/lisp/mh-e/mh-seq.el
@@ -1,6 +1,6 @@
 ;;; mh-seq.el --- MH-E sequences support  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993, 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
 ;; Keywords: mail
diff --git a/lisp/mh-e/mh-show.el b/lisp/mh-e/mh-show.el
index 8a26ab6d81e..0f90fd6f057 100644
--- a/lisp/mh-e/mh-show.el
+++ b/lisp/mh-e/mh-show.el
@@ -1,6 +1,6 @@
 ;;; mh-show.el --- MH-Show mode  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993, 1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-speed.el b/lisp/mh-e/mh-speed.el
index 0258f0b3939..5b5ad48a291 100644
--- a/lisp/mh-e/mh-speed.el
+++ b/lisp/mh-e/mh-speed.el
@@ -1,6 +1,6 @@
 ;;; mh-speed.el --- MH-E speedbar support  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-thread.el b/lisp/mh-e/mh-thread.el
index 980a6a38902..8119de486a1 100644
--- a/lisp/mh-e/mh-thread.el
+++ b/lisp/mh-e/mh-thread.el
@@ -1,6 +1,6 @@
 ;;; mh-thread.el --- MH-E threading support  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-tool-bar.el b/lisp/mh-e/mh-tool-bar.el
index c0fadc66096..580faf7c5df 100644
--- a/lisp/mh-e/mh-tool-bar.el
+++ b/lisp/mh-e/mh-tool-bar.el
@@ -1,6 +1,6 @@
 ;;; mh-tool-bar.el --- MH-E tool bar support  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
 ;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-utils.el b/lisp/mh-e/mh-utils.el
index 6f84fcdb2ba..9d5711105ba 100644
--- a/lisp/mh-e/mh-utils.el
+++ b/lisp/mh-e/mh-utils.el
@@ -1,6 +1,6 @@
 ;;; mh-utils.el --- MH-E general utilities  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993, 1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
@@ -795,7 +795,7 @@ used in searching."
              (message "Creating %s" folder-name)
              (mh-exec-cmd-error nil "folder" folder-name)
              (mh-remove-from-sub-folders-cache folder-name)
-             (when (boundp 'mh-speed-folder-map)
+             (when (and (boundp 'speedbar-buffer) speedbar-buffer)
                (mh-speed-add-folder folder-name))
              (message "Creating %s...done" folder-name))
             (new-file-flag
diff --git a/lisp/mh-e/mh-xface.el b/lisp/mh-e/mh-xface.el
index 06233b1b217..83269146c41 100644
--- a/lisp/mh-e/mh-xface.el
+++ b/lisp/mh-e/mh-xface.el
@@ -1,6 +1,6 @@
 ;;; mh-xface.el --- MH-E X-Face and Face header field display  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
 ;; Keywords: mail
diff --git a/lisp/midnight.el b/lisp/midnight.el
index b2504536b48..bfa99d6a7a8 100644
--- a/lisp/midnight.el
+++ b/lisp/midnight.el
@@ -1,6 +1,6 @@
 ;;; midnight.el --- run something every midnight, e.g., kill old buffers  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Sam Steingold <sds@gnu.org>
 ;; Created: 1998-05-18
diff --git a/lisp/minibuf-eldef.el b/lisp/minibuf-eldef.el
index a9792383786..0edc10fd131 100644
--- a/lisp/minibuf-eldef.el
+++ b/lisp/minibuf-eldef.el
@@ -1,6 +1,6 @@
 ;;; minibuf-eldef.el --- Only show defaults in prompts when applicable  -*- 
lexical-binding: t -*-
 ;;
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Miles Bader <miles@gnu.org>
 ;; Keywords: convenience
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 03b64198bcf..0bfc5c06313 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1,6 +1,6 @@
 ;;; minibuffer.el --- Minibuffer and completion functions -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Package: emacs
@@ -150,8 +150,29 @@ The metadata of a completion table should be constant 
between two boundaries."
                        minibuffer-completion-table
                        minibuffer-completion-predicate))
 
+(defun completion--metadata-get-1 (metadata prop)
+  (or (alist-get prop metadata)
+      (plist-get completion-extra-properties
+                 ;; Cache the keyword
+                 (or (get prop 'completion-extra-properties--keyword)
+                     (put prop 'completion-extra-properties--keyword
+                          (intern (concat ":" (symbol-name prop))))))))
+
 (defun completion-metadata-get (metadata prop)
-  (cdr (assq prop metadata)))
+  "Get property PROP from completion METADATA.
+If the metadata specifies a completion category, the variables
+`completion-category-overrides' and
+`completion-category-defaults' take precedence for
+category-specific overrides.  If the completion metadata does not
+specify the property, the `completion-extra-properties' plist is
+consulted.  Note that the keys of the
+`completion-extra-properties' plist are keyword symbols, not
+plain symbols."
+  (if-let (((not (eq prop 'category)))
+           (cat (completion--metadata-get-1 metadata 'category))
+           (over (completion--category-override cat prop)))
+      (cdr over)
+    (completion--metadata-get-1 metadata prop)))
 
 (defun complete-with-action (action collection string predicate)
   "Perform completion according to ACTION.
@@ -961,6 +982,8 @@ is at its default value `grow-only'."
                (reverse multi-message-list)
                multi-message-separator)))
 
+(defvar touch-screen-current-tool)
+
 (defun clear-minibuffer-message ()
   "Clear message temporarily shown in the minibuffer.
 Intended to be called via `clear-message-function'."
@@ -975,7 +998,7 @@ Intended to be called via `clear-message-function'."
   ;; progress, because a preview message might currently be displayed
   ;; in the echo area.  FIXME: find some way to place this in
   ;; touch-screen.el.
-  (if (and touch-screen-preview-select
+  (if (and (bound-and-true-p touch-screen-preview-select)
            (eq (nth 3 touch-screen-current-tool) 'drag))
       'dont-clear-message
     ;; Return nil telling the caller that the message
@@ -1133,23 +1156,42 @@ styles for specific categories, such as files, buffers, 
etc."
     (project-file (styles . (substring)))
     (xref-location (styles . (substring)))
     (info-menu (styles . (basic substring)))
-    (symbol-help (styles . (basic shorthand substring))))
+    (symbol-help (styles . (basic shorthand substring)))
+    (calendar-month (display-sort-function . identity)))
   "Default settings for specific completion categories.
+
 Each entry has the shape (CATEGORY . ALIST) where ALIST is
 an association list that can specify properties such as:
 - `styles': the list of `completion-styles' to use for that category.
 - `cycle': the `completion-cycle-threshold' to use for that category.
+- `cycle-sort-function': function to sort entries when cycling.
+- `display-sort-function': function to sort entries in *Completions*.
+- `group-function': function for grouping the completion candidates.
+- `annotation-function': function to add annotations in *Completions*.
+- `affixation-function': function to prepend/append a prefix/suffix.
+
 Categories are symbols such as `buffer' and `file', used when
 completing buffer and file names, respectively.
 
 Also see `completion-category-overrides'.")
 
 (defcustom completion-category-overrides nil
-  "List of category-specific user overrides for completion styles.
+  "List of category-specific user overrides for completion metadata.
+
 Each override has the shape (CATEGORY . ALIST) where ALIST is
 an association list that can specify properties such as:
 - `styles': the list of `completion-styles' to use for that category.
 - `cycle': the `completion-cycle-threshold' to use for that category.
+- `cycle-sort-function': function to sort entries when cycling.
+- `display-sort-function': nil means to use either the sorting
+function from metadata, or if that is nil, fall back to `completions-sort';
+`identity' disables sorting and keeps the original order; and other
+possible values are the same as in `completions-sort'.
+- `group-function': function for grouping the completion candidates.
+- `annotation-function': function to add annotations in *Completions*.
+- `affixation-function': function to prepend/append a prefix/suffix.
+See more description of metadata in `completion-metadata'.
+
 Categories are symbols such as `buffer' and `file', used when
 completing buffer and file names, respectively.
 
@@ -1169,7 +1211,33 @@ overrides the default specified in 
`completion-category-defaults'."
                 ,completion--styles-type)
            (cons :tag "Completion Cycling"
                 (const :tag "Select one value from the menu." cycle)
-                 ,completion--cycling-threshold-type))))
+                 ,completion--cycling-threshold-type)
+           (cons :tag "Cycle Sorting"
+                 (const :tag "Select one value from the menu."
+                        cycle-sort-function)
+                 (choice (function :tag "Custom function")))
+           (cons :tag "Completion Sorting"
+                 (const :tag "Select one value from the menu."
+                        display-sort-function)
+                 (choice (const :tag "Use default" nil)
+                         (const :tag "No sorting" identity)
+                         (const :tag "Alphabetical sorting"
+                                minibuffer-sort-alphabetically)
+                         (const :tag "Historical sorting"
+                                minibuffer-sort-by-history)
+                         (function :tag "Custom function")))
+           (cons :tag "Completion Groups"
+                 (const :tag "Select one value from the menu."
+                        group-function)
+                 (choice (function :tag "Custom function")))
+           (cons :tag "Completion Annotation"
+                 (const :tag "Select one value from the menu."
+                        annotation-function)
+                 (choice (function :tag "Custom function")))
+           (cons :tag "Completion Affixation"
+                 (const :tag "Select one value from the menu."
+                        affixation-function)
+                 (choice (function :tag "Custom function"))))))
 
 (defun completion--category-override (category tag)
   (or (assq tag (cdr (assq category completion-category-overrides)))
@@ -1321,7 +1389,9 @@ If it's nil, sorting is disabled.
 If it's the symbol `alphabetical', candidates are sorted by
 `minibuffer-sort-alphabetically'.
 If it's the symbol `historical', candidates are sorted by
-`minibuffer-sort-by-history'.
+`minibuffer-sort-by-history', which first sorts alphabetically,
+and then rearranges the order according to the order of the
+candidates in the minibuffer history.
 If it's a function, the function is called to sort the candidates.
 The sorting function takes a list of completion candidate
 strings, which it may modify; it should return a sorted list,
@@ -1681,7 +1751,7 @@ names, where this is the directory component of the file 
name.")
   "Sort COMPLETIONS by their position in `minibuffer-history-variable'.
 
 COMPLETIONS are sorted first by `minibuffer-sort-alphbetically',
-then any elements occuring in the minibuffer history list are
+then any elements occurring in the minibuffer history list are
 moved to the front based on the chronological order they occur in
 the history.  If a history variable hasn't been specified for
 this call of `completing-read', COMPLETIONS are sorted only by
@@ -1900,10 +1970,13 @@ appear to be a match."
    ;; Allow user to specify null string
    ((= beg end) (funcall exit-function))
    ;; The CONFIRM argument is a predicate.
-   ((and (functionp minibuffer-completion-confirm)
-         (funcall minibuffer-completion-confirm
-                  (buffer-substring beg end)))
-    (funcall exit-function))
+   ((functionp minibuffer-completion-confirm)
+    (if (funcall minibuffer-completion-confirm
+                 (buffer-substring beg end))
+        (funcall exit-function)
+      (unless completion-fail-discreetly
+       (ding)
+       (completion--message "No match"))))
    ;; See if we have a completion from the table.
    ((test-completion (buffer-substring beg end)
                      minibuffer-completion-table
@@ -2375,6 +2448,9 @@ candidates."
   "Property list of extra properties of the current completion job.
 These include:
 
+`:category': the kind of objects returned by `all-completions'.
+   Used by `completion-category-overrides'.
+
 `:annotation-function': Function to annotate the completions buffer.
    The function must accept one argument, a completion string,
    and return either nil or a string which is to be displayed
@@ -2390,6 +2466,15 @@ These include:
    `:annotation-function' when both are provided, so only this
    function is used.
 
+`:group-function': Function for grouping the completion candidates.
+
+`:display-sort-function': Function to sort entries in *Completions*.
+
+`:cycle-sort-function': Function to sort entries when cycling.
+
+See more information about these functions above
+in `completion-metadata'.
+
 `:exit-function': Function to run after completion is performed.
 
    The function must accept two arguments, STRING and STATUS.
@@ -2433,12 +2518,15 @@ These include:
     (fit-window-to-buffer win completions-max-height)))
 
 (defcustom completion-auto-deselect t
-  "If non-nil, deselect the selected completion candidate when you type.
-
-A non-nil value means that after typing, point in *Completions*
-will be moved off any completion candidates.  This means
-`minibuffer-choose-completion-or-exit' will exit with the
-minibuffer's current contents, instead of a completion candidate."
+  "If non-nil, deselect current completion candidate when you type in 
minibuffer.
+
+A non-nil value means that after typing at the minibuffer prompt,
+any completion candidate highlighted in *Completions* window (to
+indicate that it is the selected candidate) will be un-highlighted,
+and point in the *Completions* window will be moved off such a candidate.
+This means that `RET' (`minibuffer-choose-completion-or-exit') will exit
+the minubuffer with the minibuffer's current contents, instead of the
+selected completion candidate."
   :type '(choice (const :tag "Candidates in *Completions* stay selected as you 
type" nil)
                  (const :tag "Typing deselects any completion candidate in 
*Completions*" t))
   :version "30.1")
@@ -2509,12 +2597,8 @@ The candidate will still be chosen by 
`choose-completion' unless
                                            base-size md
                                            minibuffer-completion-table
                                            minibuffer-completion-predicate))
-             (ann-fun (or (completion-metadata-get all-md 'annotation-function)
-                          (plist-get completion-extra-properties
-                                     :annotation-function)))
-             (aff-fun (or (completion-metadata-get all-md 'affixation-function)
-                          (plist-get completion-extra-properties
-                                     :affixation-function)))
+             (ann-fun (completion-metadata-get all-md 'annotation-function))
+             (aff-fun (completion-metadata-get all-md 'affixation-function))
              (sort-fun (completion-metadata-get all-md 'display-sort-function))
              (group-fun (completion-metadata-get all-md 'group-function))
              (mainbuf (current-buffer))
@@ -2544,7 +2628,7 @@ The candidate will still be chosen by `choose-completion' 
unless
              . ,#'(lambda (_window)
                     (with-current-buffer mainbuf
                       (when completion-auto-deselect
-                        (add-hook 'after-change-functions 
#'completions--after-change t))
+                        (add-hook 'after-change-functions 
#'completions--after-change nil t))
                       ;; Remove the base-size tail because `sort' requires a 
properly
                       ;; nil-terminated list.
                       (when last (setcdr last nil))
@@ -3068,15 +3152,14 @@ the mode hook of this mode."
     (setq-local minibuffer-completion-auto-choose nil)))
 
 (defcustom minibuffer-visible-completions nil
-  "When non-nil, visible completions can be navigated from the minibuffer.
-This means that when the *Completions* buffer is visible in a window,
-then you can use the arrow keys in the minibuffer to move the cursor
-in the *Completions* buffer.  Then you can type `RET',
-and the candidate highlighted in the *Completions* buffer
-will be accepted.
-But when the *Completions* buffer is not displayed on the screen,
-then the arrow keys move point in the minibuffer as usual, and
-`RET' accepts the input typed in the minibuffer."
+  "Whether candidates shown in *Completions* can be navigated from minibuffer.
+When non-nil, if the *Completions* buffer is displayed in a window,
+you can use the arrow keys in the minibuffer to move the cursor in
+the window showing the *Completions* buffer.  Typing `RET' selects
+the highlighted completion candidate.
+If the *Completions* buffer is not displayed on the screen, or this
+variable is nil, the arrow keys move point in the minibuffer as usual,
+and `RET' accepts the input typed into the minibuffer."
   :type 'boolean
   :version "30.1")
 
@@ -3101,7 +3184,6 @@ displaying the *Completions* buffer exists."
   "<down>"  (minibuffer-visible-completions-bind 
#'minibuffer-next-line-completion)
   "RET"     (minibuffer-visible-completions-bind 
#'minibuffer-choose-completion-or-exit)
   "C-g"     (minibuffer-visible-completions-bind 
#'minibuffer-hide-completions))
-
 
 ;;; Completion tables.
 
@@ -4053,15 +4135,16 @@ LEN is the length of the completion string."
 (defun completion--flex-score (str re &optional dont-error)
   "Compute flex score of completion STR based on RE.
 If DONT-ERROR, just return nil if RE doesn't match STR."
-  (cond ((string-match re str)
-         (let* ((match-end (match-end 0))
-                (md (cddr
-                     (setq
-                      completion--flex-score-last-md
-                      (match-data t completion--flex-score-last-md)))))
-           (completion--flex-score-1 md match-end (length str))))
-        ((not dont-error)
-         (error "Internal error: %s does not match %s" re str))))
+  (let ((case-fold-search completion-ignore-case))
+    (cond ((string-match re str)
+           (let* ((match-end (match-end 0))
+                  (md (cddr
+                       (setq
+                        completion--flex-score-last-md
+                        (match-data t completion--flex-score-last-md)))))
+             (completion--flex-score-1 md match-end (length str))))
+          ((not dont-error)
+           (error "Internal error: %s does not match %s" re str)))))
 
 (defvar completion-pcm--regexp nil
   "Regexp from PCM pattern in `completion-pcm--hilit-commonality'.")
@@ -4936,7 +5019,7 @@ This is run upon minibuffer setup."
 (defun minibuffer-exit-on-screen-keyboard ()
   "Hide the on-screen keyboard if it was displayed.
 Hide the on-screen keyboard in a timer set to run in 0.1 seconds.
-It will be cancelled if the minibuffer is displayed again within
+It will be canceled if the minibuffer is displayed again within
 that timeframe.
 
 Do not hide the on screen keyboard inside a recursive edit.
diff --git a/lisp/misc.el b/lisp/misc.el
index e8b38fad42e..fb40d1c16a3 100644
--- a/lisp/misc.el
+++ b/lisp/misc.el
@@ -1,6 +1,6 @@
 ;;; misc.el --- some nonstandard editing and utility commands for Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1989, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: convenience
diff --git a/lisp/misearch.el b/lisp/misearch.el
index 2873a2542f9..f53acae472e 100644
--- a/lisp/misearch.el
+++ b/lisp/misearch.el
@@ -1,6 +1,6 @@
 ;;; misearch.el --- isearch extensions for multi-buffer search  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Juri Linkov <juri@jurta.org>
 ;; Keywords: matching
diff --git a/lisp/mouse-copy.el b/lisp/mouse-copy.el
index f45e6039320..0c4e7bcb566 100644
--- a/lisp/mouse-copy.el
+++ b/lisp/mouse-copy.el
@@ -1,6 +1,6 @@
 ;;; mouse-copy.el --- one-click text copy and move  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: John Heidemann <johnh@ISI.EDU>
 ;; Keywords: mouse
diff --git a/lisp/mouse-drag.el b/lisp/mouse-drag.el
index bcaaa18e53c..4f46370fcf0 100644
--- a/lisp/mouse-drag.el
+++ b/lisp/mouse-drag.el
@@ -1,6 +1,6 @@
 ;;; mouse-drag.el --- use mouse-2 to do a new style of scrolling  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1996-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: John Heidemann <johnh@ISI.EDU>
 ;; Keywords: mouse
diff --git a/lisp/mouse.el b/lisp/mouse.el
index 6d916e8223a..d1b06c2040d 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -1,6 +1,6 @@
 ;;; mouse.el --- window system-independent mouse support  -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: hardware, mouse
diff --git a/lisp/mpc.el b/lisp/mpc.el
index b937a6b5945..9577e0f2f42 100644
--- a/lisp/mpc.el
+++ b/lisp/mpc.el
@@ -1,6 +1,6 @@
 ;;; mpc.el --- A client for the Music Player Daemon   -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: multimedia
diff --git a/lisp/msb.el b/lisp/msb.el
index e055148c751..ec5ca9790da 100644
--- a/lisp/msb.el
+++ b/lisp/msb.el
@@ -1,6 +1,6 @@
 ;;; msb.el --- customizable buffer-selection with multiple menus  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1995, 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Lindberg <lars.lindberg@home.se>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mwheel.el b/lisp/mwheel.el
index 86ed7393a17..66a1fa1a706 100644
--- a/lisp/mwheel.el
+++ b/lisp/mwheel.el
@@ -1,6 +1,6 @@
 ;;; mwheel.el --- Mouse wheel support  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Keywords: mouse
 ;; Package: emacs
@@ -34,8 +34,8 @@
 ;; Implementation note:
 ;;
 ;; I for one would prefer some way of converting the mouse-4/mouse-5
-;; events into different event types, like 'mwheel-up' or
-;; 'mwheel-down', but I cannot find a way to do this very easily (or
+;; events into different event types, like 'wheel-up' or
+;; 'wheel-down', but I cannot find a way to do this very easily (or
 ;; portably), so for now I just live with it.
 
 (require 'timer)
@@ -56,49 +56,24 @@
              (bound-and-true-p mouse-wheel-mode))
     (mouse-wheel-mode 1)))
 
+(defvar mouse-wheel-obey-old-style-wheel-buttons t
+  "If non-nil, treat mouse-4/5/6/7 events as mouse wheel events.
+These are the event names used historically in X11 before XInput2.
+They are sometimes generated by things like text-terminals as well.")
+
 (defcustom mouse-wheel-down-event
-  (if (or (featurep 'w32-win) (featurep 'ns-win)
-          (featurep 'haiku-win) (featurep 'pgtk-win)
-          (featurep 'android-win))
-      'wheel-up
-    'mouse-4)
-  "Event used for scrolling down."
-  :group 'mouse
-  :type 'symbol
-  :set 'mouse-wheel-change-button)
-
-(defcustom mouse-wheel-down-alternate-event
-  (if (featurep 'xinput2)
-      'wheel-up
-    (unless (featurep 'x)
-      'mouse-4))
-  "Alternative wheel down event to consider."
+  (if mouse-wheel-obey-old-style-wheel-buttons 'mouse-4)
+  "Event used for scrolling down, beside `wheel-up', if any."
   :group 'mouse
   :type 'symbol
-  :version "29.1"
-  :set 'mouse-wheel-change-button)
+  :set #'mouse-wheel-change-button)
 
 (defcustom mouse-wheel-up-event
-  (if (or (featurep 'w32-win) (featurep 'ns-win)
-          (featurep 'haiku-win) (featurep 'pgtk-win)
-          (featurep 'android-win))
-      'wheel-down
-    'mouse-5)
-  "Event used for scrolling up."
+  (if mouse-wheel-obey-old-style-wheel-buttons 'mouse-5)
+  "Event used for scrolling up, beside `wheel-down', if any."
   :group 'mouse
   :type 'symbol
-  :set 'mouse-wheel-change-button)
-
-(defcustom mouse-wheel-up-alternate-event
-  (if (featurep 'xinput2)
-      'wheel-down
-    (unless (featurep 'x)
-      'mouse-5))
-  "Alternative wheel up event to consider."
-  :group 'mouse
-  :type 'symbol
-  :version "29.1"
-  :set 'mouse-wheel-change-button)
+  :set #'mouse-wheel-change-button)
 
 (defcustom mouse-wheel-click-event 'mouse-2
   "Event that should be temporarily inhibited after mouse scrolling.
@@ -108,7 +83,7 @@ scrolling with the mouse wheel.  To prevent that, this 
variable can be
 set to the event sent when clicking on the mouse wheel button."
   :group 'mouse
   :type 'symbol
-  :set 'mouse-wheel-change-button)
+  :set #'mouse-wheel-change-button)
 
 (defcustom mouse-wheel-inhibit-click-time 0.35
   "Time in seconds to inhibit clicking on mouse wheel button after scroll."
@@ -165,7 +140,7 @@ information, see `text-scale-adjust' and 
`global-text-scale-adjust'."
                     (const :tag "Scroll horizontally" :value hscroll)
                     (const :tag "Change buffer face size" :value text-scale)
                     (const :tag "Change global face size" :value 
global-text-scale)))))
-  :set 'mouse-wheel-change-button
+  :set #'mouse-wheel-change-button
   :version "28.1")
 
 (defcustom mouse-wheel-progressive-speed t
@@ -216,15 +191,9 @@ Also see `mouse-wheel-tilt-scroll'."
   :type 'boolean
   :version "26.1")
 
-(defun mwheel-event-button (event)
-  (let ((x (event-basic-type event)))
-    ;; Map mouse-wheel events to appropriate buttons
-    (if (eq 'mouse-wheel x)
-        (let ((amount (car (cdr (cdr (cdr event))))))
-          (if (< amount 0)
-              mouse-wheel-up-event
-            mouse-wheel-down-event))
-      x)))
+;; This function used to handle the `mouse-wheel` event which was
+;; removed in 2003 by commit 9eb28007fb27, thus making it obsolete.
+(define-obsolete-function-alias 'mwheel-event-button #'event-basic-type "30.1")
 
 (defun mwheel-event-window (event)
   (posn-window (event-start event)))
@@ -255,34 +224,12 @@ Also see `mouse-wheel-tilt-scroll'."
   "Function that does the job of scrolling right.")
 
 (defvar mouse-wheel-left-event
-  (if (or (featurep 'w32-win) (featurep 'ns-win)
-          (featurep 'haiku-win) (featurep 'pgtk-win)
-          (featurep 'android-win))
-      'wheel-left
-    'mouse-6)
-  "Event used for scrolling left.")
-
-(defvar mouse-wheel-left-alternate-event
-  (if (featurep 'xinput2)
-      'wheel-left
-    (unless (featurep 'x)
-      'mouse-6))
-  "Alternative wheel left event to consider.")
+  (if mouse-wheel-obey-old-style-wheel-buttons 'mouse-6)
+  "Event used for scrolling left, beside `wheel-left', if any.")
 
 (defvar mouse-wheel-right-event
-  (if (or (featurep 'w32-win) (featurep 'ns-win)
-          (featurep 'haiku-win) (featurep 'pgtk-win)
-          (featurep 'android-win))
-      'wheel-right
-    'mouse-7)
-  "Event used for scrolling right.")
-
-(defvar mouse-wheel-right-alternate-event
-  (if (featurep 'xinput2)
-      'wheel-right
-    (unless (featurep 'x)
-      'mouse-7))
-  "Alternative wheel right event to consider.")
+  (if mouse-wheel-obey-old-style-wheel-buttons 'mouse-7)
+  "Event used for scrolling right, beside `wheel-right', if any.")
 
 (defun mouse-wheel--get-scroll-window (event)
   "Return window for mouse wheel event EVENT.
@@ -311,6 +258,23 @@ active window."
                frame nil t)))))
       (mwheel-event-window event)))
 
+(defmacro mwheel--is-dir-p (dir button)
+  (declare (debug (sexp form)))
+  (let ((custom-var (intern (format "mouse-wheel-%s-event" dir)))
+        ;; N.B. that the direction `down' in a wheel event refers to
+        ;; the movement of the section of the buffer the window is
+        ;; displaying, that is to say, the direction `scroll-up' moves
+        ;; it in.
+        (event (intern (format "wheel-%s" (cond ((eq dir 'up)
+                                                 'down)
+                                                ((eq dir 'down)
+                                                 'up)
+                                                (t dir))))))
+    (macroexp-let2 nil butsym button
+      `(or (eq ,butsym ',event)
+           ;; We presume here `button' is never nil.
+           (eq ,butsym ,custom-var)))))
+
 (defun mwheel-scroll (event &optional arg)
   "Scroll up or down according to the EVENT.
 This should be bound only to mouse buttons 4, 5, 6, and 7 on
@@ -347,18 +311,17 @@ value of ARG, and the command uses it in subsequent 
scrolls."
     (when (numberp amt) (setq amt (* amt (event-line-count event))))
     (condition-case nil
         (unwind-protect
-           (let ((button (mwheel-event-button event)))
-              (cond ((and (eq amt 'hscroll) (memq button (list 
mouse-wheel-down-event
-                                                               
mouse-wheel-down-alternate-event)))
+           (let ((button (event-basic-type event)))
+              (cond ((and (eq amt 'hscroll) (mwheel--is-dir-p down button))
                      (when (and (natnump arg) (> arg 0))
                        (setq mouse-wheel-scroll-amount-horizontal arg))
                      (funcall (if mouse-wheel-flip-direction
                                   mwheel-scroll-left-function
                                 mwheel-scroll-right-function)
                               mouse-wheel-scroll-amount-horizontal))
-                    ((memq button (list mouse-wheel-down-event
-                                        mouse-wheel-down-alternate-event))
-                     (condition-case nil (funcall mwheel-scroll-down-function 
amt)
+                    ((mwheel--is-dir-p down button)
+                     (condition-case nil
+                         (funcall mwheel-scroll-down-function amt)
                        ;; Make sure we do indeed scroll to the beginning of
                        ;; the buffer.
                        (beginning-of-buffer
@@ -372,31 +335,30 @@ value of ARG, and the command uses it in subsequent 
scrolls."
                           ;; for a reason that escapes me.  This problem seems
                           ;; to only affect scroll-down.  --Stef
                           (set-window-start (selected-window) (point-min))))))
-                    ((and (eq amt 'hscroll) (memq button (list 
mouse-wheel-up-event
-                                                               
mouse-wheel-up-alternate-event)))
+                    ((and (eq amt 'hscroll) (mwheel--is-dir-p up button))
                      (when (and (natnump arg) (> arg 0))
                        (setq mouse-wheel-scroll-amount-horizontal arg))
                      (funcall (if mouse-wheel-flip-direction
                                   mwheel-scroll-right-function
                                 mwheel-scroll-left-function)
                               mouse-wheel-scroll-amount-horizontal))
-                    ((memq button (list mouse-wheel-up-event
-                                        mouse-wheel-up-alternate-event))
+                    ((mwheel--is-dir-p up button)
                      (condition-case nil (funcall mwheel-scroll-up-function 
amt)
                        ;; Make sure we do indeed scroll to the end of the 
buffer.
-                       (end-of-buffer (while t (funcall 
mwheel-scroll-up-function)))))
-                    ((memq button (list mouse-wheel-left-event
-                                        mouse-wheel-left-alternate-event)) ; 
for tilt scroll
+                       (end-of-buffer
+                        (while t (funcall mwheel-scroll-up-function)))))
+                    ((mwheel--is-dir-p left button) ; for tilt scroll
                      (when mouse-wheel-tilt-scroll
                        (funcall (if mouse-wheel-flip-direction
                                     mwheel-scroll-right-function
-                                  mwheel-scroll-left-function) amt)))
-                    ((memq button (list mouse-wheel-right-event
-                                        mouse-wheel-right-alternate-event)) ; 
for tilt scroll
+                                  mwheel-scroll-left-function)
+                                amt)))
+                    ((mwheel--is-dir-p right button) ; for tilt scroll
                      (when mouse-wheel-tilt-scroll
                        (funcall (if mouse-wheel-flip-direction
                                     mwheel-scroll-left-function
-                                  mwheel-scroll-right-function) amt)))
+                                  mwheel-scroll-right-function)
+                                amt)))
                    (t (error "Bad binding in mwheel-scroll"))))
           (if (eq scroll-window selected-window)
               ;; If there is a temporarily active region, deactivate it if
@@ -434,14 +396,12 @@ See also `text-scale-adjust'."
   (interactive (list last-input-event))
   (let ((selected-window (selected-window))
         (scroll-window (mouse-wheel--get-scroll-window event))
-        (button (mwheel-event-button event)))
+        (button (event-basic-type event)))
     (select-window scroll-window 'mark-for-redisplay)
     (unwind-protect
-        (cond ((memq button (list mouse-wheel-down-event
-                                  mouse-wheel-down-alternate-event))
+        (cond ((mwheel--is-dir-p down button)
                (text-scale-increase 1))
-              ((memq button (list mouse-wheel-up-event
-                                  mouse-wheel-up-alternate-event))
+              ((mwheel--is-dir-p up button)
                (text-scale-decrease 1)))
       (select-window selected-window))))
 
@@ -450,12 +410,10 @@ See also `text-scale-adjust'."
   "Increase or decrease the global font size according to the EVENT.
 This invokes `global-text-scale-adjust', which see."
   (interactive (list last-input-event))
-  (let ((button (mwheel-event-button event)))
-    (cond ((memq button (list mouse-wheel-down-event
-                              mouse-wheel-down-alternate-event))
+  (let ((button (event-basic-type event)))
+    (cond ((mwheel--is-dir-p down button)
            (global-text-scale-adjust 1))
-          ((memq button (list mouse-wheel-up-event
-                              mouse-wheel-up-alternate-event))
+          ((mwheel--is-dir-p up button)
            (global-text-scale-adjust -1)))))
 
 (defun mouse-wheel--add-binding (key fun)
@@ -507,15 +465,13 @@ an event used for scrolling, such as 
`mouse-wheel-down-event'."
      ;; Bindings for changing font size.
      ((and (consp binding) (eq (cdr binding) 'text-scale))
       (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event
-                           mouse-wheel-down-alternate-event
-                           mouse-wheel-up-alternate-event))
+                           'wheel-down 'wheel-up))
         (when event
           (mouse-wheel--add-binding `[,(append (car binding) (list event))]
                                     'mouse-wheel-text-scale))))
      ((and (consp binding) (eq (cdr binding) 'global-text-scale))
       (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event
-                           mouse-wheel-down-alternate-event
-                           mouse-wheel-up-alternate-event))
+                           'wheel-down 'wheel-up))
         (when event
           (mouse-wheel--add-binding `[,(append (car binding) (list event))]
                                     'mouse-wheel-global-text-scale))))
@@ -523,10 +479,7 @@ an event used for scrolling, such as 
`mouse-wheel-down-event'."
      (t
       (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event
                            mouse-wheel-left-event mouse-wheel-right-event
-                           mouse-wheel-down-alternate-event
-                           mouse-wheel-up-alternate-event
-                           mouse-wheel-left-alternate-event
-                           mouse-wheel-right-alternate-event))
+                           'wheel-down 'wheel-up 'wheel-left 'wheel-right))
         (when event
           (dolist (key (mouse-wheel--create-scroll-keys binding event))
             (mouse-wheel--add-binding key 'mwheel-scroll))))))))
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index 3d64b7976b3..fb723fb8878 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -1,6 +1,6 @@
 ;;; ange-ftp.el --- transparent FTP support for GNU Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1989-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989-2024 Free Software Foundation, Inc.
 
 ;; Author: Andy Norman <ange@hplb.hpl.hp.com>
 ;; Maintainer: emacs-devel@gnu.org
@@ -2164,7 +2164,7 @@ Create a new process if needed."
       proc)))
 
 (defun ange-ftp-passive-mode (proc on-or-off)
-  (if (string-match (concat "Passive mode " on-or-off)
+  (if (string-match (concat "Passive mode:? " on-or-off)
                     (cdr (ange-ftp-raw-send-cmd
                           proc (concat "passive " on-or-off)
                           "Trying passive mode..." nil)))
@@ -2850,7 +2850,8 @@ NO-ERROR, if a listing for DIRECTORY cannot be obtained."
                                   (ange-ftp-switches-ok dired-actual-switches))
                              (and (boundp 'dired-listing-switches)
                                   (ange-ftp-switches-ok
-                                   dired-listing-switches))
+                                   (connection-local-value
+                                     dired-listing-switches)))
                              "-al")
                          t no-error)
             (gethash directory ange-ftp-files-hashtable)))))
@@ -4403,40 +4404,6 @@ NEWNAME should be the name to give the new compressed or 
uncompressed file.")
          (error (signal (car err) (cdr err))))
       (ange-ftp-run-real-handler operation args))))
 
-;; The following code is commented out because Tramp now deals with
-;; Ange-FTP filenames, too.
-
-;;-;;; This regexp takes care of real ange-ftp file names (with a slash
-;;-;;; and colon).
-;;-;;; Don't allow the host name to end in a period--some systems use /.:
-;;-;;;###autoload
-;;-(or (assoc "^/[^/:]*[^/:.]:" file-name-handler-alist)
-;;-    (setq file-name-handler-alist
-;;-      (cons '("^/[^/:]*[^/:.]:" . ange-ftp-hook-function)
-;;-            file-name-handler-alist)))
-;;-
-;;-;;; This regexp recognizes absolute filenames with only one component,
-;;-;;; for the sake of hostname completion.
-;;-;;;###autoload
-;;-(or (assoc "^/[^/:]*\\'" file-name-handler-alist)
-;;-    (setq file-name-handler-alist
-;;-      (cons '("^/[^/:]*\\'" . ange-ftp-completion-hook-function)
-;;-            file-name-handler-alist)))
-;;-
-;;-;;; This regexp recognizes absolute filenames with only one component
-;;-;;; on Windows, for the sake of hostname completion.
-;;-;;; NB. Do not mark this as autoload, because it is very common to
-;;-;;; do completions in the root directory of drives on Windows.
-;;-(and (memq system-type '(ms-dos windows-nt))
-;;-     (or (assoc "^[a-zA-Z]:/[^/:]*\\'" file-name-handler-alist)
-;;-     (setq file-name-handler-alist
-;;-           (cons '("^[a-zA-Z]:/[^/:]*\\'" .
-;;-                   ange-ftp-completion-hook-function)
-;;-                 file-name-handler-alist))))
-
-;;; The above two forms are sufficient to cause this file to be loaded
-;;; if the user ever uses a file name with a colon in it.
-
 ;;; This sets the mode
 (add-hook 'find-file-hook 'ange-ftp-set-buffer-mode)
 
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el
index 74740af3bd6..359453ca433 100644
--- a/lisp/net/browse-url.el
+++ b/lisp/net/browse-url.el
@@ -1,6 +1,6 @@
 ;;; browse-url.el --- pass a URL to a web browser  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Denis Howe <dbh@doc.ic.ac.uk>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el
index f17b7388844..77b334e704e 100644
--- a/lisp/net/dbus.el
+++ b/lisp/net/dbus.el
@@ -1,6 +1,6 @@
 ;;; dbus.el --- Elisp bindings for D-Bus. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, hardware
diff --git a/lisp/net/dictionary-connection.el 
b/lisp/net/dictionary-connection.el
index 3fa675491b2..19bfbba456e 100644
--- a/lisp/net/dictionary-connection.el
+++ b/lisp/net/dictionary-connection.el
@@ -1,6 +1,6 @@
 ;;; dictionary-connection.el --- TCP-based client connection for dictionary  
-*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Torsten Hilbrich <torsten.hilbrich@gmx.net>
 ;; Keywords: network
diff --git a/lisp/net/dictionary.el b/lisp/net/dictionary.el
index d1f92334ee2..1981b757017 100644
--- a/lisp/net/dictionary.el
+++ b/lisp/net/dictionary.el
@@ -1,6 +1,6 @@
 ;;; dictionary.el --- Client for rfc2229 dictionary servers  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Torsten Hilbrich <torsten.hilbrich@gmx.net>
 ;; Keywords: interface, dictionary
diff --git a/lisp/net/dig.el b/lisp/net/dig.el
index 694a3a3a3d9..6a2e8c54e14 100644
--- a/lisp/net/dig.el
+++ b/lisp/net/dig.el
@@ -1,6 +1,6 @@
 ;;; dig.el --- Domain Name System dig interface  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 ;; Keywords: DNS BIND dig comm
diff --git a/lisp/net/dns.el b/lisp/net/dns.el
index 42e7fb415d3..23ea88ef4ad 100644
--- a/lisp/net/dns.el
+++ b/lisp/net/dns.el
@@ -1,6 +1,6 @@
 ;;; dns.el --- Domain Name Service lookups  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: network comm
diff --git a/lisp/net/eudc-bob.el b/lisp/net/eudc-bob.el
index f345a94bab4..be067452b75 100644
--- a/lisp/net/eudc-bob.el
+++ b/lisp/net/eudc-bob.el
@@ -1,6 +1,6 @@
 ;;; eudc-bob.el --- Binary Objects Support for EUDC  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Oscar Figueiredo <oscar@cpe.fr>
 ;;         Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudc-capf.el b/lisp/net/eudc-capf.el
index 6d51d572485..ac070c82cca 100644
--- a/lisp/net/eudc-capf.el
+++ b/lisp/net/eudc-capf.el
@@ -1,6 +1,6 @@
 ;;; eudc-capf.el --- EUDC - completion-at-point bindings  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Alexander Adolf
 ;; Package: eudc
diff --git a/lisp/net/eudc-export.el b/lisp/net/eudc-export.el
index 7bde976239d..9ff7979a13a 100644
--- a/lisp/net/eudc-export.el
+++ b/lisp/net/eudc-export.el
@@ -1,6 +1,6 @@
 ;;; eudc-export.el --- functions to export EUDC query results  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Oscar Figueiredo <oscar@cpe.fr>
 ;;         Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudc-hotlist.el b/lisp/net/eudc-hotlist.el
index a8b9fddde56..97f4ffe8a9c 100644
--- a/lisp/net/eudc-hotlist.el
+++ b/lisp/net/eudc-hotlist.el
@@ -1,6 +1,6 @@
 ;;; eudc-hotlist.el --- hotlist management for EUDC  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Oscar Figueiredo <oscar@cpe.fr>
 ;;         Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudc-vars.el b/lisp/net/eudc-vars.el
index b6b06f0c9fa..240385b2acf 100644
--- a/lisp/net/eudc-vars.el
+++ b/lisp/net/eudc-vars.el
@@ -1,6 +1,6 @@
 ;;; eudc-vars.el --- Emacs Unified Directory Client  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Oscar Figueiredo <oscar@cpe.fr>
 ;;         Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el
index aae7a45563d..ea90e4a7e77 100644
--- a/lisp/net/eudc.el
+++ b/lisp/net/eudc.el
@@ -1,6 +1,6 @@
 ;;; eudc.el --- Emacs Unified Directory Client  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Oscar Figueiredo <oscar@cpe.fr>
 ;;         Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudcb-bbdb.el b/lisp/net/eudcb-bbdb.el
index 37f7c65633b..78d01187556 100644
--- a/lisp/net/eudcb-bbdb.el
+++ b/lisp/net/eudcb-bbdb.el
@@ -1,6 +1,6 @@
 ;;; eudcb-bbdb.el --- Emacs Unified Directory Client - BBDB Backend  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Oscar Figueiredo <oscar@cpe.fr>
 ;;         Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudcb-ecomplete.el b/lisp/net/eudcb-ecomplete.el
index a4b7a183d25..0cf7a253727 100644
--- a/lisp/net/eudcb-ecomplete.el
+++ b/lisp/net/eudcb-ecomplete.el
@@ -1,6 +1,6 @@
 ;;; eudcb-ecomplete.el --- EUDC - ecomplete backend -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Alexander Adolf
 ;; Package: eudc
diff --git a/lisp/net/eudcb-ldap.el b/lisp/net/eudcb-ldap.el
index b1733e99f5c..c0ea840c82d 100644
--- a/lisp/net/eudcb-ldap.el
+++ b/lisp/net/eudcb-ldap.el
@@ -1,6 +1,6 @@
 ;;; eudcb-ldap.el --- Emacs Unified Directory Client - LDAP Backend  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Oscar Figueiredo <oscar@cpe.fr>
 ;;         Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudcb-mab.el b/lisp/net/eudcb-mab.el
index 805c742d9e0..2f4d210d01e 100644
--- a/lisp/net/eudcb-mab.el
+++ b/lisp/net/eudcb-mab.el
@@ -1,6 +1,6 @@
 ;;; eudcb-mab.el --- Emacs Unified Directory Client - AddressBook backend  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@newartisans.com>
 ;; Maintainer: Thomas Fitzsimmons <fitzsim@fitzsim.org>
diff --git a/lisp/net/eudcb-macos-contacts.el b/lisp/net/eudcb-macos-contacts.el
index e9ce22f4134..69c89e5a681 100644
--- a/lisp/net/eudcb-macos-contacts.el
+++ b/lisp/net/eudcb-macos-contacts.el
@@ -1,6 +1,6 @@
 ;;; eudcb-macos-contacts.el --- EUDC - macOS Contacts backend  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Alexander Adolf
 ;; Package: eudc
diff --git a/lisp/net/eudcb-mailabbrev.el b/lisp/net/eudcb-mailabbrev.el
index 196e8ff2525..1addfafdc21 100644
--- a/lisp/net/eudcb-mailabbrev.el
+++ b/lisp/net/eudcb-mailabbrev.el
@@ -1,6 +1,6 @@
 ;;; eudcb-mailabbrev.el --- EUDC - mailabbrev backend -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Alexander Adolf
 ;; Package: eudc
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 77bb6be2904..6ae1e6d3d0a 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -1,6 +1,6 @@
 ;;; eww.el --- Emacs Web Wowser  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: html
@@ -437,7 +437,7 @@ For more information, see Info node `(eww) Top'."
    ((eq eww-retrieve-command 'sync)
     (let ((data-buffer (url-retrieve-synchronously url)))
       (with-current-buffer data-buffer
-        (apply #'eww-render nil url cbargs))))
+        (apply #'eww-render nil cbargs))))
    (t
     (let ((buffer (generate-new-buffer " *eww retrieve*"))
           (error-buffer (generate-new-buffer " *eww error*")))
@@ -2064,9 +2064,10 @@ If CHARSET is nil then use UTF-8."
   "Prompt for an EWW buffer to display in the selected window."
   (interactive nil eww-mode)
   (let ((completion-extra-properties
-         '(:annotation-function (lambda (buf)
-                                  (with-current-buffer buf
-                                    (format " %s" (eww-current-url))))))
+         `(:annotation-function
+           ,(lambda (buf)
+              (with-current-buffer buf
+                (format " %s" (eww-current-url))))))
         (curbuf (current-buffer)))
     (pop-to-buffer-same-window
      (read-buffer "Switch to EWW buffer: "
diff --git a/lisp/net/gnutls.el b/lisp/net/gnutls.el
index 955172d8bb6..b0c3dcb9a70 100644
--- a/lisp/net/gnutls.el
+++ b/lisp/net/gnutls.el
@@ -1,6 +1,6 @@
 ;;; gnutls.el --- Support SSL/TLS connections through GnuTLS  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Ted Zlatanov <tzz@lifelogs.com>
 ;; Keywords: comm, tls, ssl, encryption
diff --git a/lisp/net/goto-addr.el b/lisp/net/goto-addr.el
index 57187cfce65..7c72c67f187 100644
--- a/lisp/net/goto-addr.el
+++ b/lisp/net/goto-addr.el
@@ -1,6 +1,6 @@
 ;;; goto-addr.el --- click to browse URL or to send to e-mail address  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Ding <ericding@alum.mit.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/net/hmac-def.el b/lisp/net/hmac-def.el
index 010e97dda02..3d4810a1646 100644
--- a/lisp/net/hmac-def.el
+++ b/lisp/net/hmac-def.el
@@ -1,6 +1,6 @@
 ;;; hmac-def.el --- A macro for defining HMAC functions.  -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 1999, 2001, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2001, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
 ;; Keywords: HMAC, RFC2104
diff --git a/lisp/net/hmac-md5.el b/lisp/net/hmac-md5.el
index 4d111e2b62b..1c4ac24a9c4 100644
--- a/lisp/net/hmac-md5.el
+++ b/lisp/net/hmac-md5.el
@@ -1,6 +1,6 @@
 ;;; hmac-md5.el --- Compute HMAC-MD5.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999, 2001, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2001, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
 ;; Keywords: HMAC, RFC2104, HMAC-MD5, MD5, KEYED-MD5, CRAM-MD5
diff --git a/lisp/net/imap.el b/lisp/net/imap.el
index 7de847e2a59..f10b5b8fc12 100644
--- a/lisp/net/imap.el
+++ b/lisp/net/imap.el
@@ -1,6 +1,6 @@
 ;;; imap.el --- imap library  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 ;; Keywords: mail
diff --git a/lisp/net/ldap.el b/lisp/net/ldap.el
index 5c3766a76b3..2ec3f927a40 100644
--- a/lisp/net/ldap.el
+++ b/lisp/net/ldap.el
@@ -1,6 +1,6 @@
 ;;; ldap.el --- client interface to LDAP for Emacs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Oscar Figueiredo <oscar@cpe.fr>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el
index 81cc51f1bf0..5ff75deb4e6 100644
--- a/lisp/net/mailcap.el
+++ b/lisp/net/mailcap.el
@@ -1,6 +1,6 @@
 ;;; mailcap.el --- MIME media types configuration -*- lexical-binding: t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: William M. Perry <wmperry@aventail.com>
 ;;     Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/net/mairix.el b/lisp/net/mairix.el
index 4ef179003de..9557d1a5760 100644
--- a/lisp/net/mairix.el
+++ b/lisp/net/mairix.el
@@ -1,6 +1,6 @@
 ;;; mairix.el --- Mairix interface for Emacs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: David Engster <dengste@eml.cc>
 ;; Keywords: mail searching
diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el
index cb725c0674e..83842cd6788 100644
--- a/lisp/net/net-utils.el
+++ b/lisp/net/net-utils.el
@@ -1,6 +1,6 @@
 ;;; net-utils.el --- network functions  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Peter Breton <pbreton@cs.umb.edu>
 ;; Created: Sun Mar 16 1997
diff --git a/lisp/net/network-stream.el b/lisp/net/network-stream.el
index 8cb5236ceb9..dcb3ad61f6d 100644
--- a/lisp/net/network-stream.el
+++ b/lisp/net/network-stream.el
@@ -1,6 +1,6 @@
 ;;; network-stream.el --- open network processes, possibly with encryption -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: network
diff --git a/lisp/net/newst-backend.el b/lisp/net/newst-backend.el
index 726134874ff..920111f2134 100644
--- a/lisp/net/newst-backend.el
+++ b/lisp/net/newst-backend.el
@@ -1,6 +1,6 @@
 ;;; newst-backend.el --- Retrieval backend for newsticker  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author:      Ulf Jasper <ulf.jasper@web.de>
 ;; Filename:    newst-backend.el
diff --git a/lisp/net/newst-plainview.el b/lisp/net/newst-plainview.el
index 5c734aaeb2c..6b7050a9ff0 100644
--- a/lisp/net/newst-plainview.el
+++ b/lisp/net/newst-plainview.el
@@ -1,6 +1,6 @@
 ;;; newst-plainview.el --- Single buffer frontend for newsticker.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author:      Ulf Jasper <ulf.jasper@web.de>
 ;; Filename:    newst-plainview.el
diff --git a/lisp/net/newst-reader.el b/lisp/net/newst-reader.el
index 3c79304d8dd..130e01a0deb 100644
--- a/lisp/net/newst-reader.el
+++ b/lisp/net/newst-reader.el
@@ -1,6 +1,6 @@
 ;;; newst-reader.el --- Generic RSS reader functions.  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author:      Ulf Jasper <ulf.jasper@web.de>
 ;; Filename:    newst-reader.el
diff --git a/lisp/net/newst-ticker.el b/lisp/net/newst-ticker.el
index 064b72f02c2..cd0ecd4b868 100644
--- a/lisp/net/newst-ticker.el
+++ b/lisp/net/newst-ticker.el
@@ -1,6 +1,6 @@
 ;;; newst-ticker.el --- mode line ticker for newsticker.  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author:      Ulf Jasper <ulf.jasper@web.de>
 ;; Filename:    newst-ticker.el
diff --git a/lisp/net/newst-treeview.el b/lisp/net/newst-treeview.el
index 39988ba6cfb..81b6e275ded 100644
--- a/lisp/net/newst-treeview.el
+++ b/lisp/net/newst-treeview.el
@@ -1,6 +1,6 @@
 ;;; newst-treeview.el --- Treeview frontend for newsticker.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author:      Ulf Jasper <ulf.jasper@web.de>
 ;; Filename:    newst-treeview.el
@@ -1466,7 +1466,7 @@ Move to next item unless DONT-PROCEED is non-nil."
       nil)))
 
 (defun newsticker--treeview-get-second-child (node)
-  "Get scond child of NODE."
+  "Get second child of NODE."
   (let ((children (widget-get node :children)))
     (if children
         (car (cdr children))
diff --git a/lisp/net/newsticker.el b/lisp/net/newsticker.el
index c86174b6d8e..b34c0268941 100644
--- a/lisp/net/newsticker.el
+++ b/lisp/net/newsticker.el
@@ -1,6 +1,6 @@
 ;;; newsticker.el --- A Newsticker for Emacs. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author:      Ulf Jasper <ulf.jasper@web.de>
 ;; Filename:    newsticker.el
diff --git a/lisp/net/nsm.el b/lisp/net/nsm.el
index 09f7ac52537..830dc9372ab 100644
--- a/lisp/net/nsm.el
+++ b/lisp/net/nsm.el
@@ -1,6 +1,6 @@
 ;;; nsm.el --- Network Security Manager  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: encryption, security, network
diff --git a/lisp/net/ntlm.el b/lisp/net/ntlm.el
index 3d994ed9e76..e753fe39602 100644
--- a/lisp/net/ntlm.el
+++ b/lisp/net/ntlm.el
@@ -1,6 +1,6 @@
 ;;; ntlm.el --- NTLM (NT LanManager) authentication support  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Taro Kawagishi <tarok@transpulse.org>
 ;; Maintainer: Thomas Fitzsimmons <fitzsim@fitzsim.org>
diff --git a/lisp/net/pop3.el b/lisp/net/pop3.el
index d2fdbc3ffff..27a8e904fc3 100644
--- a/lisp/net/pop3.el
+++ b/lisp/net/pop3.el
@@ -1,6 +1,6 @@
 ;;; pop3.el --- Post Office Protocol (RFC 1460) interface  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Richard L. Pieri <ratinox@peorth.gweep.net>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/net/puny.el b/lisp/net/puny.el
index 8879e34ce27..a83ede919fe 100644
--- a/lisp/net/puny.el
+++ b/lisp/net/puny.el
@@ -1,6 +1,6 @@
 ;;; puny.el --- translate non-ASCII domain names to ASCII  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: mail, net
diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el
index ecfeb9f8f84..0835d25460c 100644
--- a/lisp/net/rcirc.el
+++ b/lisp/net/rcirc.el
@@ -1,6 +1,6 @@
 ;;; rcirc.el --- default, simple IRC client          -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Ryan Yeske <rcyeske@gmail.com>
 ;; Maintainers: Ryan Yeske <rcyeske@gmail.com>,
@@ -229,6 +229,12 @@ Uninteresting lines are those whose responses are listed in
 Used as the first arg to `format-time-string'."
   :type 'string)
 
+(defcustom rcirc-log-time-format "%d-%b %H:%M "
+  "Describes how timestamps are printed in the log files.
+Used as the first arg to `format-time-string'."
+  :version "30.1"
+  :type 'string )
+
 (defcustom rcirc-input-ring-size 1024
   "Size of input history ring."
   :type 'integer)
@@ -2209,7 +2215,7 @@ disk.  PROCESS is the process object for the current 
connection."
                 (parse-iso8601-time-string time t))))
     (unless (null filename)
       (let ((cell (assoc-string filename rcirc-log-alist))
-            (line (concat (format-time-string rcirc-time-format time)
+            (line (concat (format-time-string rcirc-log-time-format time)
                           (substring-no-properties
                            (rcirc-format-response-string process sender
                                                          response target text))
diff --git a/lisp/net/rfc2104.el b/lisp/net/rfc2104.el
index ea6a5382f4e..907ec11de9c 100644
--- a/lisp/net/rfc2104.el
+++ b/lisp/net/rfc2104.el
@@ -1,6 +1,6 @@
 ;;; rfc2104.el --- RFC2104 Hashed Message Authentication Codes  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <jas@pdc.kth.se>
 ;; Keywords: mail
diff --git a/lisp/net/sasl-cram.el b/lisp/net/sasl-cram.el
index 5ae2c447ba5..ed6e00f578a 100644
--- a/lisp/net/sasl-cram.el
+++ b/lisp/net/sasl-cram.el
@@ -1,6 +1,6 @@
 ;;; sasl-cram.el --- CRAM-MD5 module for the SASL client framework  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2000, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@gnu.org>
 ;;     Kenichi OKADA <okada@opaopa.org>
diff --git a/lisp/net/sasl-digest.el b/lisp/net/sasl-digest.el
index 140758e23b0..75106fceee9 100644
--- a/lisp/net/sasl-digest.el
+++ b/lisp/net/sasl-digest.el
@@ -1,6 +1,6 @@
 ;;; sasl-digest.el --- DIGEST-MD5 module for the SASL client framework  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2000, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;;     Kenichi OKADA <okada@opaopa.org>
diff --git a/lisp/net/sasl-ntlm.el b/lisp/net/sasl-ntlm.el
index c70059ac69d..a845598b4f0 100644
--- a/lisp/net/sasl-ntlm.el
+++ b/lisp/net/sasl-ntlm.el
@@ -1,6 +1,6 @@
 ;;; sasl-ntlm.el --- NTLM (NT Lan Manager) module for the SASL client 
framework  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2000, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Taro Kawagishi <tarok@transpulse.org>
 ;; Keywords: SASL, NTLM
diff --git a/lisp/net/sasl-scram-rfc.el b/lisp/net/sasl-scram-rfc.el
index ddccf2b1425..8450f648cd9 100644
--- a/lisp/net/sasl-scram-rfc.el
+++ b/lisp/net/sasl-scram-rfc.el
@@ -1,6 +1,6 @@
 ;;; sasl-scram-rfc.el --- SCRAM-SHA-1 module for the SASL client framework  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Magnus Henoch <magnus.henoch@gmail.com>
 ;; Package: sasl
diff --git a/lisp/net/sasl-scram-sha256.el b/lisp/net/sasl-scram-sha256.el
index 27267f3c2e2..345bb6e4313 100644
--- a/lisp/net/sasl-scram-sha256.el
+++ b/lisp/net/sasl-scram-sha256.el
@@ -1,6 +1,6 @@
 ;;; sasl-scram-sha256.el --- SCRAM-SHA-256 module for the SASL client 
framework  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 ;; Package: sasl
diff --git a/lisp/net/sasl.el b/lisp/net/sasl.el
index 7fe97904a4c..621b873af59 100644
--- a/lisp/net/sasl.el
+++ b/lisp/net/sasl.el
@@ -1,6 +1,6 @@
 ;;; sasl.el --- SASL client framework  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2000, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@gnu.org>
 ;; Keywords: SASL
diff --git a/lisp/net/secrets.el b/lisp/net/secrets.el
index 08ab942fddb..c1a670fde8c 100644
--- a/lisp/net/secrets.el
+++ b/lisp/net/secrets.el
@@ -1,6 +1,6 @@
 ;;; secrets.el --- Client interface to gnome-keyring and kwallet. -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm password passphrase
diff --git a/lisp/net/shr-color.el b/lisp/net/shr-color.el
index cc2e6dc469b..9bd05381c3b 100644
--- a/lisp/net/shr-color.el
+++ b/lisp/net/shr-color.el
@@ -1,6 +1,6 @@
 ;;; shr-color.el --- Simple HTML Renderer color management  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Julien Danjou <julien@danjou.info>
 ;; Keywords: html
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index 9f030b4c743..e23fc6104d2 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -1,6 +1,6 @@
 ;;; shr.el --- Simple HTML Renderer -*- lexical-binding: t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: html
@@ -200,7 +200,7 @@ inline if it occupies less than this fraction of window 
width.
 
 HEIGHT can be also be an integer or a floating point number.  If it is an
 integer and the pixel height of an image exceeds it, the image image is
-displyed on a separate line.  If it is a float number , the limit is
+displayed on a separate line.  If it is a float number , the limit is
 interpreted as a multiple of the height of default font."
   :version "30.1"
   :type '(choice (const nil) (cons number number)))
@@ -1137,7 +1137,9 @@ element is the data blob and the second element is the 
content-type."
         (when image
           ;; The trailing space can confuse shr-insert into not
           ;; putting any space after inline images.
-         (setq alt (string-trim alt))
+          ;; ALT may be nil when visiting image URLs in eww
+          ;; (bug#67764).
+         (setq alt (if alt (string-trim alt) "*"))
          ;; When inserting big-ish pictures, put them at the
          ;; beginning of the line.
          (let ((inline (shr--inline-image-p image)))
@@ -1146,8 +1148,8 @@ element is the data blob and the second element is the 
content-type."
                (insert "\n"))
            (let ((image-pos (point)))
              (if (eq size 'original)
-                 (insert-sliced-image image (or alt "*") nil 20 1)
-               (insert-image image (or alt "*")))
+                 (insert-sliced-image image alt nil 20 1)
+               (insert-image image alt))
              (put-text-property start (point) 'image-size size)
              (when (and (not inline) shr-max-inline-image-size)
                (insert "\n"))
@@ -1435,13 +1437,85 @@ ones, in case fg and bg are nil."
        (shr-dom-print elem)))))
   (insert (format "</%s>" (dom-tag dom))))
 
+(defconst shr-correct-attribute-case
+  '((attributename . attributeName)
+    (attributetype . attributeType)
+    (basefrequency . baseFrequency)
+    (baseprofile . baseProfile)
+    (calcmode . calcMode)
+    (clippathunits . clipPathUnits)
+    (diffuseconstant . diffuseConstant)
+    (edgemode . edgeMode)
+    (filterunits . filterUnits)
+    (glyphref . glyphRef)
+    (gradienttransform . gradientTransform)
+    (gradientunits . gradientUnits)
+    (kernelmatrix . kernelMatrix)
+    (kernelunitlength . kernelUnitLength)
+    (keypoints . keyPoints)
+    (keysplines . keySplines)
+    (keytimes . keyTimes)
+    (lengthadjust . lengthAdjust)
+    (limitingconeangle . limitingConeAngle)
+    (markerheight . markerHeight)
+    (markerunits . markerUnits)
+    (markerwidth . markerWidth)
+    (maskcontentunits . maskContentUnits)
+    (maskunits . maskUnits)
+    (numoctaves . numOctaves)
+    (pathlength . pathLength)
+    (patterncontentunits . patternContentUnits)
+    (patterntransform . patternTransform)
+    (patternunits . patternUnits)
+    (pointsatx . pointsAtX)
+    (pointsaty . pointsAtY)
+    (pointsatz . pointsAtZ)
+    (preservealpha . preserveAlpha)
+    (preserveaspectratio . preserveAspectRatio)
+    (primitiveunits . primitiveUnits)
+    (refx . refX)
+    (refy . refY)
+    (repeatcount . repeatCount)
+    (repeatdur . repeatDur)
+    (requiredextensions . requiredExtensions)
+    (requiredfeatures . requiredFeatures)
+    (specularconstant . specularConstant)
+    (specularexponent . specularExponent)
+    (spreadmethod . spreadMethod)
+    (startoffset . startOffset)
+    (stddeviation . stdDeviation)
+    (stitchtiles . stitchTiles)
+    (surfacescale . surfaceScale)
+    (systemlanguage . systemLanguage)
+    (tablevalues . tableValues)
+    (targetx . targetX)
+    (targety . targetY)
+    (textlength . textLength)
+    (viewbox . viewBox)
+    (viewtarget . viewTarget)
+    (xchannelselector . xChannelSelector)
+    (ychannelselector . yChannelSelector)
+    (zoomandpan . zoomAndPan))
+  "Attributes for correcting the case in SVG and MathML.
+Based on 
https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inforeign .")
+
+(defun shr-correct-dom-case (dom)
+  "Correct the case for SVG segments."
+  (dolist (attr (dom-attributes dom))
+    (when-let ((rep (assoc-default (car attr) shr-correct-attribute-case)))
+      (setcar attr rep)))
+  (dolist (child (dom-children dom))
+    (shr-correct-dom-case child))
+  dom)
+
 (defun shr-tag-svg (dom)
   (when (and (image-type-available-p 'svg)
             (not shr-inhibit-images)
              (dom-attr dom 'width)
              (dom-attr dom 'height))
-    (funcall shr-put-image-function (list (shr-dom-to-xml dom 'utf-8)
-                                          'image/svg+xml)
+    (funcall shr-put-image-function
+            (list (shr-dom-to-xml (shr-correct-dom-case dom) 'utf-8)
+                   'image/svg+xml)
             "SVG Image")))
 
 (defun shr-tag-sup (dom)
diff --git a/lisp/net/sieve-manage.el b/lisp/net/sieve-manage.el
index 81f50e74987..0faeb02bcfd 100644
--- a/lisp/net/sieve-manage.el
+++ b/lisp/net/sieve-manage.el
@@ -1,6 +1,6 @@
 ;;; sieve-manage.el --- Implementation of the managesieve protocol in elisp  
-*- lexical-binding:t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 ;;         Albert Krewinkel <tarleb@moltkeplatz.de>
@@ -171,8 +171,8 @@ Valid states are `closed', `initial', `nonauth', and 
`auth'.")
   "Append ARGS to sieve-manage log buffer.
 
 ARGS can be a string or a list of strings.
-The buffer to use for logging is specifified via
-`sieve-manage-log'. If it is nil, logging is disabled."
+The buffer to use for logging is specified via `sieve-manage-log'.
+If it is nil, logging is disabled."
   (when sieve-manage-log
     (with-current-buffer (or (get-buffer sieve-manage-log)
                              (with-current-buffer
diff --git a/lisp/net/sieve-mode.el b/lisp/net/sieve-mode.el
index a1ad0bffddc..4fbdd183973 100644
--- a/lisp/net/sieve-mode.el
+++ b/lisp/net/sieve-mode.el
@@ -1,6 +1,6 @@
 ;;; sieve-mode.el --- Sieve code editing commands for Emacs  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 
diff --git a/lisp/net/sieve.el b/lisp/net/sieve.el
index fbd07dee27c..fddc6e21bcc 100644
--- a/lisp/net/sieve.el
+++ b/lisp/net/sieve.el
@@ -1,6 +1,6 @@
 ;;; sieve.el --- Utilities to manage sieve scripts  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 
diff --git a/lisp/net/snmp-mode.el b/lisp/net/snmp-mode.el
index 24f6bd8ae57..016b7a39d9d 100644
--- a/lisp/net/snmp-mode.el
+++ b/lisp/net/snmp-mode.el
@@ -1,6 +1,6 @@
 ;;; snmp-mode.el --- SNMP & SNMPv2 MIB major mode  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1995, 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Paul D. Smith <psmith@BayNetworks.com>
 ;; Keywords: data
diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el
index b2bb59a25a0..de04d58ed18 100644
--- a/lisp/net/soap-client.el
+++ b/lisp/net/soap-client.el
@@ -1,6 +1,6 @@
 ;;; soap-client.el --- Access SOAP web services       -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Alexandru Harsanyi <AlexHarsanyi@gmail.com>
 ;; Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
@@ -1956,7 +1956,7 @@ This is a specialization of `soap-decode-type' for
                                   (xml-get-children node (intern e-name)))
                               ;; e-name is nil so a) we don't know which
                               ;; children to operate on, and b) we want to
-                              ;; re-use soap-decode-xs-complex-type, which
+                              ;; reuse soap-decode-xs-complex-type, which
                               ;; expects a node argument with a complex
                               ;; type; therefore we need to operate on the
                               ;; entire node.  We wrap node in a list so
diff --git a/lisp/net/soap-inspect.el b/lisp/net/soap-inspect.el
index 97e962dfae5..c7e9d477a78 100644
--- a/lisp/net/soap-inspect.el
+++ b/lisp/net/soap-inspect.el
@@ -1,6 +1,6 @@
 ;;; soap-inspect.el --- Interactive WSDL inspector    -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Alexandru Harsanyi <AlexHarsanyi@gmail.com>
 ;; Created: October 2010
diff --git a/lisp/net/socks.el b/lisp/net/socks.el
index e572e5c9bdf..ecbac7e2345 100644
--- a/lisp/net/socks.el
+++ b/lisp/net/socks.el
@@ -1,6 +1,6 @@
 ;;; socks.el --- A Socks v5 Client for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1996-2000, 2002, 2007-2023 Free Software Foundation,
+;; Copyright (C) 1996-2000, 2002, 2007-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: William M. Perry <wmperry@gnu.org>
diff --git a/lisp/net/telnet.el b/lisp/net/telnet.el
index fbe9af3d6a5..d0008501ea3 100644
--- a/lisp/net/telnet.el
+++ b/lisp/net/telnet.el
@@ -1,6 +1,6 @@
 ;;; telnet.el --- run a telnet session from within an Emacs buffer  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Author: William F. Schelter
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index e4d3ba8c74b..2e4ad1cc412 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -1,6 +1,6 @@
 ;;; tramp-adb.el --- Functions for calling Android Debug Bridge from Tramp  
-*- lexical-binding:t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Jürgen Hötzel <juergen@archlinux.org>
 ;; Keywords: comm, processes
diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el
index 590544f199f..298cacdb0e0 100644
--- a/lisp/net/tramp-archive.el
+++ b/lisp/net/tramp-archive.el
@@ -1,6 +1,6 @@
 ;;; tramp-archive.el --- Tramp archive manager  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el
index 6ecb80f09b2..25123a6e282 100644
--- a/lisp/net/tramp-cache.el
+++ b/lisp/net/tramp-cache.el
@@ -1,6 +1,6 @@
 ;;; tramp-cache.el --- file information caching for Tramp  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2000, 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Daniel Pittman <daniel@inanna.danann.net>
 ;;         Michael Albinus <michael.albinus@gmx.de>
@@ -340,7 +340,7 @@ Preserve timestamps."
   (declare (indent 3) (debug t))
   `(progn
      ;; Unify localname.  Remove hop from `tramp-file-name' structure.
-     (setq ,key (tramp-file-name-unify ,key ,file))
+     (setf ,key (tramp-file-name-unify ,key ,file))
      (let* ((hash (tramp-get-hash-table ,key))
            (cached (and (hash-table-p hash) (gethash ,property hash))))
        (unwind-protect (progn ,@body)
@@ -358,7 +358,7 @@ Preserve timestamps."
   (declare (indent 3) (debug t))
   `(progn
      ;; Unify localname.  Remove hop from `tramp-file-name' structure.
-     (setq ,key (tramp-file-name-unify ,key ,file))
+     (setf ,key (tramp-file-name-unify ,key ,file))
      (let* ((hash (tramp-get-hash-table ,key))
            (values
             (and (hash-table-p hash)
@@ -474,7 +474,7 @@ used to cache connection properties of the local machine."
   "Save PROPERTY, run BODY, reset PROPERTY."
   (declare (indent 2) (debug t))
   `(progn
-     (setq ,key (tramp-file-name-unify ,key))
+     (setf ,key (tramp-file-name-unify ,key))
      (let* ((hash (tramp-get-hash-table ,key))
            (cached (and (hash-table-p hash)
                         (gethash ,property hash tramp-cache-undefined))))
@@ -491,7 +491,7 @@ used to cache connection properties of the local machine."
 PROPERTIES is a list of file properties (strings)."
   (declare (indent 2) (debug t))
   `(progn
-     (setq ,key (tramp-file-name-unify ,key))
+     (setf ,key (tramp-file-name-unify ,key))
      (let* ((hash (tramp-get-hash-table ,key))
            (values
             (mapcar
diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el
index f56c93c370d..a545a8e7273 100644
--- a/lisp/net/tramp-cmds.el
+++ b/lisp/net/tramp-cmds.el
@@ -1,6 +1,6 @@
 ;;; tramp-cmds.el --- Interactive commands for Tramp  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el
index 7c10c6530e9..87b20b982f9 100644
--- a/lisp/net/tramp-compat.el
+++ b/lisp/net/tramp-compat.el
@@ -1,6 +1,6 @@
 ;;; tramp-compat.el --- Tramp compatibility functions  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
@@ -61,6 +61,7 @@
 ;; avoid them in cases we know what we do.
 (defmacro tramp-compat-funcall (function &rest arguments)
   "Call FUNCTION with ARGUMENTS if it exists.  Do not raise compiler warnings."
+  (declare (indent 1) (debug t))
   `(when (functionp ,function)
      (with-no-warnings (funcall ,function ,@arguments))))
 
@@ -306,6 +307,16 @@ Also see `ignore'."
       ?\N{KHMER SIGN CAMNUC PII KUUH})
     "List of characters equivalent to trailing colon in \"password\" 
prompts."))
 
+;; Macro `connection-local-p' is new in Emacs 30.1.
+(if (macrop 'connection-local-p)
+    (defalias 'tramp-compat-connection-local-p #'connection-local-p)
+  (defmacro tramp-compat-connection-local-p (variable)
+    "Non-nil if VARIABLE has a connection-local binding in 
`default-directory'."
+    `(let (connection-local-variables-alist file-local-variables-alist)
+       (hack-connection-local-variables
+       (connection-local-criteria-for-default-directory))
+       (and (assq ',variable connection-local-variables-alist) t))))
+
 (dolist (elt (all-completions "tramp-compat-" obarray 'functionp))
   (function-put (intern elt) 'tramp-suppress-trace t))
 
@@ -319,6 +330,16 @@ Also see `ignore'."
 ;;; TODO:
 ;;
 ;; * Starting with Emacs 27.1, there's no need to escape open
-;;   parentheses with a backslash in docstrings anymore.
+;;   parentheses with a backslash in docstrings anymore.  However,
+;;   `outline-minor-mode' has still problems with this.  Since there
+;;   are developers using `outline-minor-mode' in Lisp files, we still
+;;   keep this quoting.
+;;
+;; * Starting with Emacs 29.1, use `buffer-match-p'.
+;;
+;; * Starting with Emacs 30.1, there is `handler-bind'.  Use it
+;;   instead of `condition-case' when the origin of an error shall be
+;;   kept, for example when the HANDLER propagates the error with
+;;   `(signal (car err) (cdr err)'.
 
 ;;; tramp-compat.el ends here
diff --git a/lisp/net/tramp-container.el b/lisp/net/tramp-container.el
index 7383ea583cb..1f578949e4d 100644
--- a/lisp/net/tramp-container.el
+++ b/lisp/net/tramp-container.el
@@ -1,6 +1,6 @@
 ;;; tramp-container.el --- Tramp integration for Docker-like containers  -*- 
lexical-binding: t; -*-
 
-;; Copyright © 2022-2023 Free Software Foundation, Inc.
+;; Copyright © 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Brian Cully <bjc@kublai.com>
 ;; Keywords: comm, processes
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
index 587b9db067a..a7af64bff5c 100644
--- a/lisp/net/tramp-crypt.el
+++ b/lisp/net/tramp-crypt.el
@@ -1,6 +1,6 @@
 ;;; tramp-crypt.el --- Tramp crypt utilities  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
@@ -148,6 +148,8 @@ If NAME doesn't belong to an encrypted remote directory, 
return nil."
     (and tramp-crypt-enabled (stringp name)
         (not (file-name-quoted-p name))
         (not (string-suffix-p tramp-crypt-encfs-config name))
+        ;; No lock file name.
+        (not (string-prefix-p ".#" (file-name-nondirectory name)))
         (dolist (dir tramp-crypt-directories)
           (and (string-prefix-p
                 dir (file-name-as-directory (expand-file-name name)))
@@ -157,7 +159,7 @@ If NAME doesn't belong to an encrypted remote directory, 
return nil."
 ;; New handlers should be added here.
 ;;;###tramp-autoload
 (defconst tramp-crypt-file-name-handler-alist
-  '(;; `abbreviate-file-name' performed by default handler.
+  '((abbreviate-file-name . identity)
     (access-file . tramp-crypt-handle-access-file)
     (add-name-to-file . tramp-handle-add-name-to-file)
     ;; `byte-compiler-base-file-name' performed by default handler.
@@ -492,7 +494,7 @@ See `tramp-crypt-do-encrypt-or-decrypt-file'."
 
 ;;;###tramp-autoload
 (defun tramp-crypt-add-directory (name)
-  "Mark remote directory NAME for encryption.
+  "Mark expanded remote directory NAME for encryption.
 Files in that directory and all subdirectories will be encrypted
 before copying to, and decrypted after copying from that
 directory.  File names will be also encrypted."
@@ -516,7 +518,7 @@ directory.  File names will be also encrypted."
  #'tramp-crypt-command-completion-p)
 
 (defun tramp-crypt-remove-directory (name)
-  "Unmark remote directory NAME for encryption.
+  "Unmark expanded remote directory NAME for encryption.
 Existing files in that directory and its subdirectories will be
 kept in their encrypted form."
   ;; (declare (completion tramp-crypt-command-completion-p))
@@ -853,6 +855,23 @@ WILDCARD is not supported."
     (tramp-compat-funcall
      'unlock-file (tramp-crypt-encrypt-file-name filename))))
 
+(defun tramp-crypt-cleanup-connection (vec)
+  "Cleanup crypt resources determined by VEC."
+  (let ((tramp-cleanup-connection-hook
+        (remove
+         #'tramp-crypt-cleanup-connection tramp-cleanup-connection-hook))
+       (tramp-crypt-enabled t))
+    (dolist (dir tramp-crypt-directories)
+      (when (tramp-file-name-equal-p vec (tramp-dissect-file-name dir))
+       (tramp-cleanup-connection (tramp-crypt-dissect-file-name dir))))))
+
+;; Add cleanup hooks.
+(add-hook 'tramp-cleanup-connection-hook #'tramp-crypt-cleanup-connection)
+(add-hook 'tramp-crypt-unload-hook
+         (lambda ()
+           (remove-hook 'tramp-cleanup-connection-hook
+                        #'tramp-crypt-cleanup-connection)))
+
 (with-eval-after-load 'bookmark
   (add-hook 'bookmark-inhibit-context-functions
            #'tramp-crypt-file-name-p)
diff --git a/lisp/net/tramp-ftp.el b/lisp/net/tramp-ftp.el
index 1712c00b0a0..28ef8c67777 100644
--- a/lisp/net/tramp-ftp.el
+++ b/lisp/net/tramp-ftp.el
@@ -1,6 +1,6 @@
 ;;; tramp-ftp.el --- Tramp convenience functions for Ange-FTP  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
diff --git a/lisp/net/tramp-fuse.el b/lisp/net/tramp-fuse.el
index 30516ce9ecc..3d42948043c 100644
--- a/lisp/net/tramp-fuse.el
+++ b/lisp/net/tramp-fuse.el
@@ -1,6 +1,6 @@
 ;;; tramp-fuse.el --- Tramp access functions for FUSE mounts  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 35778aca6d4..72589e7ce4a 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1,6 +1,6 @@
 ;;; tramp-gvfs.el --- Tramp access functions for GVFS daemon  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el
index f67d8a0ec2f..c0b60f57e40 100644
--- a/lisp/net/tramp-integration.el
+++ b/lisp/net/tramp-integration.el
@@ -1,6 +1,6 @@
 ;;; tramp-integration.el --- Tramp integration into other packages  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
diff --git a/lisp/net/tramp-message.el b/lisp/net/tramp-message.el
index 8afc8d5fd87..96071e626a5 100644
--- a/lisp/net/tramp-message.el
+++ b/lisp/net/tramp-message.el
@@ -1,6 +1,6 @@
 ;;; tramp-message.el --- Tramp messages  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
@@ -515,7 +515,7 @@ This shouldn't be changed globally, but let-bind where 
needed.")
 Bound in `tramp-*-file-name-handler' functions.")
 
 (defun tramp-debug-message-buttonize (position)
-  "Buttonize function in current buffer, at next line starting after POSTION."
+  "Buttonize function in current buffer, at next line starting after POSITION."
   (declare (tramp-suppress-trace t))
   (save-excursion
     (goto-char position)
diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el
index c2b84845f68..ced3c1b5aa8 100644
--- a/lisp/net/tramp-rclone.el
+++ b/lisp/net/tramp-rclone.el
@@ -1,6 +1,6 @@
 ;;; tramp-rclone.el --- Tramp access functions to cloud storages  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 3b47dafcb46..6bb1d976ec5 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1,6 +1,6 @@
 ;;; tramp-sh.el --- Tramp access functions for (s)sh-like connections  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; (copyright statements below in code to be updated with the above notice)
 
@@ -521,8 +521,8 @@ The string is used in `tramp-methods'.")
  (tramp-set-completion-function "fcp" tramp-completion-function-alist-ssh))
 
 (defcustom tramp-sh-extra-args
-  `((,(rx "/bash" eos) . "-noediting -norc -noprofile")
-    (,(rx "/zsh" eos) . "-f +Z -V"))
+  `((,(rx (| bos "/") "bash" eos) . "-noediting -norc -noprofile")
+    (,(rx (| bos "/") "zsh" eos) . "-f +Z -V"))
   "Alist specifying extra arguments to pass to the remote shell.
 Entries are (REGEXP . ARGS) where REGEXP is a regular expression
 matching the shell file name and ARGS is a string specifying the
@@ -533,7 +533,7 @@ This variable is only used when Tramp needs to start up 
another shell
 for tilde expansion.  The extra arguments should typically prevent the
 shell from reading its init file."
   :group 'tramp
-  :version "27.1"
+  :version "30.1"
   :type '(alist :key-type regexp :value-type string))
 
 (defconst tramp-actions-before-shell
@@ -1239,7 +1239,7 @@ Operations not mentioned here will be handled by the 
normal Emacs functions.")
       (with-current-buffer (tramp-get-connection-buffer v)
        (goto-char (point-min))
        (tramp-set-file-property v localname "file-symlink-marker" (read 
(current-buffer)))
-       ;; We cannote call `read', the file name isn't quoted.
+       ;; We cannot call `read', the file name isn't quoted.
        (forward-line)
        (buffer-substring (point) (line-end-position))))
 
@@ -2523,7 +2523,7 @@ The method used must be an out-of-band method."
                      (tramp-get-connection-name v)
                      (tramp-get-connection-buffer v)
                      copy-program copy-args)))
-               ;; This is neded for ssh or PuTTY based processes, and
+               ;; This is needed for ssh or PuTTY based processes, and
                ;; only if the respective options are set.  Perhaps,
                ;; the setting could be more fine-grained.
                ;; (process-put p 'tramp-shared-socket t)
@@ -2877,7 +2877,16 @@ the result will be a local, non-Tramp, file name."
                (tramp-run-real-handler
                 #'expand-file-name (list localname))))))))))
 
-;;; Remote commands:
+;;; Remote processes:
+
+(defcustom tramp-pipe-stty-settings "-icanon min 1 time 0"
+  "How to prevent blocking read in pipeline processes.
+This is used in `make-process' with `connection-type' `pipe'."
+  :group 'tramp
+  :version "29.3"
+  :type '(choice (const :tag "Use size limit" "-icanon min 1 time 0")
+                (const :tag "Use timeout" "-icanon min 0 time 1")
+                string))
 
 ;; We use BUFFER also as connection buffer during setup.  Because of
 ;; this, its original contents must be saved, and restored once
@@ -3089,12 +3098,21 @@ implementation will be used."
                              ;; otherwise strings larger than 4096
                              ;; bytes, sent by the process, could
                              ;; block, see termios(3) and Bug#61341.
+                             ;; In order to prevent blocking read
+                             ;; from pipe processes, "stty -icanon"
+                             ;; is used.  By default, it expects at
+                             ;; least one character to read.  When a
+                             ;; process does not read from stdin,
+                             ;; like magit, it should set a timeout
+                             ;; instead. See`tramp-pipe-stty-settings'.
+                             ;; (Bug#62093)
                              ;; 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-send-command
+                              v (format
+                                 "stty %s %s"
+                                 (if (tramp-check-remote-uname v "Darwin")
+                                     "" "-icrnl")
+                                 tramp-pipe-stty-settings)))
                            ;; `tramp-maybe-open-connection' and
                            ;; `tramp-send-command-and-read' could
                            ;; have trashed the connection buffer.
@@ -3634,20 +3652,20 @@ filled are described in `tramp-bundle-read-file-names'."
 
     (dolist
        (elt
-        (ignore-errors
+        (with-current-buffer (tramp-get-connection-buffer vec)
           ;; We cannot use `tramp-send-command-and-read', because
           ;; this does not cooperate well with heredoc documents.
-          (tramp-send-command
-           vec
-           (format
-            "tramp_bundle_read_file_names <<'%s'\n%s\n%s\n"
-            tramp-end-of-heredoc
-            (mapconcat #'tramp-shell-quote-argument files "\n")
-            tramp-end-of-heredoc))
-          (with-current-buffer (tramp-get-connection-buffer vec)
-            ;; Read the expression.
-            (goto-char (point-min))
-            (read (current-buffer)))))
+          (unless (tramp-send-command-and-check
+                   vec
+                   (format
+                    "tramp_bundle_read_file_names <<'%s'\n%s\n%s\n"
+                    tramp-end-of-heredoc
+                    (mapconcat #'tramp-shell-quote-argument files "\n")
+                    tramp-end-of-heredoc))
+            (tramp-error vec 'file-error "%s" (tramp-get-buffer-string)))
+          ;; Read the expression.
+          (goto-char (point-min))
+          (read (current-buffer))))
 
       (tramp-set-file-property vec (car elt) "file-exists-p" (nth 1 elt))
       (tramp-set-file-property vec (car elt) "file-readable-p" (nth 2 elt))
@@ -3847,7 +3865,7 @@ Fall back to normal file name handler if no Tramp handler 
exists."
           v 'file-notify-error
           "`%s' failed to start on remote host"
           (string-join sequence " "))
-       ;; This is neded for ssh or PuTTY based processes, and only if
+       ;; This is needed for ssh or PuTTY based processes, and only if
        ;; the respective options are set.  Perhaps, the setting could
        ;; be more fine-grained.
        ;; (process-put p 'tramp-shared-socket t)
@@ -4094,7 +4112,7 @@ Only send the definition if it has not already been done."
     (unless (member name scripts)
       (with-tramp-progress-reporter
          vec 5 (format-message "Sending script `%s'" name)
-       ;; In bash, leading TABs like in `tramp-vc-registered-read-file-names'
+       ;; In bash, leading TABs like in `tramp-bundle-read-file-names'
        ;; could result in unwanted command expansion.  Avoid this.
        (setq script (tramp-compat-string-replace
                      (make-string 1 ?\t) (make-string 8 ? ) script))
@@ -4175,18 +4193,6 @@ This function expects to be in the right *tramp* buffer."
 ;; On hydra.nixos.org, the $PATH environment variable is too long to
 ;; send it.  This is likely not due to PATH_MAX, but PIPE_BUF.  We
 ;; check it, and use a temporary file in case of.  See Bug#33781.
-
-;; The PIPE_BUF in POSIX [1] can be as low as 512 [2]. Here are the values
-;; on various platforms:
-;;   - 512 on macOS, FreeBSD, NetBSD, OpenBSD, MirBSD, native Windows.
-;;   - 4 KiB on Linux, OSF/1, Cygwin, Haiku.
-;;   - 5 KiB on Solaris.
-;;   - 8 KiB on HP-UX, Plan9.
-;;   - 10 KiB on IRIX.
-;;   - 32 KiB on AIX, Minix.
-;; [1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
-;; [2] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html
-;; See Bug#65324.
 (defun tramp-set-remote-path (vec)
   "Set the remote environment PATH to existing directories.
 I.e., for each directory in `tramp-remote-path', it is tested
@@ -4196,13 +4202,7 @@ variable PATH."
         (format
          "PATH=%s && export PATH"
          (string-join (tramp-get-remote-path vec) ":")))
-       (pipe-buf
-        (with-tramp-connection-property vec "pipe-buf"
-          (tramp-send-command-and-read
-           vec
-            (format "getconf PIPE_BUF / 2>%s || echo 4096"
-                    (tramp-get-remote-null-device vec))
-            'noerror)))
+       (pipe-buf (tramp-get-remote-pipe-buf vec))
        tmpfile chunk chunksize)
     (tramp-message vec 5 "Setting $PATH environment variable")
     (if (tramp-compat-length< command pipe-buf)
@@ -5255,7 +5255,7 @@ connection if a previous connection has died for some 
reason."
                              (and tramp-encoding-command-interactive
                                   `(,tramp-encoding-command-interactive)))))))
 
-                 ;; This is neded for ssh or PuTTY based processes,
+                 ;; This is needed for ssh or PuTTY based processes,
                  ;; and only if the respective options are set.
                  ;; Perhaps, the setting could be more fine-grained.
                  ;; (process-put p 'tramp-shared-socket t)
@@ -5354,7 +5354,7 @@ connection if a previous connection has died for some 
reason."
                              "2>" (tramp-get-remote-null-device previous-hop))
                          ?l (concat remote-shell " " extra-args " -i"))
                         ;; A restricted shell does not allow "exec".
-                        (when r-shell '("&&" "exit" "||" "exit")))
+                        (when r-shell '("&&" "exit")) '("||" "exit"))
                        " "))
 
                      ;; Send the command.
@@ -5597,6 +5597,7 @@ raises an error."
   "Check whether REGEXP matches the connection property \"uname\"."
   (string-match-p regexp (tramp-get-connection-property vec "uname" "")))
 
+;;;###tramp-autoload
 (defun tramp-get-remote-path (vec)
   "Compile list of remote directories for PATH.
 Nonexistent directories are removed from spec."
@@ -5680,6 +5681,27 @@ Nonexistent directories are removed from spec."
           (lambda (x) (not (tramp-get-file-property vec x "file-directory-p")))
           remote-path))))))
 
+;; The PIPE_BUF in POSIX [1] can be as low as 512 [2]. Here are the values
+;; on various platforms:
+;;   - 512 on macOS, FreeBSD, NetBSD, OpenBSD, MirBSD, native Windows.
+;;   - 4 KiB on Linux, OSF/1, Cygwin, Haiku.
+;;   - 5 KiB on Solaris.
+;;   - 8 KiB on HP-UX, Plan9.
+;;   - 10 KiB on IRIX.
+;;   - 32 KiB on AIX, Minix.
+;; [1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
+;; [2] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html
+;; See Bug#65324.
+;;;###tramp-autoload
+(defun tramp-get-remote-pipe-buf (vec)
+  "Return PIPE_BUF config from the remote side."
+  (with-tramp-connection-property vec "pipe-buf"
+    (tramp-send-command-and-read
+     vec
+     (format "getconf PIPE_BUF / 2>%s || echo 4096"
+             (tramp-get-remote-null-device vec))
+     'noerror)))
+
 (defun tramp-get-remote-locale (vec)
   "Determine remote locale, supporting UTF8 if possible."
   (with-tramp-connection-property vec "locale"
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index 87fbb93e810..3616cad2fb3 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -1,6 +1,6 @@
 ;;; tramp-smb.el --- Tramp access functions for SMB servers  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
diff --git a/lisp/net/tramp-sshfs.el b/lisp/net/tramp-sshfs.el
index 102ba637f55..8dad599c7e7 100644
--- a/lisp/net/tramp-sshfs.el
+++ b/lisp/net/tramp-sshfs.el
@@ -1,6 +1,6 @@
 ;;; tramp-sshfs.el --- Tramp access functions via sshfs  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index 742b8128199..0c717c4a5aa 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -1,6 +1,6 @@
 ;;; tramp-sudoedit.el --- Functions for accessing under root permissions  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
diff --git a/lisp/net/tramp-uu.el b/lisp/net/tramp-uu.el
index e7527f06e81..025c9d62890 100644
--- a/lisp/net/tramp-uu.el
+++ b/lisp/net/tramp-uu.el
@@ -1,6 +1,6 @@
 ;;; tramp-uu.el --- uuencode in Lisp  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
 ;; Maintainer: Michael Albinus <michael.albinus@gmx.de>
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 3baad82dda1..74d95757e46 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -1,6 +1,6 @@
 ;;; tramp.el --- Transparent Remote Access, Multiple Protocol  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
 ;;         Michael Albinus <michael.albinus@gmx.de>
@@ -219,7 +219,7 @@ pair of the form (KEY VALUE).  The following KEYs are 
defined:
     set this to any value other than \"/bin/sh\": Tramp wants to
     use a shell which groks tilde expansion, but it can search
     for it.  Also note that \"/bin/sh\" exists on all Unixen
-    except Andtoid, this might not be true for the value that you
+    except Android, this might not be true for the value that you
     decide to use.  You Have Been Warned.
 
   * `tramp-remote-shell-login'
@@ -1085,10 +1085,10 @@ Derived from `tramp-postfix-host-format'.")
 (defconst tramp-localname-regexp (rx (* (not (any "\r\n"))) eos)
   "Regexp matching localnames.")
 
-(defconst tramp-unknown-id-string "UNKNOWN"
+(defvar tramp-unknown-id-string "UNKNOWN"
   "String used to denote an unknown user or group.")
 
-(defconst tramp-unknown-id-integer -1
+(defvar tramp-unknown-id-integer -1
   "Integer used to denote an unknown user or group.")
 
 ;;;###tramp-autoload
@@ -1205,14 +1205,7 @@ The `ftp' syntax does not support methods.")
       ;; FIXME: This shouldn't be necessary.
       (rx bos "/" (? "[" (* (not "]"))) eos)
     (rx
-     bos
-     ;; `file-name-completion' uses absolute paths for matching.
-     ;; This means that on W32 systems, something like
-     ;; "/ssh:host:~/path" becomes "c:/ssh:host:~/path".  See also
-     ;; `tramp-drop-volume-letter'.
-     (? (regexp tramp-volume-letter-regexp))
-     ;; We cannot use `tramp-prefix-regexp', because it starts with `bol'.
-     (literal tramp-prefix-format)
+     (regexp tramp-prefix-regexp)
 
      ;; Optional multi-hops.
      (* (regexp tramp-remote-file-name-spec-regexp)
@@ -2081,7 +2074,7 @@ without a visible progress reporter."
 (defmacro with-tramp-timeout (list &rest body)
   "Like `with-timeout', but allow SECONDS to be nil.
 
-(fn (SECONDS TIMEOUT-FORMS...) BODY)"
+\(fn (SECONDS TIMEOUT-FORMS...) BODY)"
   (declare (indent 1) (debug ((form body) body)))
   (let ((seconds (car list))
        (timeout-forms (cdr list)))
@@ -2666,7 +2659,7 @@ not in completion mode."
            (string-match-p (rx (regexp tramp-postfix-host-regexp) eos) dir))
       (concat dir filename))
      ((string-match-p
-       (rx bos (regexp tramp-prefix-regexp)
+       (rx (regexp tramp-prefix-regexp)
           (* (regexp tramp-remote-file-name-spec-regexp)
              (regexp tramp-postfix-hop-regexp))
           (? (regexp tramp-method-regexp) (regexp tramp-postfix-method-regexp)
@@ -3198,7 +3191,7 @@ Host is always \"localhost\"."
          (when (zerop (tramp-call-process nil "getent" nil t nil "passwd"))
            (goto-char (point-min))
            (cl-loop while (not (eobp)) collect
-                    (tramp-parse-etc-group-group))))
+                    (tramp-parse-passwd-group))))
       (tramp-parse-file filename #'tramp-parse-passwd-group))))
 
 (defun tramp-parse-passwd-group ()
@@ -3328,7 +3321,7 @@ BODY is the backend specific code."
     (with-parsed-tramp-file-name (expand-file-name ,directory) nil
       (tramp-barf-if-file-missing v ,directory
        (when (file-directory-p ,directory)
-         (setq ,directory
+         (setf ,directory
                (file-name-as-directory (expand-file-name ,directory)))
          (let ((temp
                 (with-tramp-file-property v localname "directory-files" 
,@body))
@@ -3499,7 +3492,7 @@ on the same host.  Otherwise, TARGET is quoted."
      (let ((non-essential t))
        (when (and (tramp-tramp-file-p ,target)
                  (tramp-file-name-equal-p v (tramp-dissect-file-name ,target)))
-        (setq ,target (tramp-file-local-name (expand-file-name ,target))))
+        (setf ,target (tramp-file-local-name (expand-file-name ,target))))
        ;; There could be a cyclic link.
        (tramp-flush-file-properties
        v (expand-file-name ,target (tramp-file-local-name default-directory))))
@@ -4849,7 +4842,12 @@ a connection-local variable."
        (unless (or (null stderr) (bufferp stderr))
          (signal 'wrong-type-argument (list #'bufferp stderr)))
 
-       (let* ((buffer
+       ;; Check for `tramp-sh-file-name-handler', because something
+       ;; is different between tramp-sh.el, and tramp-adb.el or
+       ;; tramp-sshfs.el.
+       (let* ((sh-file-name-handler-p (tramp-sh-file-name-handler-p v))
+              (adb-file-name-handler-p (tramp-adb-file-name-p v))
+              (buffer
                (if buffer
                    (get-buffer-create buffer)
                  ;; BUFFER can be nil.  We use a temporary buffer.
@@ -4869,6 +4867,12 @@ a connection-local variable."
                            (member
                             elt (default-toplevel-value 
'process-environment))))
                        (setq env (cons elt env)))))
+              ;; Add remote path if exists.
+              (env (if-let ((sh-file-name-handler-p)
+                            (remote-path
+                             (string-join (tramp-get-remote-path v) ":")))
+                       (setenv-internal env "PATH" remote-path 'keep)
+                     env))
               (env (setenv-internal
                     env "INSIDE_EMACS" (tramp-inside-emacs) 'keep))
               (env (mapcar #'tramp-shell-quote-argument (delq nil env)))
@@ -4879,83 +4883,83 @@ a connection-local variable."
                (append
                 `("cd" ,(tramp-shell-quote-argument localname) "&&" "(" "env")
                 env `(,command ")")))
-               ;; Add remote shell if needed.
+              ;; Add remote shell if needed.
               (command
                (if (consp (tramp-get-method-parameter v 'tramp-direct-async))
                    (append
                     (tramp-get-method-parameter v 'tramp-direct-async)
                      `(,(string-join command " ")))
-                 command)))
-
-         ;; Check for `tramp-sh-file-name-handler', because something
-         ;; is different between tramp-sh.el, and tramp-adb.el or
-         ;; tramp-sshfs.el.
-         (let* ((sh-file-name-handler-p (tramp-sh-file-name-handler-p v))
-                (adb-file-name-handler-p (tramp-adb-file-name-p v))
-                (login-program
-                 (tramp-get-method-parameter v 'tramp-login-program))
-                ;; We don't create the temporary file.  In fact, it
-                ;; is just a prefix for the ControlPath option of
-                ;; ssh; the real temporary file has another name, and
-                ;; it is created and protected by ssh.  It is also
-                ;; removed by ssh when the connection is closed.  The
-                ;; temporary file name is cached in the main
-                ;; connection process, therefore we cannot use
-                ;; `tramp-get-connection-process'.
-                (tmpfile
-                 (when sh-file-name-handler-p
-                   (with-tramp-connection-property
-                       (tramp-get-process v) "temp-file"
-                     (tramp-compat-make-temp-name))))
-                (options
-                 (when sh-file-name-handler-p
-                   (tramp-compat-funcall
-                    'tramp-ssh-controlmaster-options v)))
-                (device
-                 (when adb-file-name-handler-p
-                   (tramp-compat-funcall
-                    'tramp-adb-get-device v)))
-                 (pta (unless (eq connection-type 'pipe) "-t"))
-                login-args p)
-
-           ;; Replace `login-args' place holders.  Split
-           ;; ControlMaster options.
-           (setq
-            login-args
-            (append
-             (flatten-tree (tramp-get-method-parameter v 'tramp-async-args))
-             (flatten-tree
-              (mapcar
-               (lambda (x) (split-string x " "))
-               (tramp-expand-args
-                v 'tramp-login-args
-                ?h (or host "") ?u (or user "") ?p (or port "")
-                ?c (format-spec (or options "") (format-spec-make ?t tmpfile))
-                ?d (or device "") ?a (or pta "") ?l ""))))
-            p (make-process
-               :name name :buffer buffer
-               :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 reliably
-           ;; to provide it as `make-process' argument when filter is
-           ;; t.  See Bug#51177.
-           (when filter
-             (set-process-filter p filter))
-           (tramp-post-process-creation p v)
-           ;; Query flag is overwritten in `tramp-post-process-creation',
-           ;; so we reset it.
-           (set-process-query-on-exit-flag p (null noquery))
-           ;; This is neded for ssh or PuTTY based processes, and
-           ;; only if the respective options are set.  Perhaps, the
-           ;; setting could be more fine-grained.
-           ;; (process-put p 'tramp-shared-socket t)
-           (process-put p 'remote-command orig-command)
-           (tramp-set-connection-property p "remote-command" orig-command)
-           (when (bufferp stderr)
-             (tramp-taint-remote-process-buffer stderr))
-
-           p))))))
+                 command))
+              (login-program
+               (tramp-get-method-parameter v 'tramp-login-program))
+              ;; We don't create the temporary file.  In fact, it is
+              ;; just a prefix for the ControlPath option of ssh; the
+              ;; real temporary file has another name, and it is
+              ;; created and protected by ssh.  It is also removed by
+              ;; ssh when the connection is closed.  The temporary
+              ;; file name is cached in the main connection process,
+              ;; therefore we cannot use
+              ;; `tramp-get-connection-process'.
+              (tmpfile
+               (when sh-file-name-handler-p
+                 (with-tramp-connection-property
+                     (tramp-get-process v) "temp-file"
+                   (tramp-compat-make-temp-name))))
+              (options
+               (when sh-file-name-handler-p
+                 (tramp-compat-funcall
+                     'tramp-ssh-controlmaster-options v)))
+              (device
+               (when adb-file-name-handler-p
+                 (tramp-compat-funcall
+                     'tramp-adb-get-device v)))
+               (pta (unless (eq connection-type 'pipe) "-t"))
+              login-args p)
+
+         ;; Command could be too long, for example due to a longish PATH.
+         (when (and sh-file-name-handler-p
+                    (tramp-compat-length>
+                     (string-join command) (tramp-get-remote-pipe-buf v)))
+           (signal 'error (cons "Command too long:" command)))
+
+         ;; Replace `login-args' place holders.  Split ControlMaster
+         ;; options.
+         (setq
+          login-args
+          (append
+           (flatten-tree (tramp-get-method-parameter v 'tramp-async-args))
+           (flatten-tree
+            (mapcar
+             (lambda (x) (split-string x " "))
+             (tramp-expand-args
+              v 'tramp-login-args
+              ?h (or host "") ?u (or user "") ?p (or port "")
+              ?c (format-spec (or options "") (format-spec-make ?t tmpfile))
+              ?d (or device "") ?a (or pta "") ?l ""))))
+          p (make-process
+             :name name :buffer buffer
+             :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 reliably
+         ;; to provide it as `make-process' argument when filter is
+         ;; t.  See Bug#51177.
+         (when filter
+           (set-process-filter p filter))
+         (tramp-post-process-creation p v)
+         ;; Query flag is overwritten in `tramp-post-process-creation',
+         ;; so we reset it.
+         (set-process-query-on-exit-flag p (null noquery))
+         ;; This is needed for ssh or PuTTY based processes, and
+         ;; only if the respective options are set.  Perhaps, the
+         ;; setting could be more fine-grained.
+         ;; (process-put p 'tramp-shared-socket t)
+         (process-put p 'remote-command orig-command)
+         (tramp-set-connection-property p "remote-command" orig-command)
+         (when (bufferp stderr)
+           (tramp-taint-remote-process-buffer stderr))
+
+         p)))))
 
 (defun tramp-handle-make-symbolic-link
     (_target linkname &optional _ok-if-already-exists)
diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el
index aefe14e845e..c131d39c110 100644
--- a/lisp/net/trampver.el
+++ b/lisp/net/trampver.el
@@ -1,13 +1,13 @@
 ;;; trampver.el --- Transparent Remote Access, Multiple Protocol  -*- 
lexical-binding:t -*-
 ;;; lisp/trampver.el.  Generated from trampver.el.in by configure.
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
 ;; Maintainer: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
 ;; Package: tramp
-;; Version: 2.7.0-pre
+;; Version: 2.7.1-pre
 ;; Package-Requires: ((emacs "27.1"))
 ;; Package-Type: multi
 ;; URL: https://www.gnu.org/software/tramp/
@@ -40,7 +40,7 @@
 ;; ./configure" to change them.
 
 ;;;###tramp-autoload
-(defconst tramp-version "2.7.0-pre"
+(defconst tramp-version "2.7.1-pre"
   "This version of Tramp.")
 
 ;;;###tramp-autoload
@@ -78,7 +78,7 @@
 ;; Check for Emacs version.
 (let ((x   (if (not (string-version-lessp emacs-version "27.1"))
       "ok"
-    (format "Tramp 2.7.0-pre is not fit for %s"
+    (format "Tramp 2.7.1-pre is not fit for %s"
             (replace-regexp-in-string "\n" "" (emacs-version))))))
   (unless (string-equal "ok" x) (error "%s" x)))
 
diff --git a/lisp/net/webjump.el b/lisp/net/webjump.el
index 77f00578a48..cff838fca51 100644
--- a/lisp/net/webjump.el
+++ b/lisp/net/webjump.el
@@ -1,6 +1,6 @@
 ;;; webjump.el --- programmable Web hotlist  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author:     Neil W. Van Dyke <nwv@acm.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/net/zeroconf.el b/lisp/net/zeroconf.el
index 238bf20bb66..54422d43cd7 100644
--- a/lisp/net/zeroconf.el
+++ b/lisp/net/zeroconf.el
@@ -1,6 +1,6 @@
 ;;; zeroconf.el --- Service browser using Avahi.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, hardware
diff --git a/lisp/newcomment.el b/lisp/newcomment.el
index 9ae7de70a0e..ee7b2ea34d8 100644
--- a/lisp/newcomment.el
+++ b/lisp/newcomment.el
@@ -1,6 +1,6 @@
 ;;; newcomment.el --- (un)comment regions of buffers -*- lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: code extracted from Emacs-20's simple.el
 ;; Maintainer: Stefan Monnier <monnier@gnu.org>
diff --git a/lisp/notifications.el b/lisp/notifications.el
index a694b38e52e..2692df9d7fa 100644
--- a/lisp/notifications.el
+++ b/lisp/notifications.el
@@ -1,6 +1,6 @@
 ;;; notifications.el --- Client interface to desktop notifications.  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Julien Danjou <julien@danjou.info>
 ;; Keywords: comm desktop notifications
@@ -23,7 +23,7 @@
 ;;; Commentary:
 
 ;; This package provides an implementation of the Desktop Notifications
-;; <https://developer.gnome.org/notification-spec/>.
+;; <https://specifications.freedesktop.org/notification-spec/latest/>.
 
 ;; In order to activate this package, you must add the following code
 ;; into your .emacs:
diff --git a/lisp/novice.el b/lisp/novice.el
index 05e4bfc91c9..33a6d153180 100644
--- a/lisp/novice.el
+++ b/lisp/novice.el
@@ -1,6 +1,6 @@
 ;;; novice.el --- handling of disabled commands ("novice mode") for Emacs  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985-1987, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985-1987, 1994, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -67,9 +67,10 @@ If nil, the feature is disabled, i.e., all commands work 
normally.")
                "Here's the first part of its description:\n\n")
               ;; Keep only the first paragraph of the documentation.
               (with-temp-buffer
-                (insert (condition-case ()
-                            (documentation cmd)
-                          (error "<< not documented >>")))
+                (insert (or (condition-case ()
+                               (documentation cmd)
+                             (error nil))
+                           "<< not documented >>"))
                 (goto-char (point-min))
                 (when (search-forward "\n\n" nil t)
                   (delete-region (match-beginning 0) (point-max)))
diff --git a/lisp/nxml/nxml-enc.el b/lisp/nxml/nxml-enc.el
index 1fd7abef974..b5b6c844ceb 100644
--- a/lisp/nxml/nxml-enc.el
+++ b/lisp/nxml/nxml-enc.el
@@ -1,9 +1,9 @@
 ;;; nxml-enc.el --- XML encoding auto-detection  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/nxml-maint.el b/lisp/nxml/nxml-maint.el
index 24eb711eb99..be49e41dbed 100644
--- a/lisp/nxml/nxml-maint.el
+++ b/lisp/nxml/nxml-maint.el
@@ -1,9 +1,9 @@
 ;;; nxml-maint.el --- commands for maintainers of nxml-*.el  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/nxml-mode.el b/lisp/nxml/nxml-mode.el
index bc32598003e..02391dc6968 100644
--- a/lisp/nxml/nxml-mode.el
+++ b/lisp/nxml/nxml-mode.el
@@ -1,9 +1,9 @@
 ;;; nxml-mode.el --- a new XML mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2003-2004, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/nxml-ns.el b/lisp/nxml/nxml-ns.el
index 2781ea87938..10dafe32e62 100644
--- a/lisp/nxml/nxml-ns.el
+++ b/lisp/nxml/nxml-ns.el
@@ -1,9 +1,9 @@
 ;;; nxml-ns.el --- XML namespace processing  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/nxml-outln.el b/lisp/nxml/nxml-outln.el
index 5f1eec75ef9..a470fbdc5b1 100644
--- a/lisp/nxml/nxml-outln.el
+++ b/lisp/nxml/nxml-outln.el
@@ -1,9 +1,9 @@
 ;;; nxml-outln.el --- outline support for nXML mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2004, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/nxml-parse.el b/lisp/nxml/nxml-parse.el
index f2440065deb..61ff0b68b68 100644
--- a/lisp/nxml/nxml-parse.el
+++ b/lisp/nxml/nxml-parse.el
@@ -1,9 +1,9 @@
 ;;; nxml-parse.el --- XML parser, sharing infrastructure with nxml-mode  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/nxml-rap.el b/lisp/nxml/nxml-rap.el
index 8e11707b9b7..6117b8bd33a 100644
--- a/lisp/nxml/nxml-rap.el
+++ b/lisp/nxml/nxml-rap.el
@@ -1,9 +1,9 @@
 ;;; nxml-rap.el --- low-level support for random access parsing for nXML mode  
-*- lexical-binding:t -*-
 
-;; Copyright (C) 2003-2004, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/nxml-util.el b/lisp/nxml/nxml-util.el
index e9d04126400..7f425f8bcea 100644
--- a/lisp/nxml/nxml-util.el
+++ b/lisp/nxml/nxml-util.el
@@ -1,9 +1,9 @@
 ;;; nxml-util.el --- utility functions for nxml-*.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/rng-cmpct.el b/lisp/nxml/rng-cmpct.el
index 98aad8bd4dd..9aa7eecf346 100644
--- a/lisp/nxml/rng-cmpct.el
+++ b/lisp/nxml/rng-cmpct.el
@@ -1,9 +1,9 @@
 ;;; rng-cmpct.el --- parsing of RELAX NG Compact Syntax schemas  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/rng-dt.el b/lisp/nxml/rng-dt.el
index 577157687a3..b7fd46dd894 100644
--- a/lisp/nxml/rng-dt.el
+++ b/lisp/nxml/rng-dt.el
@@ -1,9 +1,9 @@
 ;;; rng-dt.el --- datatype library interface for RELAX NG  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/rng-loc.el b/lisp/nxml/rng-loc.el
index 82e8494a49f..3e55bc5d4b9 100644
--- a/lisp/nxml/rng-loc.el
+++ b/lisp/nxml/rng-loc.el
@@ -1,9 +1,9 @@
 ;;; rng-loc.el --- Locate the schema to use for validation  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/rng-maint.el b/lisp/nxml/rng-maint.el
index 42feb221e81..62f5ce8b93d 100644
--- a/lisp/nxml/rng-maint.el
+++ b/lisp/nxml/rng-maint.el
@@ -1,9 +1,9 @@
 ;;; rng-maint.el --- commands for RELAX NG maintainers  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/rng-match.el b/lisp/nxml/rng-match.el
index 51c197cd6c6..61e4ffdb1a9 100644
--- a/lisp/nxml/rng-match.el
+++ b/lisp/nxml/rng-match.el
@@ -1,9 +1,9 @@
 ;;; rng-match.el --- matching of RELAX NG patterns against XML events  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/rng-nxml.el b/lisp/nxml/rng-nxml.el
index fd1f4fb904e..af16e7ae50b 100644
--- a/lisp/nxml/rng-nxml.el
+++ b/lisp/nxml/rng-nxml.el
@@ -1,9 +1,9 @@
 ;;; rng-nxml.el --- make nxml-mode take advantage of rng-validate-mode  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/rng-parse.el b/lisp/nxml/rng-parse.el
index 1728de7aadd..cb49f4f69e3 100644
--- a/lisp/nxml/rng-parse.el
+++ b/lisp/nxml/rng-parse.el
@@ -1,9 +1,9 @@
 ;;; rng-parse.el --- parse an XML file and validate it against a schema  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/rng-pttrn.el b/lisp/nxml/rng-pttrn.el
index f37ace7f734..996e9ca0929 100644
--- a/lisp/nxml/rng-pttrn.el
+++ b/lisp/nxml/rng-pttrn.el
@@ -1,9 +1,9 @@
 ;;; rng-pttrn.el --- RELAX NG patterns  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/rng-uri.el b/lisp/nxml/rng-uri.el
index 4cfa212990d..587ca226de8 100644
--- a/lisp/nxml/rng-uri.el
+++ b/lisp/nxml/rng-uri.el
@@ -1,9 +1,9 @@
 ;;; rng-uri.el --- URI parsing and manipulation  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/rng-util.el b/lisp/nxml/rng-util.el
index 4f49885fc45..f9d47c20347 100644
--- a/lisp/nxml/rng-util.el
+++ b/lisp/nxml/rng-util.el
@@ -1,9 +1,9 @@
 ;;; rng-util.el --- utility functions for RELAX NG library  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/rng-valid.el b/lisp/nxml/rng-valid.el
index 898fe204fd4..1c9998345fb 100644
--- a/lisp/nxml/rng-valid.el
+++ b/lisp/nxml/rng-valid.el
@@ -1,9 +1,9 @@
 ;;; rng-valid.el --- real-time validation of XML using RELAX NG  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/rng-xsd.el b/lisp/nxml/rng-xsd.el
index cd963534402..417e4c7b5bc 100644
--- a/lisp/nxml/rng-xsd.el
+++ b/lisp/nxml/rng-xsd.el
@@ -1,9 +1,9 @@
 ;;; rng-xsd.el --- W3C XML Schema datatypes library for RELAX NG  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/xmltok.el b/lisp/nxml/xmltok.el
index 78fa91b5cdc..a4816d1b3f7 100644
--- a/lisp/nxml/xmltok.el
+++ b/lisp/nxml/xmltok.el
@@ -1,9 +1,9 @@
 ;;; xmltok.el --- XML tokenization  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/nxml/xsd-regexp.el b/lisp/nxml/xsd-regexp.el
index 3c33c4c0170..5474ac179d6 100644
--- a/lisp/nxml/xsd-regexp.el
+++ b/lisp/nxml/xsd-regexp.el
@@ -1,9 +1,9 @@
 ;;; xsd-regexp.el --- translate W3C XML Schema regexps to Emacs regexps  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, regexp
+;; Keywords: text, hypermedia, languages, XML, regexp
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/obarray.el b/lisp/obarray.el
index 485627d51de..a26992df8e2 100644
--- a/lisp/obarray.el
+++ b/lisp/obarray.el
@@ -1,6 +1,6 @@
 ;;; obarray.el --- obarray functions -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: obarray functions
diff --git a/lisp/obsolete/autoarg.el b/lisp/obsolete/autoarg.el
index cd4628be669..84354c893ab 100644
--- a/lisp/obsolete/autoarg.el
+++ b/lisp/obsolete/autoarg.el
@@ -1,6 +1,6 @@
 ;;; autoarg.el --- make digit keys supply prefix args -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author:  Dave Love <fx@gnu.org>
 ;; Created: 1998-09-04
diff --git a/lisp/obsolete/autoload.el b/lisp/obsolete/autoload.el
index ecf931d0881..850ec83e645 100644
--- a/lisp/obsolete/autoload.el
+++ b/lisp/obsolete/autoload.el
@@ -1,6 +1,6 @@
 ;;; autoload.el --- maintain autoloads in loaddefs.el  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1991-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Roland McGrath <roland@gnu.org>
 ;; Keywords: maint
diff --git a/lisp/obsolete/bruce.el b/lisp/obsolete/bruce.el
index 83f91ab8816..2a44946c7b6 100644
--- a/lisp/obsolete/bruce.el
+++ b/lisp/obsolete/bruce.el
@@ -1,7 +1,7 @@
 ;;; bruce.el --- bruce phrase utility for overloading the Communications  -*- 
lexical-binding: t; -*-
 ;;; Decency Act snoops, if any.
 
-;; Copyright (C) 1988, 1993, 1997, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1988, 1993, 1997, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/cc-compat.el b/lisp/obsolete/cc-compat.el
index 33330623739..b3643f888e4 100644
--- a/lisp/obsolete/cc-compat.el
+++ b/lisp/obsolete/cc-compat.el
@@ -1,6 +1,6 @@
 ;;; cc-compat.el --- cc-mode compatibility with c-mode.el confusion  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
 
 ;; Authors:    1998- Martin Stjernholm
 ;;            1994-1999 Barry A. Warsaw
diff --git a/lisp/obsolete/cl-compat.el b/lisp/obsolete/cl-compat.el
index 255c3dc8277..606f8da3748 100644
--- a/lisp/obsolete/cl-compat.el
+++ b/lisp/obsolete/cl-compat.el
@@ -1,6 +1,6 @@
 ;;; cl-compat.el --- Common Lisp extensions for GNU Emacs Lisp (compatibility) 
 -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Gillespie <daveg@synaptics.com>
 ;; Version: 2.02
diff --git a/lisp/obsolete/cl.el b/lisp/obsolete/cl.el
index 2d4de825910..398b45260e5 100644
--- a/lisp/obsolete/cl.el
+++ b/lisp/obsolete/cl.el
@@ -1,6 +1,6 @@
 ;;; cl.el --- Compatibility aliases for the old CL library.  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Deprecated-since: 27.1
diff --git a/lisp/obsolete/crisp.el b/lisp/obsolete/crisp.el
index c7e3919cdba..3a3a44f850f 100644
--- a/lisp/obsolete/crisp.el
+++ b/lisp/obsolete/crisp.el
@@ -1,6 +1,6 @@
 ;;; crisp.el --- CRiSP/Brief Emacs emulator  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Gary D. Foster <Gary.Foster@Corp.Sun.COM>
 ;; Keywords: emulations brief crisp
diff --git a/lisp/obsolete/eieio-compat.el b/lisp/obsolete/eieio-compat.el
index bb3d5ccb49c..26648a4d7bb 100644
--- a/lisp/obsolete/eieio-compat.el
+++ b/lisp/obsolete/eieio-compat.el
@@ -1,6 +1,6 @@
 ;;; eieio-compat.el --- Compatibility with Older EIEIO versions  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1995-1996, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1996, 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: OO, lisp
diff --git a/lisp/obsolete/eudcb-ph.el b/lisp/obsolete/eudcb-ph.el
index 356987afebf..fd3d3821989 100644
--- a/lisp/obsolete/eudcb-ph.el
+++ b/lisp/obsolete/eudcb-ph.el
@@ -1,6 +1,6 @@
 ;;; eudcb-ph.el --- Emacs Unified Directory Client - CCSO PH/QI Backend  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Oscar Figueiredo <oscar@cpe.fr>
 ;;         Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/obsolete/gs.el b/lisp/obsolete/gs.el
index 07623acddc9..516468058f2 100644
--- a/lisp/obsolete/gs.el
+++ b/lisp/obsolete/gs.el
@@ -1,6 +1,6 @@
 ;;; gs.el --- interface to Ghostscript  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
diff --git a/lisp/obsolete/gulp.el b/lisp/obsolete/gulp.el
index 0263c67df9e..03c005f498b 100644
--- a/lisp/obsolete/gulp.el
+++ b/lisp/obsolete/gulp.el
@@ -1,6 +1,6 @@
 ;;; gulp.el --- ask for updates for Lisp packages  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Sam Shteingold <shteingd@math.ucla.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/html2text.el b/lisp/obsolete/html2text.el
index 42ec65bc194..ffe70bc9b9a 100644
--- a/lisp/obsolete/html2text.el
+++ b/lisp/obsolete/html2text.el
@@ -1,6 +1,6 @@
 ;;; html2text.el --- a simple html to plain text converter -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Joakim Hove <hove@phys.ntnu.no>
 ;; Obsolete-since: 26.1
diff --git a/lisp/obsolete/info-edit.el b/lisp/obsolete/info-edit.el
index 5b9bb4c253e..fb6de736590 100644
--- a/lisp/obsolete/info-edit.el
+++ b/lisp/obsolete/info-edit.el
@@ -1,6 +1,6 @@
 ;;; info-edit.el --- Editing info files  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1986, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1992-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: help
diff --git a/lisp/obsolete/inversion.el b/lisp/obsolete/inversion.el
index 03094825ecd..21e6ffd6275 100644
--- a/lisp/obsolete/inversion.el
+++ b/lisp/obsolete/inversion.el
@@ -1,6 +1,6 @@
 ;;; inversion.el --- When you need something in version XX.XX  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Version: 1.3
diff --git a/lisp/obsolete/iswitchb.el b/lisp/obsolete/iswitchb.el
index 59e6c0403a2..3f05b7fe7ac 100644
--- a/lisp/obsolete/iswitchb.el
+++ b/lisp/obsolete/iswitchb.el
@@ -1,6 +1,6 @@
 ;;; iswitchb.el --- switch between buffers using substrings  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Stephen Eglen <stephen@gnu.org>
 ;; Keywords: completion convenience
diff --git a/lisp/obsolete/landmark.el b/lisp/obsolete/landmark.el
index 968b817e9e8..0a67bba8028 100644
--- a/lisp/obsolete/landmark.el
+++ b/lisp/obsolete/landmark.el
@@ -1,6 +1,6 @@
 ;;; landmark.el --- Neural-network robot that learns landmarks  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1996-1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Terrence Brannon <metaperl@gmail.com>
 ;; Created: December 16, 1996 - first release to usenet
diff --git a/lisp/obsolete/linum.el b/lisp/obsolete/linum.el
index 017afe10c1a..1f46957caa6 100644
--- a/lisp/obsolete/linum.el
+++ b/lisp/obsolete/linum.el
@@ -1,6 +1,6 @@
 ;;; linum.el --- display line numbers in the left margin -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Markus Triska <markus.triska@gmx.at>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/longlines.el b/lisp/obsolete/longlines.el
index 0f9f73d044b..6aa388805f2 100644
--- a/lisp/obsolete/longlines.el
+++ b/lisp/obsolete/longlines.el
@@ -1,13 +1,13 @@
 ;;; longlines.el --- automatically wrap long lines   -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2000-2001, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2001, 2004-2024 Free Software Foundation, Inc.
 
 ;; Authors:    Kai Grossjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 ;;             Alex Schroeder <alex@gnu.org>
 ;;             Chong Yidong <cyd@stupidchicken.com>
 ;; Maintainer: emacs-devel@gnu.org
 ;; Obsolete-since: 24.4
-;; Keywords: convenience, wp
+;; Keywords: convenience, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/obsolete/makesum.el b/lisp/obsolete/makesum.el
index 69f1820eaba..85bd5c8f99d 100644
--- a/lisp/obsolete/makesum.el
+++ b/lisp/obsolete/makesum.el
@@ -1,6 +1,6 @@
 ;;; makesum.el --- generate key binding summary for Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: help
diff --git a/lisp/obsolete/mantemp.el b/lisp/obsolete/mantemp.el
index 9fd6c91cc4e..32d7f81cf60 100644
--- a/lisp/obsolete/mantemp.el
+++ b/lisp/obsolete/mantemp.el
@@ -1,6 +1,6 @@
 ;;; mantemp.el --- create manual template instantiations from g++ 2.7.2 output 
 -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Tom Houlder <thoulder@icor.fr>
 ;; Created: 10 Dec 1996
diff --git a/lisp/obsolete/messcompat.el b/lisp/obsolete/messcompat.el
index a7d40e43f50..b30794c0eae 100644
--- a/lisp/obsolete/messcompat.el
+++ b/lisp/obsolete/messcompat.el
@@ -1,6 +1,6 @@
 ;;; messcompat.el --- making message mode compatible with mail mode  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: mail, news
diff --git a/lisp/obsolete/metamail.el b/lisp/obsolete/metamail.el
index 561c0dc4ebd..8e3000e7268 100644
--- a/lisp/obsolete/metamail.el
+++ b/lisp/obsolete/metamail.el
@@ -1,6 +1,6 @@
 ;;; metamail.el --- Metamail interface for GNU Emacs  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1993, 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
 ;; Keywords: mail, news, mime, multimedia
diff --git a/lisp/obsolete/mh-compat.el b/lisp/obsolete/mh-compat.el
index e45263bfd9f..ca72bf3b22d 100644
--- a/lisp/obsolete/mh-compat.el
+++ b/lisp/obsolete/mh-compat.el
@@ -1,6 +1,6 @@
 ;;; mh-compat.el --- make MH-E compatible with various versions of Emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Bill Wohler <wohler@newt.com>
 ;; Keywords: mail
diff --git a/lisp/obsolete/netrc.el b/lisp/obsolete/netrc.el
index 07f7fb94833..dc856612e30 100644
--- a/lisp/obsolete/netrc.el
+++ b/lisp/obsolete/netrc.el
@@ -1,6 +1,6 @@
 ;;; netrc.el --- .netrc parsing functionality  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
diff --git a/lisp/obsolete/nnir.el b/lisp/obsolete/nnir.el
index a3c61490154..dbcc3eaffec 100644
--- a/lisp/obsolete/nnir.el
+++ b/lisp/obsolete/nnir.el
@@ -1,6 +1,6 @@
 ;;; nnir.el --- Search mail with various search engines  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Kai Großjohann <grossjohann@ls6.cs.uni-dortmund.de>
 ;; Swish-e and Swish++ backends by:
diff --git a/lisp/obsolete/otodo-mode.el b/lisp/obsolete/otodo-mode.el
index 0077088a20b..deca885b44b 100644
--- a/lisp/obsolete/otodo-mode.el
+++ b/lisp/obsolete/otodo-mode.el
@@ -1,6 +1,6 @@
 ;;; otodo-mode.el --- major mode for editing TODO list files  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Oliver Seidel <privat@os10000.net>
 ;; Maintainer: Stephen Berman <stephen.berman@gmx.net>
diff --git a/lisp/obsolete/pgg-def.el b/lisp/obsolete/pgg-def.el
index 62f5368a730..8cf571ab274 100644
--- a/lisp/obsolete/pgg-def.el
+++ b/lisp/obsolete/pgg-def.el
@@ -1,6 +1,6 @@
 ;;; pgg-def.el --- functions/macros for defining PGG functions  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Created: 1999/11/02
diff --git a/lisp/obsolete/pgg-gpg.el b/lisp/obsolete/pgg-gpg.el
index 6af59c8e3e5..586fa67a8e8 100644
--- a/lisp/obsolete/pgg-gpg.el
+++ b/lisp/obsolete/pgg-gpg.el
@@ -1,6 +1,6 @@
 ;;; pgg-gpg.el --- GnuPG support for PGG.  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Symmetric encryption and gpg-agent support added by:
diff --git a/lisp/obsolete/pgg-parse.el b/lisp/obsolete/pgg-parse.el
index ca713203b47..0b45eb27279 100644
--- a/lisp/obsolete/pgg-parse.el
+++ b/lisp/obsolete/pgg-parse.el
@@ -1,6 +1,6 @@
 ;;; pgg-parse.el --- OpenPGP packet parsing  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Created: 1999/10/28
diff --git a/lisp/obsolete/pgg-pgp.el b/lisp/obsolete/pgg-pgp.el
index e000e7ead59..76261957e18 100644
--- a/lisp/obsolete/pgg-pgp.el
+++ b/lisp/obsolete/pgg-pgp.el
@@ -1,6 +1,6 @@
 ;;; pgg-pgp.el --- PGP 2.* and 6.* support for PGG.  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1999-2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Created: 1999/11/02
diff --git a/lisp/obsolete/pgg-pgp5.el b/lisp/obsolete/pgg-pgp5.el
index 8871ab3f9e0..09e273a49d0 100644
--- a/lisp/obsolete/pgg-pgp5.el
+++ b/lisp/obsolete/pgg-pgp5.el
@@ -1,6 +1,6 @@
 ;;; pgg-pgp5.el --- PGP 5.* support for PGG.  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Created: 1999/11/02
diff --git a/lisp/obsolete/pgg.el b/lisp/obsolete/pgg.el
index f2196c1b8eb..6c00ad201f1 100644
--- a/lisp/obsolete/pgg.el
+++ b/lisp/obsolete/pgg.el
@@ -1,6 +1,6 @@
 ;;; pgg.el --- glue for the various PGP implementations.  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1999-2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
diff --git a/lisp/obsolete/ps-def.el b/lisp/obsolete/ps-def.el
index 222f5622b7f..641845d2b95 100644
--- a/lisp/obsolete/ps-def.el
+++ b/lisp/obsolete/ps-def.el
@@ -1,10 +1,10 @@
 ;;; ps-def.el --- Emacs definitions for ps-print -*- lexical-binding: t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
 ;;     Kenichi Handa <handa@gnu.org> (multi-byte characters)
-;; Keywords: wp, print, PostScript
+;; Keywords: text, print, PostScript
 ;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
 ;; Package: ps-print
 ;; Obsolete-since: 29.1
diff --git a/lisp/obsolete/quickurl.el b/lisp/obsolete/quickurl.el
index 65a4c06e163..7393bebdce1 100644
--- a/lisp/obsolete/quickurl.el
+++ b/lisp/obsolete/quickurl.el
@@ -1,6 +1,6 @@
 ;;; quickurl.el --- insert a URL based on text at point in buffer  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Pearson <davep@davep.org>
 ;; Created: 1999-05-28
diff --git a/lisp/obsolete/rcompile.el b/lisp/obsolete/rcompile.el
index d9f498a313b..e0826475e32 100644
--- a/lisp/obsolete/rcompile.el
+++ b/lisp/obsolete/rcompile.el
@@ -1,6 +1,6 @@
 ;;; rcompile.el --- run a compilation on a remote machine  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Alon Albert <alon@milcse.rtsg.mot.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/rfc2368.el b/lisp/obsolete/rfc2368.el
index 77a1a6d910f..ddfb14d5e08 100644
--- a/lisp/obsolete/rfc2368.el
+++ b/lisp/obsolete/rfc2368.el
@@ -1,6 +1,6 @@
 ;;; rfc2368.el --- support for rfc2368  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Sen Nagata <sen@eccosys.com>
 ;; Keywords: mail
diff --git a/lisp/obsolete/rlogin.el b/lisp/obsolete/rlogin.el
index 1afa50cb0ff..f285165ba21 100644
--- a/lisp/obsolete/rlogin.el
+++ b/lisp/obsolete/rlogin.el
@@ -1,6 +1,6 @@
 ;;; rlogin.el --- remote login interface  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: Noah Friedman <friedman@splode.com>
 ;; Keywords: unix, comm
diff --git a/lisp/obsolete/sb-image.el b/lisp/obsolete/sb-image.el
index 28926ac5d61..d65ea502685 100644
--- a/lisp/obsolete/sb-image.el
+++ b/lisp/obsolete/sb-image.el
@@ -1,6 +1,6 @@
 ;;; sb-image.el --- Image management for speedbar  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2003, 2005-2019, 2021-2023 Free Software
+;; Copyright (C) 1999-2003, 2005-2019, 2021-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/obsolete/starttls.el b/lisp/obsolete/starttls.el
index bbf70df82a4..dab65bbef87 100644
--- a/lisp/obsolete/starttls.el
+++ b/lisp/obsolete/starttls.el
@@ -1,6 +1,6 @@
 ;;; starttls.el --- STARTTLS functions  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Author: Simon Josefsson <simon@josefsson.org>
diff --git a/lisp/obsolete/sup-mouse.el b/lisp/obsolete/sup-mouse.el
index 96a9d28f379..e7bb58950a0 100644
--- a/lisp/obsolete/sup-mouse.el
+++ b/lisp/obsolete/sup-mouse.el
@@ -1,6 +1,6 @@
 ;;; sup-mouse.el --- supdup mouse support for lisp machines  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Wolfgang Rupprecht
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/terminal.el b/lisp/obsolete/terminal.el
index 31c1ebead14..13667589c9e 100644
--- a/lisp/obsolete/terminal.el
+++ b/lisp/obsolete/terminal.el
@@ -1,6 +1,6 @@
 ;;; terminal.el --- terminal emulator for GNU Emacs  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1986-1989, 1993-1994, 2001-2023 Free Software
+;; Copyright (C) 1986-1989, 1993-1994, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Richard Mlynarik <mly@eddie.mit.edu>
diff --git a/lisp/obsolete/thumbs.el b/lisp/obsolete/thumbs.el
index ddf734f22ea..781e91c471c 100644
--- a/lisp/obsolete/thumbs.el
+++ b/lisp/obsolete/thumbs.el
@@ -1,6 +1,6 @@
 ;;; thumbs.el --- Thumbnails previewer for images files  -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Jean-Philippe Theberge <jphiltheberge@videotron.ca>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/tls.el b/lisp/obsolete/tls.el
index 9089684cd52..447b0691afd 100644
--- a/lisp/obsolete/tls.el
+++ b/lisp/obsolete/tls.el
@@ -1,6 +1,6 @@
 ;;; tls.el --- TLS/SSL support via wrapper around GnuTLS  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1996-1999, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 ;; Keywords: comm, tls, gnutls, ssl
diff --git a/lisp/obsolete/tpu-edt.el b/lisp/obsolete/tpu-edt.el
index 4c8beb7dcff..62431662baa 100644
--- a/lisp/obsolete/tpu-edt.el
+++ b/lisp/obsolete/tpu-edt.el
@@ -1,6 +1,6 @@
 ;;; tpu-edt.el --- Emacs emulating TPU emulating EDT  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1993-1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Rob Riepel <riepel@networking.stanford.edu>
 ;; Version: 4.5
diff --git a/lisp/obsolete/tpu-extras.el b/lisp/obsolete/tpu-extras.el
index f3b91ba878a..801a20d3550 100644
--- a/lisp/obsolete/tpu-extras.el
+++ b/lisp/obsolete/tpu-extras.el
@@ -1,6 +1,6 @@
 ;;; tpu-extras.el --- scroll margins and free cursor mode for TPU-edt  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Rob Riepel <riepel@networking.stanford.edu>
 ;; Keywords: emulations
diff --git a/lisp/obsolete/tpu-mapper.el b/lisp/obsolete/tpu-mapper.el
index 2c9836cc2ee..ed5608a7222 100644
--- a/lisp/obsolete/tpu-mapper.el
+++ b/lisp/obsolete/tpu-mapper.el
@@ -1,6 +1,6 @@
 ;;; tpu-mapper.el --- create a TPU-edt X-windows keymap file  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Rob Riepel <riepel@networking.stanford.edu>
 ;; Keywords: emulations
diff --git a/lisp/obsolete/uce.el b/lisp/obsolete/uce.el
index 58036cc6e01..85e25cb7558 100644
--- a/lisp/obsolete/uce.el
+++ b/lisp/obsolete/uce.el
@@ -1,6 +1,6 @@
 ;;; uce.el --- facilitate reply to unsolicited commercial email  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996, 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: stanislav shalunov <shalunov@mccme.ru>
 ;; Created: 10 Dec 1996
diff --git a/lisp/obsolete/url-about.el b/lisp/obsolete/url-about.el
index fe1c51cc10c..b9de3a8674d 100644
--- a/lisp/obsolete/url-about.el
+++ b/lisp/obsolete/url-about.el
@@ -1,6 +1,6 @@
 ;;; url-about.el --- Show internal URLs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes, hypermedia
 ;; Obsolete-since: 29.1
diff --git a/lisp/obsolete/url-dired.el b/lisp/obsolete/url-dired.el
index 98af8e236e4..6004ebeb0d2 100644
--- a/lisp/obsolete/url-dired.el
+++ b/lisp/obsolete/url-dired.el
@@ -1,6 +1,6 @@
 ;;; url-dired.el --- URL Dired minor mode  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, files
 ;; Obsolete-since: 29.1
diff --git a/lisp/obsolete/url-ns.el b/lisp/obsolete/url-ns.el
index 53db684887c..41aaa5b63be 100644
--- a/lisp/obsolete/url-ns.el
+++ b/lisp/obsolete/url-ns.el
@@ -1,6 +1,6 @@
 ;;; url-ns.el --- Various netscape-ish functions for proxy definitions  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes, hypermedia
 ;; Obsolete-since: 27.1
diff --git a/lisp/obsolete/vc-arch.el b/lisp/obsolete/vc-arch.el
index 0b74d48d27d..7cb31951502 100644
--- a/lisp/obsolete/vc-arch.el
+++ b/lisp/obsolete/vc-arch.el
@@ -1,6 +1,6 @@
 ;;; vc-arch.el --- VC backend for the Arch version-control system  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author:      FSF (see vc.el for full credits)
 ;; Maintainer:  Stefan Monnier <monnier@gnu.org>
diff --git a/lisp/obsolete/vc-mtn.el b/lisp/obsolete/vc-mtn.el
index e1c96b5511b..a185d58ac1d 100644
--- a/lisp/obsolete/vc-mtn.el
+++ b/lisp/obsolete/vc-mtn.el
@@ -1,6 +1,6 @@
 ;;; vc-mtn.el --- VC backend for Monotone  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: vc
diff --git a/lisp/obsolete/vip.el b/lisp/obsolete/vip.el
index 5b19f916c57..eecedbd5e74 100644
--- a/lisp/obsolete/vip.el
+++ b/lisp/obsolete/vip.el
@@ -1,6 +1,6 @@
 ;;; vip.el --- a VI Package for GNU Emacs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1986-1988, 1992-1993, 1998, 2001-2023 Free Software
+;; Copyright (C) 1986-1988, 1992-1993, 1998, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Masahiko Sato <ms@sail.stanford.edu>
diff --git a/lisp/obsolete/vt-control.el b/lisp/obsolete/vt-control.el
index 179c03596b2..45fa8b04e4d 100644
--- a/lisp/obsolete/vt-control.el
+++ b/lisp/obsolete/vt-control.el
@@ -1,6 +1,6 @@
 ;;; vt-control.el --- Common VTxxx control functions  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Rob Riepel <riepel@networking.stanford.edu>
 ;; Keywords: terminals
diff --git a/lisp/obsolete/vt100-led.el b/lisp/obsolete/vt100-led.el
index cfdd07b513f..8762b2ded80 100644
--- a/lisp/obsolete/vt100-led.el
+++ b/lisp/obsolete/vt100-led.el
@@ -1,6 +1,6 @@
 ;;; vt100-led.el --- functions for LED control on VT-100 terminals & clones  
-*- lexical-binding:t -*-
 
-;; Copyright (C) 1988, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Howard Gayle
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/ws-mode.el b/lisp/obsolete/ws-mode.el
index d41fd8ffc36..d8ee63c8a01 100644
--- a/lisp/obsolete/ws-mode.el
+++ b/lisp/obsolete/ws-mode.el
@@ -1,6 +1,6 @@
 ;;; ws-mode.el --- WordStar emulation mode for GNU Emacs -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 1991, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Juergen Nickelsen <nickel@cs.tu-berlin.de>
 ;; Version: 0.7
diff --git a/lisp/obsolete/yow.el b/lisp/obsolete/yow.el
index 59ae9a6263b..eb4c65c4084 100644
--- a/lisp/obsolete/yow.el
+++ b/lisp/obsolete/yow.el
@@ -1,6 +1,6 @@
 ;;; yow.el --- quote random zippyisms  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Richard Mlynarik
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/org/ChangeLog.1 b/lisp/org/ChangeLog.1
index 82b1c832c40..74a62e00855 100644
--- a/lisp/org/ChangeLog.1
+++ b/lisp/org/ChangeLog.1
@@ -12523,7 +12523,7 @@
 2012-01-03  Carsten Dominik  <carsten.dominik@gmail.com>  (tiny change)
 
        * org-clock.el (org-clock-in, org-clock-find-position):
-       Remove erraneous space in regexp.
+       Remove erroneous space in regexp.
 
 2012-01-03  Eric Schulte  <eric.schulte@gmx.com>
 
@@ -12700,7 +12700,7 @@
 2012-01-03  Carsten Dominik  <carsten.dominik@gmail.com>  (tiny change)
 
        * org-clock.el (org-clock-in, org-clock-find-position):
-       Remove erraneous space in regexp.
+       Remove erroneous space in regexp.
 
 2012-01-03  Jambunathan K  <kjambunathan@gmail.com>
 
@@ -14573,7 +14573,7 @@
 
 2012-01-03  Nicolas Goaziou  <n.goaziou@gmail.com>
 
-       * org-footnote.el (org-footnote-at-definition-p): Re-use
+       * org-footnote.el (org-footnote-at-definition-p): Reuse
        `org-footnote-definition-re'.
 
 2012-01-03  Nicolas Goaziou  <n.goaziou@gmail.com>
@@ -18471,7 +18471,7 @@
 
        * org-list.el (org-in-item-p): When point was just after
        org-list-end-re, check wouldn't be done for starting line.  So, if
-       the first line was an item, it wouln't be noticed and function
+       the first line was an item, it wouldn't be noticed and function
        would return nil.  Simplify and comment code.
 
 2011-07-28  Nicolas Goaziou  <n.goaziou@gmail.com>
@@ -19554,7 +19554,7 @@
 
 2011-07-28  Julien Danjou  <julien@danjou.info>
 
-       * org-agenda.el (org-format-agenda-item): Simplify time comuting.
+       * org-agenda.el (org-format-agenda-item): Simplify time computing.
 
 2011-07-28  Nicolas Goaziou  <n.goaziou@gmail.com>
 
@@ -22539,7 +22539,7 @@
 
 2010-11-11  Dan Davison  <davison@stats.ox.ac.uk>
 
-       * org-src.el (org-src-font-lock-fontify-block): Re-use hidden
+       * org-src.el (org-src-font-lock-fontify-block): Reuse hidden
        language major mode buffers during fontification.
 
 2010-11-11  Dan Davison  <davison@stats.ox.ac.uk>
@@ -26729,7 +26729,7 @@
 2009-11-20  Eric Schulte  <schulte.eric@gmail.com>
 
        * org-exp-blocks.el (org-export-blocks-format-ditaa): Use sha1
-       hash keys to cache and re-use images generated by the
+       hash keys to cache and reuse images generated by the
        org-exp-blocks interface to ditaa and dot.
 
        * org.el (org-format-latex): Latex images are now saved to files
@@ -29300,7 +29300,7 @@
        statistics.
        (org-hierarchical-checkbox-statistics): New option.
 
-       * org.el (org-cycle): Remove erraneous space character.
+       * org.el (org-cycle): Remove erroneous space character.
 
        * org-icalendar.el (org-icalendar-timezone): Initialize from
        environment.
@@ -32833,7 +32833,7 @@
 ;; add-log-time-zone-rule: t
 ;; End:
 
-       Copyright (C) 2008-2023 Free Software Foundation, Inc.
+       Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lisp/org/ob-C.el b/lisp/org/ob-C.el
index 7763c4c07c1..1a25306570e 100644
--- a/lisp/org/ob-C.el
+++ b/lisp/org/ob-C.el
@@ -1,6 +1,6 @@
 ;;; ob-C.el --- Babel Functions for C and Similar Languages -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;;      Thierry Banel
diff --git a/lisp/org/ob-R.el b/lisp/org/ob-R.el
index f2cc069aa5e..670be050bf2 100644
--- a/lisp/org/ob-R.el
+++ b/lisp/org/ob-R.el
@@ -1,6 +1,6 @@
 ;;; ob-R.el --- Babel Functions for R                -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;;     Dan Davison
diff --git a/lisp/org/ob-awk.el b/lisp/org/ob-awk.el
index e5e42a91d14..777baa04234 100644
--- a/lisp/org/ob-awk.el
+++ b/lisp/org/ob-awk.el
@@ -1,6 +1,6 @@
 ;;; ob-awk.el --- Babel Functions for Awk            -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Maintainer: Tyler Smith <tyler@plantarum.ca>
diff --git a/lisp/org/ob-calc.el b/lisp/org/ob-calc.el
index 5572ce818bd..d335aab7499 100644
--- a/lisp/org/ob-calc.el
+++ b/lisp/org/ob-calc.el
@@ -1,6 +1,6 @@
 ;;; ob-calc.el --- Babel Functions for Calc          -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Maintainer: Tom Gillespie <tgbugs@gmail.com>
diff --git a/lisp/org/ob-clojure.el b/lisp/org/ob-clojure.el
index d993e0cb79e..f6d57c01316 100644
--- a/lisp/org/ob-clojure.el
+++ b/lisp/org/ob-clojure.el
@@ -1,6 +1,6 @@
 ;;; ob-clojure.el --- Babel Functions for Clojure    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Joel Boehland, Eric Schulte, Oleh Krehel, Frederick Giasson
 ;; Maintainer: Daniel Kraus <daniel@kraus.my>
diff --git a/lisp/org/ob-comint.el b/lisp/org/ob-comint.el
index adfe31c4008..66861a54ffc 100644
--- a/lisp/org/ob-comint.el
+++ b/lisp/org/ob-comint.el
@@ -1,6 +1,6 @@
 ;;; ob-comint.el --- Babel Functions for Interaction with Comint Buffers -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research, comint
diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el
index 2df3396ee72..0367b11330d 100644
--- a/lisp/org/ob-core.el
+++ b/lisp/org/ob-core.el
@@ -1,6 +1,6 @@
 ;;; ob-core.el --- Working with Code Blocks          -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Authors: Eric Schulte
 ;;     Dan Davison
diff --git a/lisp/org/ob-css.el b/lisp/org/ob-css.el
index f93c576fc5c..4806d80c5b8 100644
--- a/lisp/org/ob-css.el
+++ b/lisp/org/ob-css.el
@@ -1,6 +1,6 @@
 ;;; ob-css.el --- Babel Functions for CSS            -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-ditaa.el b/lisp/org/ob-ditaa.el
index 62200082851..b8ead656fac 100644
--- a/lisp/org/ob-ditaa.el
+++ b/lisp/org/ob-ditaa.el
@@ -1,6 +1,6 @@
 ;;; ob-ditaa.el --- Babel Functions for ditaa        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-dot.el b/lisp/org/ob-dot.el
index ecef071a780..ed2955ba512 100644
--- a/lisp/org/ob-dot.el
+++ b/lisp/org/ob-dot.el
@@ -1,6 +1,6 @@
 ;;; ob-dot.el --- Babel Functions for dot            -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Maintainer: Justin Abrahms <justin@abrah.ms>
diff --git a/lisp/org/ob-emacs-lisp.el b/lisp/org/ob-emacs-lisp.el
index f2111d6493c..2adb6725c3c 100644
--- a/lisp/org/ob-emacs-lisp.el
+++ b/lisp/org/ob-emacs-lisp.el
@@ -1,6 +1,6 @@
 ;;; ob-emacs-lisp.el --- Babel Functions for Emacs-lisp Code -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-eshell.el b/lisp/org/ob-eshell.el
index b3fbe3ad52d..eefb43dc1a9 100644
--- a/lisp/org/ob-eshell.el
+++ b/lisp/org/ob-eshell.el
@@ -1,6 +1,6 @@
 ;;; ob-eshell.el --- Babel Functions for Eshell      -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: stardiviner <numbchild@gmail.com>
 ;; Maintainer: stardiviner <numbchild@gmail.com>
diff --git a/lisp/org/ob-eval.el b/lisp/org/ob-eval.el
index 07e53077253..62c558642a0 100644
--- a/lisp/org/ob-eval.el
+++ b/lisp/org/ob-eval.el
@@ -1,6 +1,6 @@
 ;;; ob-eval.el --- Babel Functions for External Code Evaluation -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research, comint
diff --git a/lisp/org/ob-exp.el b/lisp/org/ob-exp.el
index 4d1b084be01..489ffdb330b 100644
--- a/lisp/org/ob-exp.el
+++ b/lisp/org/ob-exp.el
@@ -1,6 +1,6 @@
 ;;; ob-exp.el --- Exportation of Babel Source Blocks -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Authors: Eric Schulte
 ;;     Dan Davison
diff --git a/lisp/org/ob-forth.el b/lisp/org/ob-forth.el
index e5dcad6d038..c39cce32f11 100644
--- a/lisp/org/ob-forth.el
+++ b/lisp/org/ob-forth.el
@@ -1,6 +1,6 @@
 ;;; ob-forth.el --- Babel Functions for Forth        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research, forth
diff --git a/lisp/org/ob-fortran.el b/lisp/org/ob-fortran.el
index 2c050cb18a8..d1bc06b2bd7 100644
--- a/lisp/org/ob-fortran.el
+++ b/lisp/org/ob-fortran.el
@@ -1,6 +1,6 @@
 ;;; ob-fortran.el --- Babel Functions for Fortran    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Authors: Sergey Litvinov
 ;;       Eric Schulte
diff --git a/lisp/org/ob-gnuplot.el b/lisp/org/ob-gnuplot.el
index e3e42918c75..8d7e62928a2 100644
--- a/lisp/org/ob-gnuplot.el
+++ b/lisp/org/ob-gnuplot.el
@@ -1,6 +1,6 @@
 ;;; ob-gnuplot.el --- Babel Functions for Gnuplot    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Maintainer: Ihor Radchenko <yantar92@gmail.com>
diff --git a/lisp/org/ob-groovy.el b/lisp/org/ob-groovy.el
index c0da69fcbf1..6e5208f5edc 100644
--- a/lisp/org/ob-groovy.el
+++ b/lisp/org/ob-groovy.el
@@ -1,6 +1,6 @@
 ;;; ob-groovy.el --- Babel Functions for Groovy      -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Miro Bezjak <bezjak.miro@gmail.com>
 ;; Maintainer: Palak Mathur <palakmathur@gmail.com>
diff --git a/lisp/org/ob-haskell.el b/lisp/org/ob-haskell.el
index 7185ed61ffe..c891e94283e 100644
--- a/lisp/org/ob-haskell.el
+++ b/lisp/org/ob-haskell.el
@@ -1,6 +1,6 @@
 ;;; ob-haskell.el --- Babel Functions for Haskell    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Maintainer: Lawrence Bottorff <borgauf@gmail.com>
diff --git a/lisp/org/ob-java.el b/lisp/org/ob-java.el
index 89386052666..c0dafbdceba 100644
--- a/lisp/org/ob-java.el
+++ b/lisp/org/ob-java.el
@@ -1,6 +1,6 @@
 ;;; ob-java.el --- org-babel functions for java evaluation -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Authors: Eric Schulte
 ;;          Dan Davison
diff --git a/lisp/org/ob-js.el b/lisp/org/ob-js.el
index de7ea91317f..eb53f3730cf 100644
--- a/lisp/org/ob-js.el
+++ b/lisp/org/ob-js.el
@@ -1,6 +1,6 @@
 ;;; ob-js.el --- Babel Functions for Javascript      -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research, js
diff --git a/lisp/org/ob-julia.el b/lisp/org/ob-julia.el
index cb5c7fa3b02..7a90d16408d 100644
--- a/lisp/org/ob-julia.el
+++ b/lisp/org/ob-julia.el
@@ -1,6 +1,6 @@
 ;;; ob-julia.el --- org-babel functions for julia code evaluation  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 ;; Authors: G. Jay Kerns
 ;; Maintainer: Pedro Bruel <pedro.bruel@gmail.com>
 ;; Keywords: literate programming, reproducible research, scientific computing
diff --git a/lisp/org/ob-latex.el b/lisp/org/ob-latex.el
index ce39628d642..3be59494032 100644
--- a/lisp/org/ob-latex.el
+++ b/lisp/org/ob-latex.el
@@ -1,6 +1,6 @@
 ;;; ob-latex.el --- Babel Functions for LaTeX        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-lilypond.el b/lisp/org/ob-lilypond.el
index 9693b89e23b..d3c7a45933f 100644
--- a/lisp/org/ob-lilypond.el
+++ b/lisp/org/ob-lilypond.el
@@ -1,6 +1,6 @@
 ;;; ob-lilypond.el --- Babel Functions for Lilypond  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Martyn Jago
 ;; Keywords: babel language, literate programming
diff --git a/lisp/org/ob-lisp.el b/lisp/org/ob-lisp.el
index 048ef883ca1..da2d6cf8d61 100644
--- a/lisp/org/ob-lisp.el
+++ b/lisp/org/ob-lisp.el
@@ -1,6 +1,6 @@
 ;;; ob-lisp.el --- Babel Functions for Common Lisp   -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Authors: Joel Boehland
 ;;      Eric Schulte
diff --git a/lisp/org/ob-lob.el b/lisp/org/ob-lob.el
index f77bda73dd6..cf1183f40f4 100644
--- a/lisp/org/ob-lob.el
+++ b/lisp/org/ob-lob.el
@@ -1,6 +1,6 @@
 ;;; ob-lob.el --- Functions Supporting the Library of Babel -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Authors: Eric Schulte
 ;;      Dan Davison
diff --git a/lisp/org/ob-lua.el b/lisp/org/ob-lua.el
index 7eaf5e00b13..6d60538e8ab 100644
--- a/lisp/org/ob-lua.el
+++ b/lisp/org/ob-lua.el
@@ -1,6 +1,6 @@
 ;;; ob-lua.el --- Org Babel functions for Lua evaluation -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2014, 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014, 2016-2024 Free Software Foundation, Inc.
 
 ;; Authors: Dieter Schoen
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-makefile.el b/lisp/org/ob-makefile.el
index 25306159bbb..636108615a5 100644
--- a/lisp/org/ob-makefile.el
+++ b/lisp/org/ob-makefile.el
@@ -1,6 +1,6 @@
 ;;; ob-makefile.el --- Babel Functions for Makefile  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;;        Thomas S. Dye
diff --git a/lisp/org/ob-matlab.el b/lisp/org/ob-matlab.el
index 43344495df2..de8deadbec6 100644
--- a/lisp/org/ob-matlab.el
+++ b/lisp/org/ob-matlab.el
@@ -1,6 +1,6 @@
 ;;; ob-matlab.el --- Babel support for Matlab        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Dan Davison
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-maxima.el b/lisp/org/ob-maxima.el
index d1d7c742440..86f59a08702 100644
--- a/lisp/org/ob-maxima.el
+++ b/lisp/org/ob-maxima.el
@@ -1,6 +1,6 @@
 ;;; ob-maxima.el --- Babel Functions for Maxima      -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric S Fraga
 ;;     Eric Schulte
diff --git a/lisp/org/ob-ocaml.el b/lisp/org/ob-ocaml.el
index 09224b98ba7..48e2d7b76fd 100644
--- a/lisp/org/ob-ocaml.el
+++ b/lisp/org/ob-ocaml.el
@@ -1,6 +1,6 @@
 ;;; ob-ocaml.el --- Babel Functions for Ocaml        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-octave.el b/lisp/org/ob-octave.el
index 1de263a52d0..75f0ad79e02 100644
--- a/lisp/org/ob-octave.el
+++ b/lisp/org/ob-octave.el
@@ -1,6 +1,6 @@
 ;;; ob-octave.el --- Babel Functions for Octave and Matlab -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Dan Davison
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-org.el b/lisp/org/ob-org.el
index 1bf02b461cd..9f6bae6a587 100644
--- a/lisp/org/ob-org.el
+++ b/lisp/org/ob-org.el
@@ -1,6 +1,6 @@
 ;;; ob-org.el --- Babel Functions for Org Code Blocks -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-perl.el b/lisp/org/ob-perl.el
index c8cff5da559..1006ffb12b3 100644
--- a/lisp/org/ob-perl.el
+++ b/lisp/org/ob-perl.el
@@ -1,6 +1,6 @@
 ;;; ob-perl.el --- Babel Functions for Perl          -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Authors: Dan Davison
 ;;      Eric Schulte
diff --git a/lisp/org/ob-plantuml.el b/lisp/org/ob-plantuml.el
index 3202c6e415d..aad210d61e5 100644
--- a/lisp/org/ob-plantuml.el
+++ b/lisp/org/ob-plantuml.el
@@ -1,6 +1,6 @@
 ;;; ob-plantuml.el --- Babel Functions for Plantuml  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Zhang Weize
 ;; Keywords: literate programming, reproducible research
@@ -57,7 +57,7 @@ The JAR can be configured via `org-plantuml-jar-path'.
 
 `plantuml' means to use the PlantUML executable.
 The executable can be configured via `org-plantuml-executable-path'.
-You can also configure extra arguments via `org-plantuml-executable-args'."
+You can also configure extra arguments via `org-plantuml-args'."
   :group 'org-babel
   :package-version '(Org . "9.4")
   :type 'symbol
diff --git a/lisp/org/ob-processing.el b/lisp/org/ob-processing.el
index 4eeaf98e0a2..9b055768c9b 100644
--- a/lisp/org/ob-processing.el
+++ b/lisp/org/ob-processing.el
@@ -1,6 +1,6 @@
 ;;; ob-processing.el --- Babel functions for processing -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Jarmo Hurri (adapted from ob-asymptote.el written by Eric Schulte)
 ;; Maintainer: Jarmo Hurri <jarmo.hurri@iki.fi>
diff --git a/lisp/org/ob-python.el b/lisp/org/ob-python.el
index 48a906a1934..1a442a5a08f 100644
--- a/lisp/org/ob-python.el
+++ b/lisp/org/ob-python.el
@@ -1,6 +1,6 @@
 ;;; ob-python.el --- Babel Functions for Python      -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Authors: Eric Schulte
 ;;      Dan Davison
diff --git a/lisp/org/ob-ref.el b/lisp/org/ob-ref.el
index 2eae3690d93..219a3694452 100644
--- a/lisp/org/ob-ref.el
+++ b/lisp/org/ob-ref.el
@@ -1,6 +1,6 @@
 ;;; ob-ref.el --- Babel Functions for Referencing External Data -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Authors: Eric Schulte
 ;;      Dan Davison
diff --git a/lisp/org/ob-ruby.el b/lisp/org/ob-ruby.el
index b94bc73dd79..ef65ea20d06 100644
--- a/lisp/org/ob-ruby.el
+++ b/lisp/org/ob-ruby.el
@@ -1,6 +1,6 @@
 ;;; ob-ruby.el --- Babel Functions for Ruby          -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-sass.el b/lisp/org/ob-sass.el
index 1498b931efd..a6b4a6462bb 100644
--- a/lisp/org/ob-sass.el
+++ b/lisp/org/ob-sass.el
@@ -1,6 +1,6 @@
 ;;; ob-sass.el --- Babel Functions for the Sass CSS generation language -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-scheme.el b/lisp/org/ob-scheme.el
index ef41a2ec4a5..d13b975084c 100644
--- a/lisp/org/ob-scheme.el
+++ b/lisp/org/ob-scheme.el
@@ -1,6 +1,6 @@
 ;;; ob-scheme.el --- Babel Functions for Scheme      -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Authors: Eric Schulte
 ;;         Michael Gauland
diff --git a/lisp/org/ob-screen.el b/lisp/org/ob-screen.el
index 269538e7967..5a9c36065e6 100644
--- a/lisp/org/ob-screen.el
+++ b/lisp/org/ob-screen.el
@@ -1,6 +1,6 @@
 ;;; ob-screen.el --- Babel Support for Interactive Terminal -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Benjamin Andresen
 ;; Maintainer: Ken Mankoff <mankoff@gmail.com>
diff --git a/lisp/org/ob-sed.el b/lisp/org/ob-sed.el
index 6469901fd07..fa6a2bb199d 100644
--- a/lisp/org/ob-sed.el
+++ b/lisp/org/ob-sed.el
@@ -1,6 +1,6 @@
 ;;; ob-sed.el --- Babel Functions for Sed Scripts    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Bjarte Johansen
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-shell.el b/lisp/org/ob-shell.el
index 87e38e414ce..0c17f466223 100644
--- a/lisp/org/ob-shell.el
+++ b/lisp/org/ob-shell.el
@@ -1,6 +1,6 @@
 ;;; ob-shell.el --- Babel Functions for Shell Evaluation -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-sql.el b/lisp/org/ob-sql.el
index f73e7003f6d..319d864a051 100644
--- a/lisp/org/ob-sql.el
+++ b/lisp/org/ob-sql.el
@@ -1,6 +1,6 @@
 ;;; ob-sql.el --- Babel Functions for SQL            -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Maintainer: Daniel Kraus <daniel@kraus.my>
diff --git a/lisp/org/ob-sqlite.el b/lisp/org/ob-sqlite.el
index 526b73ebd9b..296c9e3e703 100644
--- a/lisp/org/ob-sqlite.el
+++ b/lisp/org/ob-sqlite.el
@@ -1,6 +1,6 @@
 ;;; ob-sqlite.el --- Babel Functions for SQLite Databases -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Maintainer: Nick Savage <nick@nicksavage.ca>
diff --git a/lisp/org/ob-table.el b/lisp/org/ob-table.el
index 5c91f33f877..c96875df08b 100644
--- a/lisp/org/ob-table.el
+++ b/lisp/org/ob-table.el
@@ -1,6 +1,6 @@
 ;;; ob-table.el --- Support for Calling Babel Functions from Tables -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-tangle.el b/lisp/org/ob-tangle.el
index a833037ca2b..13c928df316 100644
--- a/lisp/org/ob-tangle.el
+++ b/lisp/org/ob-tangle.el
@@ -1,6 +1,6 @@
 ;;; ob-tangle.el --- Extract Source Code From Org Files -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob.el b/lisp/org/ob.el
index 4444ced5864..d3a29b83351 100644
--- a/lisp/org/ob.el
+++ b/lisp/org/ob.el
@@ -1,6 +1,6 @@
 ;;; ob.el --- Working with Code Blocks in Org        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Authors: Eric Schulte
 ;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/oc-basic.el b/lisp/org/oc-basic.el
index 5c9aad8f6a5..f05a4da8aab 100644
--- a/lisp/org/oc-basic.el
+++ b/lisp/org/oc-basic.el
@@ -1,6 +1,6 @@
 ;;; oc-basic.el --- basic back-end for citations  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
 
diff --git a/lisp/org/oc-biblatex.el b/lisp/org/oc-biblatex.el
index b2d31f0f635..098a37bd850 100644
--- a/lisp/org/oc-biblatex.el
+++ b/lisp/org/oc-biblatex.el
@@ -1,6 +1,6 @@
 ;;; oc-biblatex.el --- biblatex citation processor for Org  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
 
@@ -26,7 +26,7 @@
 
 ;; The processor relies on "biblatex" LaTeX package.  As such it ensures that
 ;; the package is properly required in the document's preamble.  More
-;; accurately, it will re-use any "\usepackage{biblatex}" already present in
+;; accurately, it will reuse any "\usepackage{biblatex}" already present in
 ;; the document (e.g., through `org-latex-packages-alist'), or insert one using
 ;; options defined in `org-cite-biblatex-options'.
 
diff --git a/lisp/org/oc-bibtex.el b/lisp/org/oc-bibtex.el
index d5e5490ede2..8d04daef97b 100644
--- a/lisp/org/oc-bibtex.el
+++ b/lisp/org/oc-bibtex.el
@@ -1,6 +1,6 @@
 ;;; oc-bibtex.el --- Vanilla citation processor for LaTeX -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
 
diff --git a/lisp/org/oc-csl.el b/lisp/org/oc-csl.el
index 2b00cb59904..ccdf028339e 100644
--- a/lisp/org/oc-csl.el
+++ b/lisp/org/oc-csl.el
@@ -1,6 +1,6 @@
 ;;; oc-csl.el --- csl citation processor for Org -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
 ;; Maintainer: András Simonyi <andras.simonyi@gmail.com>
diff --git a/lisp/org/oc-natbib.el b/lisp/org/oc-natbib.el
index 855be2a5c12..0dddca0e2b4 100644
--- a/lisp/org/oc-natbib.el
+++ b/lisp/org/oc-natbib.el
@@ -1,6 +1,6 @@
 ;;; oc-natbib.el --- Citation processor using natbib LaTeX package  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
 
diff --git a/lisp/org/oc.el b/lisp/org/oc.el
index 8a7b662098a..4270d67787a 100644
--- a/lisp/org/oc.el
+++ b/lisp/org/oc.el
@@ -1,6 +1,6 @@
 ;;; oc.el --- Org Cite library                  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
 
@@ -52,7 +52,7 @@
 ;; through the "cite_export" keyword.
 
 ;; Eventually, this library provides some tools, mainly targeted at
-;; processor implementors.  Most are export-specific and are located
+;; processor implementers.  Most are export-specific and are located
 ;; in the "Tools only available during export" and "Tools generating
 ;; or operating on parsed data" sections.
 
diff --git a/lisp/org/ol-bbdb.el b/lisp/org/ol-bbdb.el
index 47bd9d98cb5..dba587e345e 100644
--- a/lisp/org/ol-bbdb.el
+++ b/lisp/org/ol-bbdb.el
@@ -1,10 +1,10 @@
 ;;; ol-bbdb.el --- Links to BBDB entries             -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Authors: Carsten Dominik <carsten.dominik@gmail.com>
 ;;       Thomas Baumann <thomas dot baumann at ch dot tum dot de>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-bibtex.el b/lisp/org/ol-bibtex.el
index a16a4b39277..ea4b54cc25a 100644
--- a/lisp/org/ol-bibtex.el
+++ b/lisp/org/ol-bibtex.el
@@ -1,11 +1,11 @@
 ;;; ol-bibtex.el --- Links to BibTeX entries        -*- lexical-binding: t; -*-
 ;;
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 ;;
 ;; Authors: Bastien Guerry <bzg@gnu.org>
 ;;       Carsten Dominik <carsten dot dominik at gmail dot com>
 ;;       Eric Schulte <schulte dot eric at gmail dot com>
-;; Keywords: org, wp, capture
+;; Keywords: org, text, capture
 ;;
 ;; This file is part of GNU Emacs.
 ;;
diff --git a/lisp/org/ol-docview.el b/lisp/org/ol-docview.el
index a9cd9b9950f..f12d3558d42 100644
--- a/lisp/org/ol-docview.el
+++ b/lisp/org/ol-docview.el
@@ -1,9 +1,9 @@
 ;;; ol-docview.el --- Links to Docview mode buffers  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Jan Böcker <jan.boecker at jboecker dot de>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-doi.el b/lisp/org/ol-doi.el
index 971b0508787..0550a48b63e 100644
--- a/lisp/org/ol-doi.el
+++ b/lisp/org/ol-doi.el
@@ -1,6 +1,6 @@
 ;;; ol-doi.el --- DOI links support in Org           -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
 
diff --git a/lisp/org/ol-eshell.el b/lisp/org/ol-eshell.el
index b7d3baf3895..dead1aa8a3a 100644
--- a/lisp/org/ol-eshell.el
+++ b/lisp/org/ol-eshell.el
@@ -1,6 +1,6 @@
 ;;; ol-eshell.el --- Links to Working Directories in Eshell  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Konrad Hinsen <konrad.hinsen AT fastmail.net>
 
diff --git a/lisp/org/ol-eww.el b/lisp/org/ol-eww.el
index ee970b6aaa1..fb711c60527 100644
--- a/lisp/org/ol-eww.el
+++ b/lisp/org/ol-eww.el
@@ -1,6 +1,6 @@
 ;;; ol-eww.el --- Store URL and kill from Eww mode    -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Marco Wahl <marcowahlsoft>a<gmailcom>
 ;; Keywords: link, eww
diff --git a/lisp/org/ol-gnus.el b/lisp/org/ol-gnus.el
index 7c07ce0454d..91af4d10a25 100644
--- a/lisp/org/ol-gnus.el
+++ b/lisp/org/ol-gnus.el
@@ -1,10 +1,10 @@
 ;;; ol-gnus.el --- Links to Gnus Groups and Messages -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;;         Tassilo Horn <tassilo at member dot fsf dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-info.el b/lisp/org/ol-info.el
index 350ccf5cc57..48581bd779b 100644
--- a/lisp/org/ol-info.el
+++ b/lisp/org/ol-info.el
@@ -1,9 +1,9 @@
 ;;; ol-info.el --- Links to Info Nodes               -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-irc.el b/lisp/org/ol-irc.el
index 3760644e858..78c4884b00f 100644
--- a/lisp/org/ol-irc.el
+++ b/lisp/org/ol-irc.el
@@ -1,6 +1,6 @@
 ;;; ol-irc.el --- Links to IRC Sessions              -*- lexical-binding: t; 
-*-
 ;;
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Philip Jackson <emacs@shellarchive.co.uk>
 ;; Keywords: erc, irc, link, org
diff --git a/lisp/org/ol-man.el b/lisp/org/ol-man.el
index 40fdc8f9237..5ce04330021 100644
--- a/lisp/org/ol-man.el
+++ b/lisp/org/ol-man.el
@@ -1,9 +1,9 @@
 ;;; ol-man.el --- Links to man pages -*- lexical-binding: t; -*-
 ;;
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Maintainer: Bastien Guerry <bzg@gnu.org>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-mhe.el b/lisp/org/ol-mhe.el
index 403b5a25483..52339c0a622 100644
--- a/lisp/org/ol-mhe.el
+++ b/lisp/org/ol-mhe.el
@@ -1,9 +1,9 @@
 ;;; ol-mhe.el --- Links to MH-E Messages             -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Thomas Baumann <thomas dot baumann at ch dot tum dot de>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-rmail.el b/lisp/org/ol-rmail.el
index 2877798281d..a1af1b94915 100644
--- a/lisp/org/ol-rmail.el
+++ b/lisp/org/ol-rmail.el
@@ -1,9 +1,9 @@
 ;;; ol-rmail.el --- Links to Rmail Messages          -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-w3m.el b/lisp/org/ol-w3m.el
index 6fb01a60d59..e8981173371 100644
--- a/lisp/org/ol-w3m.el
+++ b/lisp/org/ol-w3m.el
@@ -1,9 +1,9 @@
 ;;; ol-w3m.el --- Copy and Paste From W3M            -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Andy Stewart <lazycat dot manatee at gmail dot com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol.el b/lisp/org/ol.el
index cbc02a985c1..ac0c308da21 100644
--- a/lisp/org/ol.el
+++ b/lisp/org/ol.el
@@ -1,9 +1,9 @@
 ;;; ol.el --- Org links library                      -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el
index 670116304e6..f8195a053bc 100644
--- a/lisp/org/org-agenda.el
+++ b/lisp/org/org-agenda.el
@@ -1,9 +1,9 @@
 ;;; org-agenda.el --- Dynamic task and appointment lists for Org  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-archive.el b/lisp/org/org-archive.el
index e74c59a51d9..f5c223661c4 100644
--- a/lisp/org/org-archive.el
+++ b/lisp/org/org-archive.el
@@ -1,9 +1,9 @@
 ;;; org-archive.el --- Archiving for Org             -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-attach-git.el b/lisp/org/org-attach-git.el
index 4763aefd45c..48b2198402d 100644
--- a/lisp/org/org-attach-git.el
+++ b/lisp/org/org-attach-git.el
@@ -1,6 +1,6 @@
 ;;; org-attach-git.el --- Automatic git commit extension to org-attach -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Original Author: John Wiegley <johnw@newartisans.com>
 ;; Restructurer: Gustav Wikström <gustav@whil.se>
diff --git a/lisp/org/org-attach.el b/lisp/org/org-attach.el
index e8b27751e76..7130e5629ab 100644
--- a/lisp/org/org-attach.el
+++ b/lisp/org/org-attach.el
@@ -1,6 +1,6 @@
 ;;; org-attach.el --- Manage file attachments to Org outlines -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@newartisans.com>
 ;; Keywords: org data attachment
diff --git a/lisp/org/org-capture.el b/lisp/org/org-capture.el
index a696c615b2a..1897c096306 100644
--- a/lisp/org/org-capture.el
+++ b/lisp/org/org-capture.el
@@ -1,9 +1,9 @@
 ;;; org-capture.el --- Fast note taking in Org       -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
@@ -1312,7 +1312,7 @@ may have been stored before."
                (while (< (point) end)
                  (indent-to i)
                  (forward-line)))
-             ;; Pre-pending an item could change the type of the list
+             ;; Prepending an item could change the type of the list
              ;; if there is a mismatch.  In this situation,
              ;; prioritize the existing list.
              (when prepend?
diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el
index 6ab313e1218..e79677ad6be 100644
--- a/lisp/org/org-clock.el
+++ b/lisp/org/org-clock.el
@@ -1,9 +1,9 @@
 ;;; org-clock.el --- The time clocking code for Org mode -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-colview.el b/lisp/org/org-colview.el
index 475416ecf74..ccf1ca731a4 100644
--- a/lisp/org/org-colview.el
+++ b/lisp/org/org-colview.el
@@ -1,9 +1,9 @@
 ;;; org-colview.el --- Column View in Org            -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-compat.el b/lisp/org/org-compat.el
index d5bf2191ae7..e9f68518e6f 100644
--- a/lisp/org/org-compat.el
+++ b/lisp/org/org-compat.el
@@ -1,9 +1,9 @@
 ;;; org-compat.el --- Compatibility Code for Older Emacsen -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
@@ -141,7 +141,7 @@ Unibyte strings are converted to multibyte for comparison."
 Elements in COMPONENTS must be a string or nil.
 DIRECTORY or the non-final elements in COMPONENTS may or may not end
 with a slash -- if they don't end with a slash, a slash will be
-inserted before contatenating."
+inserted before concatenating."
     (save-match-data
       (mapconcat
        #'identity
diff --git a/lisp/org/org-crypt.el b/lisp/org/org-crypt.el
index b5df115cf90..ccf1dc63386 100644
--- a/lisp/org/org-crypt.el
+++ b/lisp/org/org-crypt.el
@@ -1,6 +1,6 @@
 ;;; org-crypt.el --- Public Key Encryption for Org Entries -*- 
lexical-binding: t; -*-
 ;;
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/lisp/org/org-ctags.el b/lisp/org/org-ctags.el
index 990214f4117..2417353ee5d 100644
--- a/lisp/org/org-ctags.el
+++ b/lisp/org/org-ctags.el
@@ -1,9 +1,9 @@
 ;;; org-ctags.el --- Integrate Emacs "tags" Facility with Org -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Paul Sexton <eeeickythump@gmail.com>
-;; Keywords: org, wp
+;; Keywords: org, text
 
 ;; This file is part of GNU Emacs.
 ;;
diff --git a/lisp/org/org-cycle.el b/lisp/org/org-cycle.el
index 90fc95f41f7..53e086552f6 100644
--- a/lisp/org/org-cycle.el
+++ b/lisp/org/org-cycle.el
@@ -1,6 +1,6 @@
 ;;; org-cycle.el --- Visibility cycling of Org entries -*- lexical-binding: t; 
-*-
 ;;
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 ;;
 ;; Maintainer: Ihor Radchenko <yantar92 at gmail dot com>
 ;; Keywords: folding, visibility cycling, invisible text
diff --git a/lisp/org/org-datetree.el b/lisp/org/org-datetree.el
index 035ef047a9d..90581f1360c 100644
--- a/lisp/org/org-datetree.el
+++ b/lisp/org/org-datetree.el
@@ -1,9 +1,9 @@
 ;;; org-datetree.el --- Create date entries in a tree -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-duration.el b/lisp/org/org-duration.el
index 2919efd4c77..1ab84776117 100644
--- a/lisp/org/org-duration.el
+++ b/lisp/org/org-duration.el
@@ -1,9 +1,9 @@
 ;;; org-duration.el --- Library handling durations   -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/org-element.el b/lisp/org/org-element.el
index 0dd149762c4..ef96dc024d1 100644
--- a/lisp/org/org-element.el
+++ b/lisp/org/org-element.el
@@ -1,9 +1,9 @@
 ;;; org-element.el --- Parser for Org Syntax         -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
@@ -5484,7 +5484,7 @@ This variable is used to determine when re-parsing buffer 
is not going
 to slow down the command.
 
 If the commands end up modifying the cache, the worst case scenario is
-performance drop.  So, advicing these commands is safe.  Yet, it is
+performance drop.  So, advising these commands is safe.  Yet, it is
 better to remove the commands advised in such a way from this list.")
 
 (defmacro org-element--request-key (request)
@@ -5906,7 +5906,7 @@ If this warning appears regularly, please report the 
warning text to Org mode ma
        (org-element-property :begin element)
        (org-element-property :org-element--cache-sync-key element))
       (org-element-cache-reset)
-      (throw 'quit nil))
+      (throw 'org-element--cache-quit nil))
     (or (avl-tree-delete org-element--cache element)
         (progn
           ;; This should not happen, but if it is, would be better to know
@@ -5919,7 +5919,7 @@ If this warning appears regularly, please report the 
warning text to Org mode ma
            (org-element-property :begin element)
            (org-element-property :org-element--cache-sync-key element))
           (org-element-cache-reset)
-          (throw 'quit nil)))))
+          (throw 'org-element--cache-quit nil)))))
 
 ;;;; Synchronization
 
@@ -6382,6 +6382,10 @@ completing the request."
                          ;; We altered the tree structure.  The tree
                          ;; traversal needs to be restarted.
                          (setf (org-element--request-key request) key)
+                         ;; Make sure that we restart tree traversal
+                         ;; past already shifted elements (before the
+                         ;; removed DATA).
+                         (setq start key)
                          (setf (org-element--request-parent request) parent)
                          ;; Restart tree traversal.
                          (setq node (org-element--cache-root)
@@ -6552,7 +6556,7 @@ the expected result."
                    (error "org-element: Parsing aborted by user.  Cache has 
been cleared.
 If you observe Emacs hangs frequently, please report this to Org mode mailing 
list (M-x org-submit-bug-report)."))
                  (message (substitute-command-keys
-                           "`org-element--parse-buffer': Suppressed 
`\\[keyboard-quit]'.  Press `\\[keyboard-quit]' %d more times to force 
interruption.")
+                           "`org-element--parse-to': Suppressed 
`\\[keyboard-quit]'.  Press `\\[keyboard-quit]' %d more times to force 
interruption.")
                           (- org-element--cache-interrupt-C-g-max-count
                              org-element--cache-interrupt-C-g-count)))
               (unless element
diff --git a/lisp/org/org-entities.el b/lisp/org/org-entities.el
index 61083022b82..5820c7428cd 100644
--- a/lisp/org/org-entities.el
+++ b/lisp/org/org-entities.el
@@ -1,10 +1,10 @@
 ;;; org-entities.el --- Support for Special Entities -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>,
 ;;         Ulf Stegemann <ulf at zeitform dot de>
-;; Keywords: outlines, calendar, wp
+;; Keywords: outlines, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
@@ -41,14 +41,19 @@
 
 (defun org-entities--user-safe-p (v)
   "Non-nil if V is a safe value for `org-entities-user'."
-  (pcase v
-    (`nil t)
-    (`(,(and (pred stringp)
-            (pred (string-match-p "\\`[a-zA-Z][a-zA-Z0-9]*\\'")))
-       ,(pred stringp) ,(pred booleanp) ,(pred stringp)
-       ,(pred stringp) ,(pred stringp) ,(pred stringp))
-     t)
-    (_ nil)))
+  (cond
+   ((not v) t)
+   ((listp v)
+    (seq-every-p
+     (lambda (e)
+       (pcase e
+         (`(,(and (pred stringp)
+                     (pred (string-match-p "\\`[a-zA-Z][a-zA-Z0-9]*\\'")))
+            ,(pred stringp) ,(pred booleanp) ,(pred stringp)
+            ,(pred stringp) ,(pred stringp) ,(pred stringp))
+          t)
+         (_ nil)))
+     v))))
 
 (defcustom org-entities-user nil
   "User-defined entities used in Org to produce special characters.
diff --git a/lisp/org/org-faces.el b/lisp/org/org-faces.el
index bb0958033fe..cb5c423ad0f 100644
--- a/lisp/org/org-faces.el
+++ b/lisp/org/org-faces.el
@@ -1,9 +1,9 @@
 ;;; org-faces.el --- Face definitions -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-feed.el b/lisp/org/org-feed.el
index f0b294b4a59..e4035dd4e96 100644
--- a/lisp/org/org-feed.el
+++ b/lisp/org/org-feed.el
@@ -1,9 +1,9 @@
 ;;; org-feed.el --- Add RSS feed items to Org files  -*- lexical-binding: t; 
-*-
 ;;
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-fold-core.el b/lisp/org/org-fold-core.el
index 6c17b00faf8..be90ca398a1 100644
--- a/lisp/org/org-fold-core.el
+++ b/lisp/org/org-fold-core.el
@@ -1,6 +1,6 @@
 ;;; org-fold-core.el --- Folding buffer text -*- lexical-binding: t; -*-
 ;;
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Ihor Radchenko <yantar92 at gmail dot com>
 ;; Keywords: folding, invisible text
@@ -433,7 +433,7 @@ Return nil when there is no matching folding spec."
   (org-fold-core-get-folding-spec-from-alias spec-or-alias))
 
 (defsubst org-fold-core--check-spec (spec-or-alias)
-  "Throw an error if SPEC-OR-ALIAS is not in 
`org-fold-core--spec-priority-list'."
+  "Throw an error if SPEC-OR-ALIAS is not in 
`org-fold-core-folding-spec-list'."
   (unless (org-fold-core-folding-spec-p spec-or-alias)
     (error "%s is not a valid folding spec" spec-or-alias)))
 
diff --git a/lisp/org/org-fold.el b/lisp/org/org-fold.el
index 1b7ca22b044..241324624c9 100644
--- a/lisp/org/org-fold.el
+++ b/lisp/org/org-fold.el
@@ -1,6 +1,6 @@
 ;;; org-fold.el --- Folding of Org entries -*- lexical-binding: t; -*-
 ;;
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Ihor Radchenko <yantar92 at gmail dot com>
 ;; Keywords: folding, invisible text
diff --git a/lisp/org/org-footnote.el b/lisp/org/org-footnote.el
index 6bdd0b32fed..608d694294c 100644
--- a/lisp/org/org-footnote.el
+++ b/lisp/org/org-footnote.el
@@ -1,9 +1,9 @@
 ;;; org-footnote.el --- Footnote support in Org      -*- lexical-binding: t; 
-*-
 ;;
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-goto.el b/lisp/org/org-goto.el
index 00bf5d46aaa..e9df4057e4b 100644
--- a/lisp/org/org-goto.el
+++ b/lisp/org/org-goto.el
@@ -1,9 +1,9 @@
 ;;; org-goto.el --- Fast navigation in an Org buffer  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/org-habit.el b/lisp/org/org-habit.el
index fb6a48b5f55..ca2910e1538 100644
--- a/lisp/org/org-habit.el
+++ b/lisp/org/org-habit.el
@@ -1,9 +1,9 @@
 ;;; org-habit.el --- The habit tracking code for Org -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw at gnu dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-id.el b/lisp/org/org-id.el
index 490e4ddee5b..9586b728e70 100644
--- a/lisp/org/org-id.el
+++ b/lisp/org/org-id.el
@@ -1,9 +1,9 @@
 ;;; org-id.el --- Global identifiers for Org entries -*- lexical-binding: t; 
-*-
 ;;
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-indent.el b/lisp/org/org-indent.el
index fe52338788c..a612e1c9dc9 100644
--- a/lisp/org/org-indent.el
+++ b/lisp/org/org-indent.el
@@ -1,9 +1,9 @@
 ;;; org-indent.el --- Dynamic indentation for Org    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-inlinetask.el b/lisp/org/org-inlinetask.el
index cb7fdf88bde..7cbdaae4e8e 100644
--- a/lisp/org/org-inlinetask.el
+++ b/lisp/org/org-inlinetask.el
@@ -1,9 +1,9 @@
 ;;; org-inlinetask.el --- Tasks Independent of Outline Hierarchy -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-keys.el b/lisp/org/org-keys.el
index 37a150bb7bf..a0dbb289dba 100644
--- a/lisp/org/org-keys.el
+++ b/lisp/org/org-keys.el
@@ -1,6 +1,6 @@
 ;;; org-keys.el --- Key bindings for Org mode        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
 
diff --git a/lisp/org/org-lint.el b/lisp/org/org-lint.el
index 0e2967b6cb6..5a202808e76 100644
--- a/lisp/org/org-lint.el
+++ b/lisp/org/org-lint.el
@@ -1,9 +1,9 @@
 ;;; org-lint.el --- Linting for Org documents        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/org-list.el b/lisp/org/org-list.el
index 1fc99d0708a..dbef7a82b1f 100644
--- a/lisp/org/org-list.el
+++ b/lisp/org/org-list.el
@@ -1,10 +1,10 @@
 ;;; org-list.el --- Plain lists for Org              -*- lexical-binding: t; 
-*-
 ;;
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;;        Bastien Guerry <bzg@gnu.org>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-macro.el b/lisp/org/org-macro.el
index 481e431c2f9..737eab5d2bb 100644
--- a/lisp/org/org-macro.el
+++ b/lisp/org/org-macro.el
@@ -1,9 +1,9 @@
 ;;; org-macro.el --- Macro Replacement Code for Org  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <n.goaziou@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el
index 4efa8ba6800..2332c0c927c 100644
--- a/lisp/org/org-macs.el
+++ b/lisp/org/org-macs.el
@@ -1,9 +1,9 @@
 ;;; org-macs.el --- Top-level Definitions for Org -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
@@ -56,8 +56,8 @@ by `package-activate-all').")
   ;; `org-assert-version' calls would fail using strict
   ;; `org-git-version' check because the generated Org version strings
   ;; will not match.
-  `(unless (or org--inhibit-version-check (equal (org-release) ,(org-release)))
-     (warn "Org version mismatch.  Org loading aborted.
+  `(unless (or ,org--inhibit-version-check (equal (org-release) 
,(org-release)))
+     (warn "Org version mismatch.
 This warning usually appears when a built-in Org version is loaded
 prior to the more recent Org version.
 
@@ -91,10 +91,15 @@ Version mismatch is commonly encountered in the following 
situations:
    early in the config.  Ideally, right after the straight.el
    bootstrap.  Moving `use-package' :straight declaration may not be
    sufficient if the corresponding `use-package' statement is
-   deferring the loading."
+   deferring the loading.
+
+4. A new Org version is synchronized with Emacs git repository and
+   stale .elc files are still left from the previous build.
+
+   It is recommended to remove .elc files from lisp/org directory and
+   re-compile."
            ;; Avoid `warn' replacing "'" with "’" (see `format-message').
-           "(straight-use-package 'org)")
-     (error "Org version mismatch.  Make sure that correct `load-path' is set 
early in init.el")))
+           "(straight-use-package 'org)")))
 
 ;; We rely on org-macs when generating Org version.  Checking Org
 ;; version here will interfere with Org build process.
@@ -1067,7 +1072,7 @@ Return width in pixels when PIXELS is non-nil."
       ;; FIXME: Fallback to old limited version, because
       ;; `window-pixel-width' is buggy in older Emacs.
       (org--string-width-1 string)
-    ;; Wrap/line prefix will make `window-text-pizel-size' return too
+    ;; Wrap/line prefix will make `window-text-pixel-size' return too
     ;; large value including the prefix.
     (remove-text-properties 0 (length string)
                             '(wrap-prefix t line-prefix t)
@@ -1119,7 +1124,12 @@ Return width in pixels when PIXELS is non-nil."
             (setq pixel-width
                   (if (get-buffer-window (current-buffer))
                       (car (window-text-pixel-size
-                            nil (line-beginning-position) (point-max)))
+                            ;; FIXME: 10000 because
+                            ;; `most-positive-fixnum' ain't working
+                            ;; (tests failing) and this call will be
+                            ;; removed after we drop Emacs 28 support
+                            ;; anyway.
+                            nil (line-beginning-position) (point-max) 10000))
                     (let ((dedicatedp (window-dedicated-p))
                           (oldbuffer (window-buffer)))
                       (unwind-protect
@@ -1128,7 +1138,7 @@ Return width in pixels when PIXELS is non-nil."
                             (set-window-dedicated-p nil nil)
                             (set-window-buffer nil (current-buffer))
                             (car (window-text-pixel-size
-                                  nil (line-beginning-position) (point-max))))
+                                  nil (line-beginning-position) (point-max) 
10000)))
                         (set-window-buffer nil oldbuffer)
                         (set-window-dedicated-p nil dedicatedp)))))
             (unless pixels
@@ -1137,7 +1147,7 @@ Return width in pixels when PIXELS is non-nil."
               (setq symbol-width
                     (if (get-buffer-window (current-buffer))
                         (car (window-text-pixel-size
-                              nil (line-beginning-position) (point-max)))
+                              nil (line-beginning-position) (point-max) 10000))
                       (let ((dedicatedp (window-dedicated-p))
                             (oldbuffer (window-buffer)))
                         (unwind-protect
@@ -1146,7 +1156,7 @@ Return width in pixels when PIXELS is non-nil."
                               (set-window-dedicated-p nil nil)
                               (set-window-buffer nil (current-buffer))
                               (car (window-text-pixel-size
-                                    nil (line-beginning-position) 
(point-max))))
+                                    nil (line-beginning-position) (point-max) 
10000)))
                           (set-window-buffer nil oldbuffer)
                           (set-window-dedicated-p nil dedicatedp)))))))
           (if pixels
diff --git a/lisp/org/org-mobile.el b/lisp/org/org-mobile.el
index 01395a4b616..c34011fc3dc 100644
--- a/lisp/org/org-mobile.el
+++ b/lisp/org/org-mobile.el
@@ -1,8 +1,8 @@
 ;;; org-mobile.el --- Code for Asymmetric Sync With a Mobile Device -*- 
lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-mouse.el b/lisp/org/org-mouse.el
index 9c9dfee51a1..35d1b6f1ce1 100644
--- a/lisp/org/org-mouse.el
+++ b/lisp/org/org-mouse.el
@@ -1,6 +1,6 @@
 ;;; org-mouse.el --- Better mouse support for Org -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Piotr Zielinski <piotr dot zielinski at gmail dot com>
 ;; Maintainer: Carsten Dominik <carsten.dominik@gmail.com>
diff --git a/lisp/org/org-num.el b/lisp/org/org-num.el
index 807fa66223b..00a25b11e53 100644
--- a/lisp/org/org-num.el
+++ b/lisp/org/org-num.el
@@ -1,9 +1,9 @@
 ;;; org-num.el --- Dynamic Headlines Numbering  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/org-pcomplete.el b/lisp/org/org-pcomplete.el
index 0567052c089..c793563570b 100644
--- a/lisp/org/org-pcomplete.el
+++ b/lisp/org/org-pcomplete.el
@@ -1,10 +1,10 @@
 ;;; org-pcomplete.el --- In-buffer Completion Code -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;;         John Wiegley <johnw at gnu dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-persist.el b/lisp/org/org-persist.el
index 01078f4596d..9acf35bd488 100644
--- a/lisp/org/org-persist.el
+++ b/lisp/org/org-persist.el
@@ -1,6 +1,6 @@
 ;;; org-persist.el --- Persist cached data across Emacs sessions         -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Ihor Radchenko <yantar92 at gmail dot com>
 ;; Keywords: cache, storage
@@ -111,7 +111,7 @@
 ;;
 ;; Each collection is represented as a plist containing the following
 ;; properties:
-;; - `:container'   : list of data continers to be stored in single
+;; - `:container'   : list of data containers to be stored in single
 ;;                    file;
 ;; - `:persist-file': data file name;
 ;; - `:associated'  : list of associated objects;
@@ -253,7 +253,7 @@ The index is a list of plists.  Each plist contains 
information about
 persistent data storage.  Each plist contains the following
 properties:
 
-  - `:container'  : list of data continers to be stored in single file
+  - `:container'  : list of data containers to be stored in single file
   - `:persist-file': data file name
   - `:associated'  : list of associated objects
   - `:last-access' : last date when the container has been read
@@ -481,9 +481,14 @@ MISC, if non-nil will be appended to the collection.  It 
must be a plist."
      (unless (stringp associated)
        (setq associated (cadr associated)))
      (let* ((rtn `(:file ,associated))
-            (inode (and (fboundp 'file-attribute-inode-number)
-                        (file-attribute-inode-number
-                         (file-attributes associated)))))
+            (inode (and
+                    ;; Do not store :inode for remote files - it may
+                    ;; be time-consuming on slow connections or even
+                    ;; fail completely when ssh connection is closed.
+                    (not (file-remote-p associated))
+                    (fboundp 'file-attribute-inode-number)
+                    (file-attribute-inode-number
+                     (file-attributes associated)))))
        (when inode (plist-put rtn :inode inode))
        rtn))
     ((or (pred bufferp) `(:buffer ,_))
@@ -501,6 +506,10 @@ MISC, if non-nil will be appended to the collection.  It 
must be a plist."
                      (or (buffer-base-buffer associated)
                          associated)))
          (setq inode (when (and file
+                                ;; Do not store :inode for remote files - it 
may
+                                ;; be time-consuming on slow connections or 
even
+                                ;; fail completely when ssh connection is 
closed.
+                                (not (file-remote-p file))
                                 (fboundp 'file-attribute-inode-number))
                        (file-attribute-inode-number
                         (file-attributes file))))
diff --git a/lisp/org/org-plot.el b/lisp/org/org-plot.el
index fe61e9ace7e..3fea8b5b8b4 100644
--- a/lisp/org/org-plot.el
+++ b/lisp/org/org-plot.el
@@ -1,6 +1,6 @@
 ;;; org-plot.el --- Support for Plotting from Org -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Eric Schulte <schulte dot eric at gmail dot com>
 ;; Maintainer: TEC <orgmode@tec.tecosaur.net>
diff --git a/lisp/org/org-protocol.el b/lisp/org/org-protocol.el
index 2b07a377e2a..61a9229adf1 100644
--- a/lisp/org/org-protocol.el
+++ b/lisp/org/org-protocol.el
@@ -1,13 +1,13 @@
 ;;; org-protocol.el --- Intercept Calls from Emacsclient to Trigger Custom 
Actions -*- lexical-binding: t; -*-
 ;;
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 ;;
 ;; Authors: Bastien Guerry <bzg@gnu.org>
 ;;       Daniel M German <dmg AT uvic DOT org>
 ;;       Sebastian Rose <sebastian_rose AT gmx DOT de>
 ;;       Ross Patterson <me AT rpatterson DOT net>
 ;; Maintainer: Sebastian Rose <sebastian_rose AT gmx DOT de>
-;; Keywords: org, emacsclient, wp
+;; Keywords: org, emacsclient, text
 
 ;; This file is part of GNU Emacs.
 ;;
@@ -34,7 +34,10 @@
 ;; `org-protocol-protocol-alist' and `org-protocol-protocol-alist-default'.
 ;;
 ;; Any application that supports calling external programs with an URL
-;; as argument may be used with this functionality.
+;; as argument could use this functionality.  For example, you can
+;; configure bookmarks in your web browser to send a link to the
+;; current page to Org and create a note from it using `org-capture'.
+;; See Info node `(org) Protocols' for more information.
 ;;
 ;;
 ;; Usage:
@@ -44,13 +47,13 @@
 ;;
 ;;       (require 'org-protocol)
 ;;
-;;   3.) Ensure emacs-server is up and running.
-;;   4.) Try this from the command line (adjust the URL as needed):
+;;   2.) Ensure emacs-server is up and running.
+;;   3.) Try this from the command line (adjust the URL as needed):
 ;;
 ;;       $ emacsclient \
 ;;         
"org-protocol://store-link?url=http:%2F%2Flocalhost%2Findex.html&title=The%20title"
 ;;
-;;   5.) Optionally add custom sub-protocols and handlers:
+;;   4.) Optionally, add custom sub-protocols and handlers:
 ;;
 ;;       (setq org-protocol-protocol-alist
 ;;             '(("my-protocol"
@@ -64,10 +67,11 @@
 ;; If it works, you can now setup other applications for using this feature.
 ;;
 ;;
-;; As of March 2009 Firefox users follow the steps documented on
-;; https://kb.mozillazine.org/Register_protocol, Opera setup is described here:
-;; http://www.opera.com/support/kb/view/535/
+;; Firefox users follow the steps documented on
+;; https://kb.mozillazine.org/Register_protocol, Opera setup is
+;; described here: http://www.opera.com/support/kb/view/535/
 ;;
+;; See also: https://orgmode.org/worg/org-contrib/org-protocol.html
 ;;
 ;; Documentation
 ;; -------------
@@ -123,9 +127,6 @@
 ;; Note that using double slashes is optional from org-protocol.el's point of
 ;; view because emacsclient squashes the slashes to one.
 ;;
-;;
-;; provides: 'org-protocol
-;;
 ;;; Code:
 
 (require 'org-macs)
diff --git a/lisp/org/org-refile.el b/lisp/org/org-refile.el
index 5a41c022fee..4f204c739fa 100644
--- a/lisp/org/org-refile.el
+++ b/lisp/org/org-refile.el
@@ -1,9 +1,9 @@
 ;;; org-refile.el --- Refile Org Subtrees             -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;;
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/org-src.el b/lisp/org/org-src.el
index aadd8eba579..8cc11965812 100644
--- a/lisp/org/org-src.el
+++ b/lisp/org/org-src.el
@@ -1,11 +1,11 @@
 ;;; org-src.el --- Source code examples in Org       -*- lexical-binding: t; 
-*-
 ;;
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;;        Bastien Guerry <bzg@gnu.org>
 ;;         Dan Davison <davison at stats dot ox dot ac dot uk>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
@@ -658,7 +658,9 @@ as `org-src-fontify-natively' is non-nil."
                     (when new-prop
                       (if (not (eq prop 'invisible))
                          (put-text-property
-                          (+ start (1- pos)) (1- (+ start next)) prop new-prop
+                          (+ start (- pos (point-min)))
+                          (+ start (- next (point-min)))
+                          prop new-prop
                           org-buffer)
                         ;; Special case.  `invisible' text property may
                         ;; clash with Org folding.  Do not assign
@@ -690,7 +692,8 @@ as `org-src-fontify-natively' is non-nil."
                             (when invisibility-spec
                               (add-to-invisibility-spec invisibility-spec))
                             (put-text-property
-                            (+ start (1- pos)) (1- (+ start next))
+                            (+ start (- pos (point-min)))
+                            (+ start (- next (point-min)))
                              'org-src-invisible new-prop
                             org-buffer)))))))
                (setq pos next)))
diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el
index aa819aa7d2f..bf0f503da2e 100644
--- a/lisp/org/org-table.el
+++ b/lisp/org/org-table.el
@@ -1,9 +1,9 @@
 ;;; org-table.el --- The Table Editor for Org        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
@@ -4894,7 +4894,7 @@ This function sets up the following dynamically scoped 
variables:
                        (push (cons field v) org-table-local-parameters)
                        (push (list field line col)
                              org-table-named-field-locations))))))))))
-      ;; Re-use existing markers when possible.
+      ;; Reuse existing markers when possible.
       (if (markerp org-table-current-begin-pos)
          (move-marker org-table-current-begin-pos (point))
        (setq org-table-current-begin-pos (point-marker)))
diff --git a/lisp/org/org-tempo.el b/lisp/org/org-tempo.el
index 81ec8fdccfe..638f0ea3f4a 100644
--- a/lisp/org/org-tempo.el
+++ b/lisp/org/org-tempo.el
@@ -1,9 +1,9 @@
 ;;; org-tempo.el --- Template expansion for Org structures -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Rasmus Pank Roulund <emacs at pank dot eu>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-timer.el b/lisp/org/org-timer.el
index 919630e696f..561b2bc0f83 100644
--- a/lisp/org/org-timer.el
+++ b/lisp/org/org-timer.el
@@ -1,9 +1,9 @@
 ;;; org-timer.el --- Timer code for Org mode         -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;;
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el
index e5b0fbcf2a9..b41756ac53e 100644
--- a/lisp/org/org-version.el
+++ b/lisp/org/org-version.el
@@ -5,13 +5,13 @@
 (defun org-release ()
   "The release version of Org.
 Inserted by installing Org mode or when a release is made."
-   (let ((org-release "9.6.11"))
+   (let ((org-release "9.6.15"))
      org-release))
 ;;;###autoload
 (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.11"))
+   (let ((org-git-version "release_9.6.15"))
      org-git-version))
 
 (provide 'org-version)
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 34c572a3f57..2c5de69a36c 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -1,15 +1,15 @@
 ;;; org.el --- Outline-based notes management and organizer -*- 
lexical-binding: t; -*-
 
 ;; Carstens outline-mode for keeping track of everything.
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;; Maintainer: Bastien Guerry <bzg@gnu.org>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 ;; Package-Requires: ((emacs "26.1"))
 
-;; Version: 9.6.11
+;; Version: 9.6.15
 
 ;; This file is part of GNU Emacs.
 ;;
@@ -1230,7 +1230,7 @@ This applies to indirect buffers created with the commands
 Valid values are:
 current-window   Display in the current window
 other-window     Just display in another window.
-dedicated-frame  Create one new frame, and re-use it each time.
+dedicated-frame  Create one new frame, and reuse it each time.
 new-frame        Make a new frame each time.  Note that in this case
                  previously-made indirect buffers are kept, and you need to
                  kill these buffers yourself."
@@ -4582,7 +4582,7 @@ is available.  This option applies only if FILE is a URL."
                            file)
                   nil))
             (error (if noerror
-                       (message "Org could't download \"%s\": %s %S" file (car 
error) (cdr error))
+                       (message "Org couldn't download \"%s\": %s %S" file 
(car error) (cdr error))
                      (signal (car error) (cdr error)))))
         (funcall (if noerror #'message #'user-error)
                  "The remote resource %S is considered unsafe, and will not be 
downloaded."
@@ -19985,7 +19985,7 @@ With argument N not nil or 1, move forward N - 1 lines 
first."
        (if (eq special 'reversed)
            (when (and (= origin bol) (eq last-command this-command))
              (goto-char refpos))
-         (when (or (> origin refpos) (= origin bol))
+         (when (or (> origin refpos) (<= origin bol))
            (goto-char refpos)))))
      ((and (looking-at org-list-full-item-re)
           (memq (org-element-type (save-match-data (org-element-at-point)))
@@ -20000,7 +20000,7 @@ With argument N not nil or 1, move forward N - 1 lines 
first."
        (if (eq special 'reversed)
            (when (and (= (point) origin) (eq last-command this-command))
              (goto-char after-bullet))
-         (when (or (> origin after-bullet) (= (point) origin))
+         (when (or (> origin after-bullet) (>= (point) origin))
            (goto-char after-bullet)))))
      ;; No special context.  Point is already at beginning of line.
      (t nil))))
@@ -20055,7 +20055,7 @@ With argument N not nil or 1, move forward N - 1 lines 
first."
                   (goto-char tags)
                 (end-of-line)))
              (t
-              (if (or (< origin tags) (= origin (line-end-position)))
+              (if (or (< origin tags) (>= origin (line-end-position)))
                   (goto-char tags)
                 (end-of-line))))))
      ((bound-and-true-p visual-line-mode)
diff --git a/lisp/org/ox-ascii.el b/lisp/org/ox-ascii.el
index 692dd216d61..74fbe20e85d 100644
--- a/lisp/org/ox-ascii.el
+++ b/lisp/org/ox-ascii.el
@@ -1,10 +1,10 @@
 ;;; ox-ascii.el --- ASCII Back-End for Org Export Engine -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
 ;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/ox-beamer.el b/lisp/org/ox-beamer.el
index 2590bd5fa72..3d4d998432d 100644
--- a/lisp/org/ox-beamer.el
+++ b/lisp/org/ox-beamer.el
@@ -1,11 +1,11 @@
 ;;; ox-beamer.el --- Beamer Back-End for Org Export Engine -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik AT gmail DOT com>
 ;;         Nicolas Goaziou <n.goaziou AT gmail DOT com>
 ;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: org, wp, tex
+;; Keywords: org, text, tex
 
 ;; This file is part of GNU Emacs.
 
@@ -929,7 +929,7 @@ holding export options."
  '((":\\(B_[a-z]+\\|BMCOL\\):" 1 'org-beamer-tag prepend))
  'prepend)
 
-(defface org-beamer-tag '((t (:box (:line-width 1 :color grey40))))
+(defface org-beamer-tag '((t (:box (:line-width 1 :color "grey40"))))
   "The special face for beamer tags."
   :group 'org-export-beamer)
 
diff --git a/lisp/org/ox-html.el b/lisp/org/ox-html.el
index cfad311207a..cde4f6117ec 100644
--- a/lisp/org/ox-html.el
+++ b/lisp/org/ox-html.el
@@ -1,11 +1,11 @@
 ;;; ox-html.el --- HTML Back-End for Org Export Engine -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;;      Jambunathan K <kjambunathan at gmail dot com>
 ;; Maintainer: TEC <orgmode@tec.tecosaur.net>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/ox-icalendar.el b/lisp/org/ox-icalendar.el
index 81a77a77056..1a6d29938fd 100644
--- a/lisp/org/ox-icalendar.el
+++ b/lisp/org/ox-icalendar.el
@@ -1,11 +1,11 @@
 ;;; ox-icalendar.el --- iCalendar Back-End for Org Export Engine -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
 ;;      Nicolas Goaziou <mail@nicolasgoaziou.fr>
 ;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/ox-koma-letter.el b/lisp/org/ox-koma-letter.el
index 33eb0597b08..aef25232c20 100644
--- a/lisp/org/ox-koma-letter.el
+++ b/lisp/org/ox-koma-letter.el
@@ -1,13 +1,13 @@
 ;;; ox-koma-letter.el --- KOMA Scrlttr2 Back-End for Org Export Engine  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <n.goaziou AT gmail DOT com>
 ;;         Alan Schmitt <alan.schmitt AT polytechnique DOT org>
 ;;         Viktor Rosenfeld <listuser36 AT gmail DOT com>
 ;;         Rasmus Pank Roulund <emacs AT pank DOT eu>
 ;; Maintainer: Marco Wahl <marcowahlsoft@gmail.com>
-;; Keywords: org, wp, tex
+;; Keywords: org, text, tex
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/ox-latex.el b/lisp/org/ox-latex.el
index 768bf402b70..b409f552a2b 100644
--- a/lisp/org/ox-latex.el
+++ b/lisp/org/ox-latex.el
@@ -1,10 +1,10 @@
 ;;; ox-latex.el --- LaTeX Back-End for Org Export Engine -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
 ;; Maintainer: Daniel Fleischer <danflscr@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
@@ -978,7 +978,7 @@ The most comprehensive option can be set with,
 which causes source code to be run through
 `engrave-faces-latex-buffer', which generates colorings using
 Emacs' font-lock information.  This requires the Emacs package
-engrave-faces (available from ELPA), and the LaTeX package
+engrave-faces (available from GNU ELPA), and the LaTeX package
 fvextra be installed.
 
 The styling of the engraved result can be customized with
@@ -1262,9 +1262,10 @@ block-specific options, you may use the following syntax:
 
 (defcustom org-latex-engraved-theme nil
   "The theme that should be used for engraved code, when non-nil.
-This can be set to any theme defined in `engrave-faces-themes' or
-loadable by Emacs.  When set to t, the current Emacs theme is
-used.  When nil, no theme is applied."
+This can be set to any theme defined in `engrave-faces-themes'
+(from the engrave-faces package) or loadable by Emacs.  When set
+to t, the current Emacs theme is used.  When nil, no theme is
+applied."
   :group 'org-export-latex
   :package-version '(Org . "9.6")
   :type 'symbol)
@@ -3666,7 +3667,7 @@ CONTENTS is the contents of the object."
 ;; takes care of tables with a "verbatim" mode.  Otherwise, it
 ;; delegates the job to either `org-latex--table.el-table',
 ;; `org-latex--org-table', `org-latex--math-table' or
-;; `org-latex--org-tabbing' functions,
+;; `org-table--org-tabbing' functions,
 ;; depending of the type of the table and the mode requested.
 ;;
 ;; `org-latex--align-string' is a subroutine used to build alignment
diff --git a/lisp/org/ox-man.el b/lisp/org/ox-man.el
index bb716f7b9f2..2019a531fa7 100644
--- a/lisp/org/ox-man.el
+++ b/lisp/org/ox-man.el
@@ -1,10 +1,10 @@
 ;;; ox-man.el --- Man Back-End for Org Export Engine -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
 ;;      Luis R Anaya <papoanaya aroba hot mail punto com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/ox-md.el b/lisp/org/ox-md.el
index 5be0ca22e07..35bc4aa642b 100644
--- a/lisp/org/ox-md.el
+++ b/lisp/org/ox-md.el
@@ -1,10 +1,10 @@
 ;;; ox-md.el --- Markdown Back-End for Org Export Engine -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <n.goaziou@gmail.com>
 ;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: org, wp, markdown
+;; Keywords: org, text, markdown
 
 ;; This file is part of GNU Emacs.
 
@@ -305,7 +305,7 @@ INFO is a plist used as a communication channel."
          (section-title (org-html--translate "Footnotes" info)))
     (when fn-alist
       (format (plist-get info :md-footnotes-section)
-              (org-md--headline-title headline-style 1 section-title)
+              (org-md--headline-title headline-style (plist-get info 
:md-toplevel-hlevel) section-title)
               (mapconcat (lambda (fn) (org-md--footnote-formatted fn info))
                          fn-alist
                          "\n")))))
diff --git a/lisp/org/ox-odt.el b/lisp/org/ox-odt.el
index dd96ed8e064..d0d4727e7aa 100644
--- a/lisp/org/ox-odt.el
+++ b/lisp/org/ox-odt.el
@@ -1,9 +1,9 @@
 ;;; ox-odt.el --- OpenDocument Text Exporter for Org Mode -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Jambunathan K <kjambunathan at gmail dot com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 ;; URL: https://orgmode.org
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/org/ox-org.el b/lisp/org/ox-org.el
index ed72cf4f2ba..fdd0658fb62 100644
--- a/lisp/org/ox-org.el
+++ b/lisp/org/ox-org.el
@@ -1,10 +1,10 @@
 ;;; ox-org.el --- Org Back-End for Org Export Engine -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <n.goaziou@gmail.com>
 ;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: org, wp
+;; Keywords: org, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/ox-publish.el b/lisp/org/ox-publish.el
index cff34f05882..ce45c6f1b77 100644
--- a/lisp/org/ox-publish.el
+++ b/lisp/org/ox-publish.el
@@ -1,9 +1,9 @@
 ;;; ox-publish.el --- Publish Related Org Mode Files as a Website -*- 
lexical-binding: t; -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: David O'Toole <dto@gnu.org>
 ;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: hypermedia, outlines, wp
+;; Keywords: hypermedia, outlines, text
 
 ;; This file is part of GNU Emacs.
 ;;
diff --git a/lisp/org/ox-texinfo.el b/lisp/org/ox-texinfo.el
index 5befcac1c39..84313645e6e 100644
--- a/lisp/org/ox-texinfo.el
+++ b/lisp/org/ox-texinfo.el
@@ -1,9 +1,9 @@
 ;;; ox-texinfo.el --- Texinfo Back-End for Org Export Engine -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 ;; Author: Jonathan Leech-Pepin <jonathan.leechpepin at gmail dot com>
 ;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/org/ox.el b/lisp/org/ox.el
index e9cc0ed8fc7..19bf559c9e7 100644
--- a/lisp/org/ox.el
+++ b/lisp/org/ox.el
@@ -1,10 +1,10 @@
 ;;; ox.el --- Export Framework for Org Mode          -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
 ;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/outline.el b/lisp/outline.el
index d8dd491212e..b50708c1a7b 100644
--- a/lisp/outline.el
+++ b/lisp/outline.el
@@ -1,6 +1,6 @@
 ;;; outline.el --- outline mode commands for Emacs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1986-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: outlines
@@ -260,7 +260,7 @@ non-nil and point is located on the heading line.")
   '(
     ;; Highlight headings according to the level.
     (eval . (list (or outline-search-function
-                      (concat "^\\(?:" outline-regexp "\\).*"))
+                      (concat "^\\(?:" outline-regexp "\\).*" 
outline-heading-end-regexp))
                   0 '(if outline-minor-mode
                          (if outline-minor-mode-highlight
                              (list 'face (outline-font-lock-face)))
diff --git a/lisp/paren.el b/lisp/paren.el
index 6296d7e67fa..cb29b8311a5 100644
--- a/lisp/paren.el
+++ b/lisp/paren.el
@@ -1,6 +1,6 @@
 ;;; paren.el --- highlight matching paren  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1993, 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: rms@gnu.org
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/password-cache.el b/lisp/password-cache.el
index b131a6eb63f..0280c31a624 100644
--- a/lisp/password-cache.el
+++ b/lisp/password-cache.el
@@ -1,6 +1,6 @@
 ;;; password-cache.el --- Read passwords, possibly using a password cache.  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1999-2000, 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 ;; Created: 2003-12-21
diff --git a/lisp/pcmpl-cvs.el b/lisp/pcmpl-cvs.el
index 0ad70e96b27..ed83052bdb9 100644
--- a/lisp/pcmpl-cvs.el
+++ b/lisp/pcmpl-cvs.el
@@ -1,6 +1,6 @@
 ;;; pcmpl-cvs.el --- functions for dealing with cvs completions  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Package: pcomplete
diff --git a/lisp/pcmpl-git.el b/lisp/pcmpl-git.el
index 698d2e747b5..95b6859dd23 100644
--- a/lisp/pcmpl-git.el
+++ b/lisp/pcmpl-git.el
@@ -1,6 +1,6 @@
 ;;; pcmpl-git.el --- Completions for Git -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Package: pcomplete
 
@@ -88,7 +88,7 @@ Files listed by `git ls-files ARGS' satisfy the predicate."
                  (pcomplete-entries
                   nil (pcmpl-git--tracked-file-predicate "-m"))))
                ;; Complete all tracked files
-               ((or "mv" "rm" "grep" "status")
+               ((or "mv" "rm" "grep" "status" "blame")
                 (pcomplete-here
                  (pcomplete-entries nil (pcmpl-git--tracked-file-predicate))))
                ;; Complete revisions
diff --git a/lisp/pcmpl-gnu.el b/lisp/pcmpl-gnu.el
index 1553c3efed7..237e3d62526 100644
--- a/lisp/pcmpl-gnu.el
+++ b/lisp/pcmpl-gnu.el
@@ -1,6 +1,6 @@
 ;;; pcmpl-gnu.el --- completions for GNU project tools -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Package: pcomplete
 
diff --git a/lisp/pcmpl-linux.el b/lisp/pcmpl-linux.el
index 589b4799c8d..d0defc54174 100644
--- a/lisp/pcmpl-linux.el
+++ b/lisp/pcmpl-linux.el
@@ -1,6 +1,6 @@
 ;;; pcmpl-linux.el --- functions for dealing with GNU/Linux completions  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Package: pcomplete
 
@@ -61,7 +61,7 @@
   (pcomplete-opt "hVanfFrsvwt(pcmpl-linux-fs-types)o?L?U?")
   (while (pcomplete-here (pcomplete-entries) nil #'identity)))
 
-(defconst pcmpl-linux-fs-modules-path-format "/lib/modules/%s/kernel/fs/")
+(defvar pcmpl-linux-fs-modules-path-format "/lib/modules/%s/kernel/fs/")
 
 (defun pcmpl-linux-fs-types ()
   "Return a list of available fs modules on GNU/Linux systems."
@@ -69,7 +69,7 @@
     (directory-files
      (format pcmpl-linux-fs-modules-path-format kernel-ver))))
 
-(defconst pcmpl-linux-mtab-file "/etc/mtab")
+(defvar pcmpl-linux-mtab-file "/etc/mtab")
 
 (defun pcmpl-linux-mounted-directories ()
   "Return a list of mounted directory names."
diff --git a/lisp/pcmpl-rpm.el b/lisp/pcmpl-rpm.el
index f8f43a505ea..65c12d2337e 100644
--- a/lisp/pcmpl-rpm.el
+++ b/lisp/pcmpl-rpm.el
@@ -1,6 +1,6 @@
 ;;; pcmpl-rpm.el --- functions for dealing with rpm completions  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Package: pcomplete
 
diff --git a/lisp/pcmpl-unix.el b/lisp/pcmpl-unix.el
index 7af5f2bce74..65308cffec4 100644
--- a/lisp/pcmpl-unix.el
+++ b/lisp/pcmpl-unix.el
@@ -1,6 +1,6 @@
 ;;; pcmpl-unix.el --- standard UNIX completions  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Package: pcomplete
 
diff --git a/lisp/pcmpl-x.el b/lisp/pcmpl-x.el
index 4ee7b4aa52b..8af78345f35 100644
--- a/lisp/pcmpl-x.el
+++ b/lisp/pcmpl-x.el
@@ -1,6 +1,6 @@
 ;;; pcmpl-x.el --- completion for miscellaneous tools  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Leo Liu <sdl.web@gmail.com>
 ;; Keywords: processes, tools, convenience
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index 3dde001328d..196c5f159cd 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -1,6 +1,6 @@
 ;;; pcomplete.el --- programmable completion -*- lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Keywords: processes abbrev
@@ -902,14 +902,16 @@ this is `comint-dynamic-complete-functions'."
                      (and dir-ignore (string-match dir-ignore file))
                    (and file-ignore (string-match file-ignore file))))))))
          (reg-pred (if regexp (lambda (file) (string-match regexp file))))
-         (pred (cond
-                ((null (or ign-pred reg-pred))  predicate)
-                ((null (or ign-pred predicate)) reg-pred)
-                ((null (or reg-pred predicate)) ign-pred)
-                (t (lambda (f)
+         ;; `completion-file-name-table' calls `file-exists-p' when
+         ;; the predicate is nil.
+         ;; So likewise, defer to PREDICATE if it's there, else take
+         ;; ourselves to be responsible for calling `file-exists-p'.
+         (pred (if (or ign-pred reg-pred)
+                   (lambda (f)
                      (and (or (null reg-pred)  (funcall reg-pred f))
                           (or (null ign-pred)  (funcall ign-pred f))
-                          (or (null predicate) (funcall predicate f))))))))
+                          (funcall (or predicate #'file-exists-p) f)))
+                 predicate)))
     (lambda (s p a)
       (if (and (eq a 'metadata) pcomplete-compare-entry-function)
           `(metadata (cycle-sort-function
diff --git a/lisp/pgtk-dnd.el b/lisp/pgtk-dnd.el
index 48edaa2472a..edc51320a79 100644
--- a/lisp/pgtk-dnd.el
+++ b/lisp/pgtk-dnd.el
@@ -1,6 +1,6 @@
 ;;; pgtk-dnd.el --- drag and drop support for GDK -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: window, drag, drop
diff --git a/lisp/pixel-scroll.el b/lisp/pixel-scroll.el
index 224a2b5f1e0..4bf912e54c0 100644
--- a/lisp/pixel-scroll.el
+++ b/lisp/pixel-scroll.el
@@ -1,6 +1,6 @@
 ;;; pixel-scroll.el --- Scroll a line smoothly  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 ;; Author: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
 ;; Keywords: mouse
 ;; Package: emacs
diff --git a/lisp/play/5x5.el b/lisp/play/5x5.el
index 772c252512d..d3393cbf9d1 100644
--- a/lisp/play/5x5.el
+++ b/lisp/play/5x5.el
@@ -1,6 +1,6 @@
 ;;; 5x5.el --- simple little puzzle game  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Pearson <davep@davep.org>
 ;; Created: 1998-10-03
diff --git a/lisp/play/animate.el b/lisp/play/animate.el
index 01e7a91f03c..33df0a65797 100644
--- a/lisp/play/animate.el
+++ b/lisp/play/animate.el
@@ -1,6 +1,6 @@
 ;;; animate.el --- make text dance  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: Richard Stallman <rms@gnu.org>
 ;; Keywords: games
diff --git a/lisp/play/blackbox.el b/lisp/play/blackbox.el
index dff585a5983..b8bbfda7821 100644
--- a/lisp/play/blackbox.el
+++ b/lisp/play/blackbox.el
@@ -1,6 +1,6 @@
 ;;; blackbox.el --- blackbox game in Emacs Lisp  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-1987, 1992, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985-1987, 1992, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: F. Thomas May <uw-nsr!uw-warp!tom@beaver.cs.washington.edu>
diff --git a/lisp/play/bubbles.el b/lisp/play/bubbles.el
index e68778d28b2..112b02605da 100644
--- a/lisp/play/bubbles.el
+++ b/lisp/play/bubbles.el
@@ -1,6 +1,6 @@
 ;;; bubbles.el --- Puzzle game for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author:      Ulf Jasper <ulf.jasper@web.de>
 ;; URL:         http://ulf.epplejasper.de/
diff --git a/lisp/play/cookie1.el b/lisp/play/cookie1.el
index e5c0d6a14d2..c8e9d097a5f 100644
--- a/lisp/play/cookie1.el
+++ b/lisp/play/cookie1.el
@@ -1,6 +1,6 @@
 ;;; cookie1.el --- retrieve random phrases from fortune cookie files  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric S. Raymond <esr@thyrsus.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/play/decipher.el b/lisp/play/decipher.el
index 88300c1d818..56f166c10f1 100644
--- a/lisp/play/decipher.el
+++ b/lisp/play/decipher.el
@@ -1,6 +1,6 @@
 ;;; decipher.el --- cryptanalyze monoalphabetic substitution ciphers  -*- 
lexical-binding: t; -*-
 ;;
-;; Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1996, 2001-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Christopher J. Madsen <chris_madsen@geocities.com>
 ;; Keywords: games
@@ -481,7 +481,7 @@ The most useful commands are:
   "Checkpoint the current cipher alphabet.
 This records the current alphabet so you can return to it later.
 You may have any number of checkpoints.
-Type `\\[decipher-restore-checkpoint]' to restore a checkpoint."
+Type \\[decipher-restore-checkpoint] to restore a checkpoint."
   (interactive "sCheckpoint description: " decipher-mode)
   (or (stringp desc)
       (setq desc ""))
@@ -508,7 +508,7 @@ Type `\\[decipher-restore-checkpoint]' to restore a 
checkpoint."
 If point is not on a checkpoint line, moves to the first checkpoint line.
 If point is on a checkpoint, restores that checkpoint.
 
-Type `\\[decipher-make-checkpoint]' to make a checkpoint."
+Type \\[decipher-make-checkpoint] to make a checkpoint."
   (interactive nil decipher-mode)
   (beginning-of-line)
   (if (looking-at "%!\\([A-Z ]+\\)!")
@@ -524,7 +524,7 @@ Type `\\[decipher-make-checkpoint]' to make a checkpoint."
     ;; Move to the first checkpoint:
     (goto-char (point-min))
     (if (re-search-forward "^%![A-Z ]+!" nil t)
-        (message "Select the checkpoint to restore and type `%s'"
+        (message "Select the checkpoint to restore and type %s"
                  (substitute-command-keys "\\[decipher-restore-checkpoint]"))
       (error "No checkpoints in this buffer"))))
 
diff --git a/lisp/play/dissociate.el b/lisp/play/dissociate.el
index 0c655281192..f96418ef1bd 100644
--- a/lisp/play/dissociate.el
+++ b/lisp/play/dissociate.el
@@ -1,6 +1,6 @@
 ;;; dissociate.el --- scramble text amusingly for Emacs  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: games
diff --git a/lisp/play/doctor.el b/lisp/play/doctor.el
index 891274448d3..79ddc4fc929 100644
--- a/lisp/play/doctor.el
+++ b/lisp/play/doctor.el
@@ -1,6 +1,6 @@
 ;;; doctor.el --- psychological help for frustrated users  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: games
diff --git a/lisp/play/dunnet.el b/lisp/play/dunnet.el
index e290a9d73ec..8d9a7853242 100644
--- a/lisp/play/dunnet.el
+++ b/lisp/play/dunnet.el
@@ -1,6 +1,6 @@
 ;;; dunnet.el --- text adventure for Emacs -*- lexical-binding: t -*-
 
-;; Copyright (C) 1992-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Ron Schnell <ronnie@driver-aces.com>
 ;; Created: 25 Jul 1992
diff --git a/lisp/play/fortune.el b/lisp/play/fortune.el
index 36551321a56..de3caacdda5 100644
--- a/lisp/play/fortune.el
+++ b/lisp/play/fortune.el
@@ -1,6 +1,6 @@
 ;;; fortune.el --- use fortune to create signatures  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Holger Schauer <Holger.Schauer@gmx.de>
 ;; Keywords: games utils mail
diff --git a/lisp/play/gamegrid.el b/lisp/play/gamegrid.el
index bf195d6a0ec..a098d0f6f69 100644
--- a/lisp/play/gamegrid.el
+++ b/lisp/play/gamegrid.el
@@ -1,6 +1,6 @@
 ;;; gamegrid.el --- library for implementing grid-based games on Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Glynn Clements <glynn@sensei.co.uk>
 ;; Old-Version: 1.02
diff --git a/lisp/play/gametree.el b/lisp/play/gametree.el
index 971d8ea70ca..86b63adddc7 100644
--- a/lisp/play/gametree.el
+++ b/lisp/play/gametree.el
@@ -1,6 +1,6 @@
 ;;; gametree.el --- manage game analysis trees in Emacs  -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Ian T Zimmerman <itz@rahul.net>
 ;; Created: Wed Dec 10 07:41:46 PST 1997
diff --git a/lisp/play/gomoku.el b/lisp/play/gomoku.el
index 7d57b15673a..0ff745916e7 100644
--- a/lisp/play/gomoku.el
+++ b/lisp/play/gomoku.el
@@ -1,6 +1,6 @@
 ;;; gomoku.el --- Gomoku game between you and Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1988, 1994, 1996, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1988, 1994, 1996, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Philippe Schnoebelen <phs@lsv.ens-cachan.fr>
diff --git a/lisp/play/handwrite.el b/lisp/play/handwrite.el
index 735874e8da6..c71dffc42ed 100644
--- a/lisp/play/handwrite.el
+++ b/lisp/play/handwrite.el
@@ -1,11 +1,11 @@
 ;;; handwrite.el --- turns your emacs buffer into a handwritten document  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Danny Roozendaal (was: <danny@tvs.kun.nl>)
 ;; Maintainer: emacs-devel@gnu.org
 ;; Created: October 21 1996
-;; Keywords: wp, print, postscript, cursive writing
+;; Keywords: text, print, postscript, cursive writing
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/play/life.el b/lisp/play/life.el
index 2796a92d4dd..377cbf2a7bc 100644
--- a/lisp/play/life.el
+++ b/lisp/play/life.el
@@ -1,6 +1,6 @@
 ;;; life.el --- John Horton Conway's Game of Life  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1988, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Kyle Jones <kyleuunet.uu.net>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/play/morse.el b/lisp/play/morse.el
index 4b2f2cfb4a8..1f4d269cbb9 100644
--- a/lisp/play/morse.el
+++ b/lisp/play/morse.el
@@ -1,6 +1,6 @@
 ;;; morse.el --- convert text to morse code and back  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Rick Farnbach <rick_farnbach@MENTORG.COM>
 ;; Keywords: games
diff --git a/lisp/play/mpuz.el b/lisp/play/mpuz.el
index f9811f91172..03ce52cdb4c 100644
--- a/lisp/play/mpuz.el
+++ b/lisp/play/mpuz.el
@@ -1,6 +1,6 @@
 ;;; mpuz.el --- multiplication puzzle for GNU Emacs  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1990, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Philippe Schnoebelen <phs@lsv.ens-cachan.fr>
 ;; Overhauled: Daniel Pfeiffer <occitan@esperanto.org>
diff --git a/lisp/play/pong.el b/lisp/play/pong.el
index bb9611f0b48..15de02d468b 100644
--- a/lisp/play/pong.el
+++ b/lisp/play/pong.el
@@ -1,6 +1,6 @@
 ;;; pong.el --- classical implementation of pong  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Benjamin Drieu <bdrieu@april.org>
 ;; Keywords: games
diff --git a/lisp/play/snake.el b/lisp/play/snake.el
index 17a90817e72..e6dea3e31ae 100644
--- a/lisp/play/snake.el
+++ b/lisp/play/snake.el
@@ -1,6 +1,6 @@
 ;;; snake.el --- implementation of Snake for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Glynn Clements <glynn@sensei.co.uk>
 ;; Created: 1997-09-10
diff --git a/lisp/play/solitaire.el b/lisp/play/solitaire.el
index f5788593794..c4927ea3cd2 100644
--- a/lisp/play/solitaire.el
+++ b/lisp/play/solitaire.el
@@ -1,6 +1,6 @@
 ;;; solitaire.el --- game of solitaire in Emacs Lisp  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Jan Schormann <Jan.Schormann@rechen-gilde.de>
 ;; Created: Fri afternoon, Jun  3,  1994
diff --git a/lisp/play/spook.el b/lisp/play/spook.el
index 3fa8444b167..6dc89e3536b 100644
--- a/lisp/play/spook.el
+++ b/lisp/play/spook.el
@@ -1,6 +1,6 @@
 ;;; spook.el --- spook phrase utility for overloading the NSA line eater  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1988, 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: games
diff --git a/lisp/play/tetris.el b/lisp/play/tetris.el
index 41276f1dbca..f3c595f0fc3 100644
--- a/lisp/play/tetris.el
+++ b/lisp/play/tetris.el
@@ -1,6 +1,6 @@
 ;;; tetris.el --- implementation of Tetris for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Glynn Clements <glynn@sensei.co.uk>
 ;; Old-Version: 2.01
diff --git a/lisp/play/zone.el b/lisp/play/zone.el
index b8a83baa44b..67c890eec7e 100644
--- a/lisp/play/zone.el
+++ b/lisp/play/zone.el
@@ -1,6 +1,6 @@
 ;;; zone.el --- idle display hacks  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Victor Zandy <zandy@cs.wisc.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/plstore.el b/lisp/plstore.el
index 758f9fc7292..db977cb6308 100644
--- a/lisp/plstore.el
+++ b/lisp/plstore.el
@@ -1,6 +1,6 @@
 ;;; plstore.el --- secure plist store -*- lexical-binding: t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@gnu.org>
 ;; Keywords: PGP, GnuPG
diff --git a/lisp/printing.el b/lisp/printing.el
index cb43f7e40dc..d9bc97d48af 100644
--- a/lisp/printing.el
+++ b/lisp/printing.el
@@ -1,9 +1,9 @@
 ;;; printing.el --- printing utilities  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, print, PostScript
+;; Keywords: text, print, PostScript
 ;; Old-Version: 6.9.3
 ;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
 
diff --git a/lisp/proced.el b/lisp/proced.el
index 47de74b0ecb..3435f1ab8cd 100644
--- a/lisp/proced.el
+++ b/lisp/proced.el
@@ -1,6 +1,6 @@
 ;;; proced.el --- operate on system processes like dired  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Roland Winkler <winkler@gnu.org>
 ;; Keywords: Processes, Unix
diff --git a/lisp/profiler.el b/lisp/profiler.el
index 634cdaf09ea..80f84037a63 100644
--- a/lisp/profiler.el
+++ b/lisp/profiler.el
@@ -1,6 +1,6 @@
 ;;; profiler.el --- UI and helper functions for Emacs's native profiler -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Tomohiro Matsuyama <tomo@cx4a.org>
 ;; Keywords: lisp
diff --git a/lisp/progmodes/antlr-mode.el b/lisp/progmodes/antlr-mode.el
index a54df19425a..1364214329a 100644
--- a/lisp/progmodes/antlr-mode.el
+++ b/lisp/progmodes/antlr-mode.el
@@ -1,6 +1,6 @@
 ;;; antlr-mode.el --- major mode for ANTLR grammar files  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Christoph Wedler <Christoph.Wedler@sap.com>
 ;; Keywords: languages, ANTLR, code generator
diff --git a/lisp/progmodes/asm-mode.el b/lisp/progmodes/asm-mode.el
index 0f5af9803a5..d47c525c5f9 100644
--- a/lisp/progmodes/asm-mode.el
+++ b/lisp/progmodes/asm-mode.el
@@ -1,6 +1,6 @@
 ;;; asm-mode.el --- mode for editing assembler code  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1991, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric S. Raymond <esr@thyrsus.com>
 ;; Maintainer: emacs-devel@gnu.org
@@ -52,9 +52,13 @@
   :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
   :group 'languages)
 
+(defun asm--safe-comment-char-p (char)
+  (memq char '(?\; ?# ?@)))
+
 (defcustom asm-comment-char ?\;
   "The `comment-start' character assumed by Asm mode."
-  :type 'character)
+  :type 'character
+  :safe #'asm--safe-comment-char-p)
 
 (defvar asm-mode-syntax-table
   (let ((st (make-syntax-table)))
diff --git a/lisp/progmodes/autoconf.el b/lisp/progmodes/autoconf.el
index 61e764c2bdc..95de105a9c5 100644
--- a/lisp/progmodes/autoconf.el
+++ b/lisp/progmodes/autoconf.el
@@ -1,6 +1,6 @@
 ;;; autoconf.el --- mode for editing Autoconf configure.ac files  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: languages
diff --git a/lisp/progmodes/bat-mode.el b/lisp/progmodes/bat-mode.el
index 9eab9fd41a6..0687a0c9f32 100644
--- a/lisp/progmodes/bat-mode.el
+++ b/lisp/progmodes/bat-mode.el
@@ -1,6 +1,6 @@
 ;;; bat-mode.el --- Major mode for editing DOS/Windows scripts  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2003, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Arni Magnusson <arnima@hafro.is>
 ;; Keywords: languages
diff --git a/lisp/progmodes/bug-reference.el b/lisp/progmodes/bug-reference.el
index 0afed5276f5..29ff521253b 100644
--- a/lisp/progmodes/bug-reference.el
+++ b/lisp/progmodes/bug-reference.el
@@ -1,6 +1,6 @@
 ;;; bug-reference.el --- buttonize bug references  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Tom Tromey <tromey@redhat.com>
 ;; Created: 21 Mar 2007
diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el
index 3b0814970ad..0095d83e302 100644
--- a/lisp/progmodes/c-ts-common.el
+++ b/lisp/progmodes/c-ts-common.el
@@ -1,6 +1,6 @@
 ;;; c-ts-common.el --- Utilities for C like Languages  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Maintainer : 付禹安 (Yuan Fu) <casouri@gmail.com>
 ;; Package    : emacs
@@ -37,9 +37,8 @@
 ;;
 ;; 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
+;; - Set `c-ts-common-indent-offset', and
+;;   `c-ts-common-indent-type-regexp-alist', then use simple-indent
 ;;   offset `c-ts-common-statement-offset' in
 ;;   `treesit-simple-indent-rules'.
 
@@ -116,7 +115,7 @@ non-whitespace characters of the current line."
   "Regexp pattern that matches a comment in C-like languages.")
 
 (defun c-ts-common--fill-paragraph (&optional arg)
-  "Fillling function for `c-ts-common'.
+  "Filling function for `c-ts-common'.
 ARG is passed to `fill-paragraph'."
   (interactive "*P")
   (save-restriction
@@ -134,7 +133,7 @@ ARG is passed to `fill-paragraph'."
       t)))
 
 (defun c-ts-common--fill-block-comment (&optional arg)
-  "Fillling function for block comments.
+  "Filling function for block comments.
 ARG is passed to `fill-paragraph'.  Assume point is in a block
 comment."
   (let* ((node (treesit-node-at (point)))
@@ -331,7 +330,7 @@ If NODE is nil, return nil."
 Assumes the anchor is (point-min), i.e., the 0th column.
 
 This function basically counts the number of block nodes (i.e.,
-brackets) (defined by `c-ts-common-indent-block-type-regexp')
+brackets) (see `c-ts-common-indent-type-regexp-alist')
 between NODE and the root node (not counting NODE itself), and
 multiply that by `c-ts-common-indent-offset'.
 
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index 51f60f70131..e5835bdb62d 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; c-ts-mode.el --- tree-sitter support for C and C++  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author     : Theodor Thornhill <theo@thornhill.no>
 ;; Maintainer : Theodor Thornhill <theo@thornhill.no>
@@ -322,7 +322,8 @@ PARENT and BOL are like other anchor functions."
                                (treesit-node-parent prev-sibling) t)))
           ;; If the start of the previous sibling isn't at the
           ;; beginning of a line, something's probably not quite
-          ;; right, go a step further.
+          ;; right, go a step further. (E.g., comment after a
+          ;; statement.)
           (_ (goto-char (treesit-node-start prev-sibling))
              (if (looking-back (rx bol (* whitespace))
                                (line-beginning-position))
@@ -356,27 +357,40 @@ PARENT, BOL, ARGS are the same as other anchor functions."
   (apply (alist-get 'standalone-parent treesit-simple-indent-presets)
          parent (treesit-node-parent parent) bol args))
 
-(defun c-ts-mode--prev-line-match (regexp)
-  "An indentation matcher that matches if previous line matches REGEXP."
-  (lambda (_n _p bol &rest _)
-    (save-excursion
-      (goto-char bol)
-      (forward-line -1)
-      (back-to-indentation)
-      (looking-at-p regexp))))
+(defun c-ts-mode--else-heuristic (node parent bol &rest _)
+  "Heuristic matcher for when \"else\" is followed by a closing bracket.
+NODE, PARENT, and BOL are the same as in other matchers."
+  (and (null node)
+       (save-excursion
+         (forward-line -1)
+         (looking-at (rx (* whitespace) "else" (* whitespace) eol)))
+       (let ((next-node (treesit-node-first-child-for-pos parent bol)))
+         (equal (treesit-node-type next-node) "}"))))
+
+(defun c-ts-mode--first-sibling (node parent &rest _)
+  "Matches when NODE is the \"first sibling\".
+\"First sibling\" is defined as: the first child node of PARENT
+such that it's on its own line.  NODE is the node to match and
+PARENT is its parent."
+  (let ((prev-sibling (treesit-node-prev-sibling node t)))
+    (or (null prev-sibling)
+        (save-excursion
+          (goto-char (treesit-node-start prev-sibling))
+          (<= (line-beginning-position)
+              (treesit-node-start parent)
+              (line-end-position))))))
 
 (defun c-ts-mode--indent-styles (mode)
   "Indent rules supported by `c-ts-mode'.
 MODE is either `c' or `cpp'."
   (let ((common
          `((c-ts-mode--for-each-tail-body-matcher prev-line 
c-ts-mode-indent-offset)
-           ;; If the user types "if (...)" and hits RET, they expect
-           ;; point on the empty line to be indented; this rule
-           ;; does that.
-           ((and no-node
-                 (c-ts-mode--prev-line-match
-                  ,(rx (or "if" "else" "while" "do" "for"))))
-            prev-line c-ts-mode-indent-offset)
+           ;; If the user types "else" and hits RET, they expect point
+           ;; on the empty line to be indented; this rule does that.
+           ;; This heuristic is intentionally very specific because
+           ;; more general heuristic is very error-prone, see
+           ;; discussion in bug#67417.
+           (c-ts-mode--else-heuristic prev-line c-ts-mode-indent-offset)
 
            ((parent-is "translation_unit") column-0 0)
            ((query "(ERROR (ERROR)) @indent") column-0 0)
@@ -423,6 +437,8 @@ MODE is either `c' or `cpp'."
            ((parent-is "preproc") c-ts-mode--anchor-prev-sibling 0)
 
            ((parent-is "function_definition") parent-bol 0)
+           ((parent-is "pointer_declarator") parent-bol 0)
+           ((parent-is ,(rx bos "declaration" eos)) parent-bol 0)
            ((parent-is "conditional_expression") first-sibling 0)
            ((parent-is "assignment_expression") parent-bol 
c-ts-mode-indent-offset)
            ((parent-is "concatenated_string") first-sibling 0)
@@ -458,7 +474,11 @@ MODE is either `c' or `cpp'."
            ((parent-is "field_declaration_list") 
c-ts-mode--anchor-prev-sibling 0)
 
            ;; Statement in {} blocks.
-           ((or (match nil "compound_statement" nil 1 1)
+           ((or (and (parent-is "compound_statement")
+                     ;; If the previous sibling(s) are not on their
+                     ;; own line, indent as if this node is the first
+                     ;; sibling (Bug#67357)
+                     c-ts-mode--first-sibling)
                 (match null "compound_statement"))
             standalone-parent c-ts-mode-indent-offset)
            ((parent-is "compound_statement") c-ts-mode--anchor-prev-sibling 0)
@@ -471,6 +491,7 @@ MODE is either `c' or `cpp'."
            ((parent-is "if_statement") standalone-parent 
c-ts-mode-indent-offset)
            ((parent-is "else_clause") standalone-parent 
c-ts-mode-indent-offset)
            ((parent-is "for_statement") standalone-parent 
c-ts-mode-indent-offset)
+           ((match "while" "do_statement") parent-bol 0) ; (do_statement 
"while")
            ((parent-is "while_statement") standalone-parent 
c-ts-mode-indent-offset)
            ((parent-is "do_statement") standalone-parent 
c-ts-mode-indent-offset)
 
@@ -495,13 +516,13 @@ MODE is either `c' or `cpp'."
        ((node-is "labeled_statement") parent-bol c-ts-mode-indent-offset)
        ((parent-is "labeled_statement") parent-bol c-ts-mode-indent-offset)
        ((parent-is "compound_statement") parent-bol c-ts-mode-indent-offset)
-       ((parent-is "if_statement") parent-bol 0)
-       ((parent-is "else_clause") parent-bol 0)
-       ((parent-is "for_statement") parent-bol 0)
-       ((parent-is "while_statement") parent-bol 0)
-       ((parent-is "switch_statement") parent-bol 0)
-       ((parent-is "case_statement") parent-bol 0)
-       ((parent-is "do_statement") parent-bol 0)
+       ((match "compound_statement" "if_statement") standalone-parent 0)
+       ((match "compound_statement" "else_clause") standalone-parent 0)
+       ((match "compound_statement" "for_statement") standalone-parent 0)
+       ((match "compound_statement" "while_statement") standalone-parent 0)
+       ((match "compound_statement" "switch_statement") standalone-parent 0)
+       ((match "compound_statement" "case_statement") standalone-parent 0)
+       ((match "compound_statement" "do_statement") standalone-parent 0)
        ,@common))))
 
 (defun c-ts-mode--top-level-label-matcher (node parent &rest _)
@@ -1362,7 +1383,7 @@ recommended to enable `electric-pair-mode' with this 
mode."
                                                 c-ts-mode-indent-style)
       :help "Show the name of the C/C++ indentation style for current buffer"]
      ["Set Comment Style" c-ts-mode-toggle-comment-style
-      :help "Toglle C/C++ comment style between block and line comments"])
+      :help "Toggle C/C++ comment style between block and line comments"])
     "--"
     ("Toggle..."
      ["SubWord Mode" subword-mode
diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el
index 91a7665edbb..fbbb81b6f10 100644
--- a/lisp/progmodes/cc-align.el
+++ b/lisp/progmodes/cc-align.el
@@ -1,6 +1,6 @@
 ;;; cc-align.el --- custom indentation functions for CC Mode -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
 
 ;; Authors:    2004- Alan Mackenzie
 ;;             1998- Martin Stjernholm
diff --git a/lisp/progmodes/cc-awk.el b/lisp/progmodes/cc-awk.el
index 22f63bb5be7..e299f4fa8d2 100644
--- a/lisp/progmodes/cc-awk.el
+++ b/lisp/progmodes/cc-awk.el
@@ -1,6 +1,6 @@
 ;;; cc-awk.el --- AWK specific code within cc-mode. -*- lexical-binding: t -*-
 
-;; Copyright (C) 1988, 1994, 1996, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1988, 1994, 1996, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Alan Mackenzie <acm@muc.de> (originally based on awk-mode.el)
diff --git a/lisp/progmodes/cc-bytecomp.el b/lisp/progmodes/cc-bytecomp.el
index c3caffbe8d2..b6923e46339 100644
--- a/lisp/progmodes/cc-bytecomp.el
+++ b/lisp/progmodes/cc-bytecomp.el
@@ -1,6 +1,6 @@
 ;;; cc-bytecomp.el --- compile time setup for proper compilation -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author:     Martin Stjernholm
 ;; Maintainer: bug-cc-mode@gnu.org
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index 658892414bc..7cd6cb0dda0 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -1,6 +1,6 @@
 ;;; cc-cmds.el --- user level commands for CC Mode -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
 
 ;; Authors:    2003- Alan Mackenzie
 ;;             1998- Martin Stjernholm
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 6c1816f2879..bc0aae919e5 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -1,6 +1,6 @@
 ;;; cc-defs.el --- compile time definitions for CC Mode -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
 
 ;; Authors:    2003- Alan Mackenzie
 ;;             1998- Martin Stjernholm
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 018a194ac14..ea4ee3d7b7c 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -1,6 +1,6 @@
 ;;; cc-engine.el --- core syntax guessing engine for CC mode -*- 
lexical-binding:t; coding: utf-8 -*-
 
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
 
 ;; Authors:    2001- Alan Mackenzie
 ;;             1998- Martin Stjernholm
@@ -7554,7 +7554,7 @@ multi-line strings (but not C++, for example)."
 (defun c-ml-string-opener-intersects-region (&optional start finish)
   ;; If any part of the region [START FINISH] is inside an ml-string opener,
   ;; return a dotted list of the start, end and double-quote position of the
-  ;; first such opener.  That list wlll not include any "context characters"
+  ;; first such opener.  That list will not include any "context characters"
   ;; before or after the opener.  If an opener is found, the match-data will
   ;; indicate it, with (match-string 1) being the entire delimiter, and
   ;; (match-string 2) the "main" double-quote.  Otherwise, the match-data is
@@ -9891,7 +9891,7 @@ point unchanged and return nil."
   ;; Note that this function is incomplete, handling only those cases expected
   ;; to be common in a C++20 requires clause.
   ;;
-  ;; Note also that (...) is not recognised as a primary expression if the
+  ;; Note also that (...) is not recognized as a primary expression if the
   ;; next token is an open brace.
   (let ((here (point))
        (c-restricted-<>-arglists t)
@@ -11476,7 +11476,7 @@ This function might do hidden buffer changes."
                 ;; an arglist it would be a meaningless expression because
                 ;; the result isn't used.  We therefore choose to recognize
                 ;; it as a declaration when there's "symmetrical WS" around
-                ;; the "*" or the flag `c-assymetry-fontification-flag' is
+                ;; the "*" or the flag `c-asymmetry-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
@@ -13021,7 +13021,7 @@ comment at the start of cc-engine.el for more info."
 
 (defun c-laomib-get-cache (containing-sexp start)
   ;; Get an element from `c-laomib-cache' matching CONTAINING-SEXP, and which
-  ;; is suitable for start postiion START.
+  ;; is suitable for start position START.
   ;; Return that element or nil if one wasn't found.
   (let ((ptr c-laomib-cache)
        elt)
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index 6e5ee28c4ec..6419d6cf05a 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -1,6 +1,6 @@
 ;; cc-fonts.el --- font lock support for CC Mode -*- lexical-binding: t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Authors:    2003- Alan Mackenzie
 ;;             2002- Martin Stjernholm
@@ -1112,7 +1112,7 @@ casts and declarations are fontified.  Used on level 2 
and higher."
   ;; 'c-decl-type-start (according to TYPES).  Stop at LIMIT.
   ;;
   ;; If TYPES is t, fontify all identifiers as types; if it is a number, a
-  ;; buffer position, additionally set the `c-deftype' text property on the
+  ;; buffer position, additionally set the `c-typedef' text property on the
   ;; keyword at that position; if it is nil fontify as either variables or
   ;; functions, otherwise TYPES is a face to use.  If NOT-TOP is non-nil, we
   ;; are not at the top-level ("top-level" includes being directly inside a
diff --git a/lisp/progmodes/cc-guess.el b/lisp/progmodes/cc-guess.el
index 797e0a1939b..f7fe5feeca6 100644
--- a/lisp/progmodes/cc-guess.el
+++ b/lisp/progmodes/cc-guess.el
@@ -1,6 +1,6 @@
 ;;; cc-guess.el --- guess indentation values by scanning existing code -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985, 1987, 1992-2006, 2011-2023 Free Software
+;; Copyright (C) 1985, 1987, 1992-2006, 2011-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author:     1994-1995 Barry A. Warsaw
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 4b5fa1756d3..dc75bf741a6 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -1,6 +1,6 @@
 ;;; cc-langs.el --- language specific settings for CC Mode -*- 
lexical-binding: t; coding: utf-8 -*-
 
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
 
 ;; Authors:    2002- Alan Mackenzie
 ;;             1998- Martin Stjernholm
@@ -818,7 +818,7 @@ there be copies of the opener contained in the multi-line 
string."
 
 (c-lang-defconst c-cpp-or-ml-match-offset
   ;; The offset to be added onto match numbers for a multi-line string in
-  ;; matches for `c-cpp-or-ml-string-opener-re'.
+  ;; matches for `c-ml-string-cpp-or-opener-re'.
   t (if (c-lang-const c-anchored-cpp-prefix)
        (+ 2 (regexp-opt-depth (c-lang-const c-anchored-cpp-prefix)))
       2))
diff --git a/lisp/progmodes/cc-menus.el b/lisp/progmodes/cc-menus.el
index 8d9864c4f6d..25b3c89f73b 100644
--- a/lisp/progmodes/cc-menus.el
+++ b/lisp/progmodes/cc-menus.el
@@ -1,6 +1,6 @@
 ;;; cc-menus.el --- imenu support for CC Mode -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
 
 ;; Authors:    1998- Martin Stjernholm
 ;;             1992-1999 Barry A. Warsaw
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 227a6af2a6b..64a679eacc7 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1,6 +1,6 @@
 ;;; cc-mode.el --- major mode for editing C and similar languages -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
 
 ;; Authors:    2003- Alan Mackenzie
 ;;             1998- Martin Stjernholm
@@ -256,6 +256,9 @@ control).  See \"cc-mode.el\" for more info."
        (put 'c-initialize-cc-mode initprop c-initialization-ok))))
 
   ;; Set up text conversion, for Emacs >= 30.0
+  ;; This is needed here because CC-mode's implementation of
+  ;; electricity does not rely on `post-self-insert-hook' (which is
+  ;; already handled adequately by `analyze-text-conversion').
   (when (boundp 'post-text-conversion-hook)
     (add-hook 'post-text-conversion-hook #'c-post-text-conversion nil t))
 
@@ -1374,8 +1377,14 @@ Note that the style variables are always made local to 
the buffer."
                       (not (nth 3 s))
                       (c-get-char-property (1- (point)) 'c-fl-syn-tab))
                    (c-put-char-property pos 'syntax-table '(1))
-                   (c-put-char-properties (1+ pos) (c-point 'eol pos)
-                                          'syntax-table '(1)))
+                   ;; Remove syntax-table text properties from template
+                   ;; delimiters.
+                   (c-clear-char-property-with-value
+                    (1+ pos) (c-point 'eol pos)
+                    'syntax-table c-<-as-paren-syntax)
+                   (c-clear-char-property-with-value
+                    (1+ pos) (c-point 'eol pos)
+                    'syntax-table c->-as-paren-syntax))
                  (setq pos (point)))
              (setq pos (1+ pos)))))))))
 
diff --git a/lisp/progmodes/cc-styles.el b/lisp/progmodes/cc-styles.el
index e412a52cfb8..ff6371d9368 100644
--- a/lisp/progmodes/cc-styles.el
+++ b/lisp/progmodes/cc-styles.el
@@ -1,6 +1,6 @@
 ;;; cc-styles.el --- support for styles in CC Mode -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
 
 ;; Authors:    2004- Alan Mackenzie
 ;;             1998- Martin Stjernholm
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index c7b66f040cd..3845c2d55f0 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -1,6 +1,6 @@
 ;;; cc-vars.el --- user customization variables for CC Mode -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
 
 ;; Authors:    2002- Alan Mackenzie
 ;;             1998- Martin Stjernholm
diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el
index 639c1fe7947..2b40fac752f 100644
--- a/lisp/progmodes/cfengine.el
+++ b/lisp/progmodes/cfengine.el
@@ -1,6 +1,6 @@
 ;;; cfengine.el --- mode for editing Cfengine files  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Maintainer: Ted Zlatanov <tzz@lifelogs.com>
diff --git a/lisp/progmodes/cl-font-lock.el b/lisp/progmodes/cl-font-lock.el
index 5febf7ff15f..f6d4cde3fec 100644
--- a/lisp/progmodes/cl-font-lock.el
+++ b/lisp/progmodes/cl-font-lock.el
@@ -1,12 +1,12 @@
 ;;; cl-font-lock.el --- Pretty Common Lisp font locking -*- lexical-binding: 
t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Yue Daian <sheepduke@gmail.com>
 ;; Maintainer: Spenser Truex <web@spensertruex.com>
 ;; Created: 2019-06-16
 ;; Old-Version: 0.3.0
 ;; Package-Requires: ((emacs "24.5"))
-;; Keywords: lisp wp files convenience
+;; Keywords: lisp text files convenience
 ;; URL: https://github.com/cl-font-lock/cl-font-lock
 
 ;; This file is part of GNU Emacs
diff --git a/lisp/progmodes/cmacexp.el b/lisp/progmodes/cmacexp.el
index 110726fa362..062f2d0b4e2 100644
--- a/lisp/progmodes/cmacexp.el
+++ b/lisp/progmodes/cmacexp.el
@@ -1,6 +1,6 @@
 ;;; cmacexp.el --- expand C macros in a region  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: Francesco Potortì <pot@gnu.org>
 ;; Adapted-By: ESR
diff --git a/lisp/progmodes/cmake-ts-mode.el b/lisp/progmodes/cmake-ts-mode.el
index 8fcdcaddc7b..29c9e957d3c 100644
--- a/lisp/progmodes/cmake-ts-mode.el
+++ b/lisp/progmodes/cmake-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; cmake-ts-mode.el --- tree-sitter support for CMake  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author     : Randy Taylor <dev@rjt.dev>
 ;; Maintainer : Randy Taylor <dev@rjt.dev>
@@ -32,10 +32,8 @@
 
 (declare-function treesit-parser-create "treesit.c")
 (declare-function treesit-query-capture "treesit.c")
-(declare-function treesit-induce-sparse-tree "treesit.c")
-(declare-function treesit-node-child "treesit.c")
-(declare-function treesit-node-start "treesit.c")
 (declare-function treesit-node-type "treesit.c")
+(declare-function treesit-search-subtree "treesit.c")
 
 (defcustom cmake-ts-mode-indent-offset 2
   "Number of spaces for each indentation step in `cmake-ts-mode'."
@@ -195,37 +193,14 @@ Check if a node type is available, then return the right 
font lock rules."
    '((ERROR) @font-lock-warning-face))
   "Tree-sitter font-lock settings for `cmake-ts-mode'.")
 
-(defun cmake-ts-mode--imenu ()
-  "Return Imenu alist for the current buffer."
-  (let* ((node (treesit-buffer-root-node))
-         (func-tree (treesit-induce-sparse-tree
-                     node "function_def" nil 1000))
-         (func-index (cmake-ts-mode--imenu-1 func-tree)))
-    (append
-     (when func-index `(("Function" . ,func-index))))))
-
-(defun cmake-ts-mode--imenu-1 (node)
-  "Helper for `cmake-ts-mode--imenu'.
-Find string representation for NODE and set marker, then recurse
-the subtrees."
-  (let* ((ts-node (car node))
-         (children (cdr node))
-         (subtrees (mapcan #'cmake-ts-mode--imenu-1
-                           children))
-         (name (when ts-node
-                 (pcase (treesit-node-type ts-node)
-                   ("function_def"
-                    (treesit-node-text
-                     (treesit-node-child (treesit-node-child ts-node 0) 2) 
t)))))
-         (marker (when ts-node
-                   (set-marker (make-marker)
-                               (treesit-node-start ts-node)))))
-    (cond
-     ((or (null ts-node) (null name)) subtrees)
-     (subtrees
-      `((,name ,(cons name marker) ,@subtrees)))
-     (t
-      `((,name . ,marker))))))
+(defun cmake-ts-mode--function-name (node)
+  "Return the function name of NODE.
+Return nil if there is no name or if NODE is not a function node."
+  (pcase (treesit-node-type node)
+    ("function_command"
+     (treesit-node-text
+      (treesit-search-subtree node "^argument$" nil nil 2)
+      t))))
 
 ;;;###autoload
 (define-derived-mode cmake-ts-mode prog-mode "CMake"
@@ -242,7 +217,8 @@ the subtrees."
     (setq-local comment-start-skip (rx "#" (* (syntax whitespace))))
 
     ;; Imenu.
-    (setq-local imenu-create-index-function #'cmake-ts-mode--imenu)
+    (setq-local treesit-simple-imenu-settings
+                `(("Function" "\\`function_command\\'" nil 
cmake-ts-mode--function-name)))
     (setq-local which-func-functions nil)
 
     ;; Indent.
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index 9e441dbfcf7..11d400e145a 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -1,6 +1,6 @@
 ;;; compile.el --- run compiler as inferior of Emacs, parse error messages  
-*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1987, 1993-1999, 2001-2023 Free Software
+;; Copyright (C) 1985-1987, 1993-1999, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Authors: Roland McGrath <roland@gnu.org>,
@@ -362,6 +362,28 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
     (ruby-Test::Unit
      "^    [[ ]?\\([^ (].*\\):\\([1-9][0-9]*\\)\\(\\]\\)?:in " 1 2)
 
+    ;; Tested with Lua 5.1, 5.2, 5.3, 5.4, and LuaJIT 2.1.
+    (lua
+     ,(rx bol
+          (+? (not (in "\t\n")))
+          ": "
+          (group (+? (not (in "\t\n"))))
+          ":"
+          (group (+ (in "0-9")))
+          ": "
+          (+ nonl)
+          "\nstack traceback:\n\t")
+     1 2 nil 2 1)
+    (lua-stack
+     ,(rx bol "\t"
+          (| "[C]:"
+             (: (group (+? (not (in "\t\n"))))
+                ":"
+                (? (group (+ (in "0-9")))
+                   ":")))
+          " in ")
+     1 2 nil 0 1)
+
     (gmake
      ;; Set GNU make error messages as INFO level.
      ;; It starts with the name of the make program which is variable,
@@ -1789,7 +1811,7 @@ to a function that generates a unique name."
 ;; run compile with the default command line
 (defun recompile (&optional edit-command)
   "Re-compile the program including the current buffer.
-If this is run in a Compilation mode buffer, re-use the arguments from the
+If this is run in a Compilation mode buffer, reuse the arguments from the
 original use.  Otherwise, recompile using `compile-command'.
 If the optional argument `edit-command' is non-nil, the command can be edited."
   (interactive "P")
@@ -1868,6 +1890,12 @@ process from additional information inserted by Emacs."
 (defvar-local compilation--start-time nil
   "The time when the compilation started as returned by `float-time'.")
 
+(defun compilation--downcase-mode-name (mode)
+  "Downcase the name of major MODE, even if MODE is not a string.
+The function `downcase' will barf if passed the name of a `major-mode'
+which is not a string, but instead a symbol or a list."
+  (downcase (format-mode-line mode)))
+
 ;;;###autoload
 (defun compilation-start (command &optional mode name-function highlight-regexp
                                   continue)
@@ -2059,11 +2087,12 @@ Returns the compilation buffer created."
                        (get-buffer-process
                         (with-no-warnings
                           (comint-exec
-                           outbuf (downcase mode-name)
+                           outbuf (compilation--downcase-mode-name mode-name)
                            shell-file-name
                            nil `(,shell-command-switch ,command)))))
-                    (start-file-process-shell-command (downcase mode-name)
-                                                      outbuf command))))
+                    (start-file-process-shell-command
+                      (compilation--downcase-mode-name mode-name)
+                     outbuf command))))
               ;; Make the buffer's mode line show process state.
               (setq mode-line-process
                     '((:propertize ":%s" face compilation-mode-line-run)
@@ -2768,7 +2797,8 @@ Prefix arg N says how many files to move backwards (or 
forwards, if negative)."
   (let ((buffer (compilation-find-buffer)))
     (if (get-buffer-process buffer)
        (interrupt-process (get-buffer-process buffer))
-      (error "The %s process is not running" (downcase mode-name)))))
+      (error "The %s process is not running"
+             (compilation--downcase-mode-name mode-name)))))
 
 (defalias 'compile-mouse-goto-error 'compile-goto-error)
 
@@ -3122,7 +3152,16 @@ and overlay is highlighted between MK and END-MK."
       (cancel-timer next-error-highlight-timer))
   (remove-hook 'pre-command-hook
               #'compilation-goto-locus-delete-o))
-
+
+(defun compilation--expand-fn (directory filename)
+  "Expand FILENAME or resolve its true name.
+Unlike `expand-file-name', `file-truename' follows symlinks, which
+we try to avoid if possible."
+  (let* ((expandedname (expand-file-name filename directory)))
+    (if (file-exists-p expandedname)
+        expandedname
+      (file-truename (file-name-concat directory filename)))))
+
 (defun compilation-find-file-1 (marker filename directory &optional formats)
   (or formats (setq formats '("%s")))
   (let ((dirs compilation-search-path)
@@ -3143,8 +3182,8 @@ and overlay is highlighted between MK and END-MK."
             fmts formats)
       ;; For each directory, try each format string.
       (while (and fmts (null buffer))
-        (setq name (file-truename
-                    (file-name-concat thisdir (format (car fmts) filename)))
+        (setq name (compilation--expand-fn thisdir
+                                           (format (car fmts) filename))
               buffer (and (file-exists-p name)
                           (find-file-noselect name))
               fmts (cdr fmts)))
@@ -3166,8 +3205,8 @@ and overlay is highlighted between MK and END-MK."
         (setq thisdir (car dirs)
               fmts formats)
         (while (and fmts (null buffer))
-          (setq name (file-truename
-                      (file-name-concat thisdir (format (car fmts) filename)))
+          (setq name (compilation--expand-fn thisdir
+                                             (format (car fmts) filename))
                 buffer (and (file-exists-p name)
                             (find-file-noselect name))
                 fmts (cdr fmts)))
@@ -3227,8 +3266,7 @@ attempts to find a file whose name is produced by (format 
FMT FILENAME)."
               (ding) (sit-for 2))
              ((and (file-directory-p name)
                    (not (file-exists-p
-                         (setq name (file-truename
-                                     (file-name-concat name filename))))))
+                         (setq name (compilation--expand-fn name filename)))))
               (message "No `%s' in directory %s" filename origname)
               (ding) (sit-for 2))
              (t
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index ab624a08646..758a6e17f72 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -1,6 +1,6 @@
 ;;; cperl-mode.el --- Perl code editing commands for Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Author: Ilya Zakharevich <ilyaz@cpan.org>
 ;;     Bob Olson
@@ -104,7 +104,10 @@
   :version "20.3")
 
 (defgroup cperl-indentation-details nil
-  "Indentation."
+  "Indentation.
+The option `cperl-file-style' (which see) can be used to set
+several indentation options in one go, following popular
+indentation styles."
   :prefix "cperl-"
   :group 'cperl)
 
@@ -157,6 +160,29 @@ for constructs with multiline 
if/unless/while/until/for/foreach condition."
   :type 'boolean
   :group 'cperl-autoinsert-details)
 
+(defcustom cperl-file-style nil
+  "Indentation style to use in cperl-mode.
+Setting this option will override options as given in
+`cperl-style-alist' for the keyword provided here.  If nil, then
+the individual options as customized are used.
+\"PBP\" is the style recommended in the Book \"Perl Best
+Practices\" by Damian Conway.  \"CPerl\" is the traditional style
+of cperl-mode, and \"PerlStyle\" follows the Perl documentation
+in perlstyle.  The other styles have been developed for other
+programming languages, mostly C."
+  :type '(choice (const "PBP")
+                 (const "CPerl")
+                 (const "PerlStyle")
+                 (const "GNU")
+                 (const "C++")
+                 (const "K&R")
+                 (const "BSD")
+                 (const "Whitesmith")
+                 (const :tag "Default" nil))
+  :group 'cperl-indentation-details
+  :version "29.1")
+;;;###autoload(put 'cperl-file-style 'safe-local-variable 'stringp)
+
 (defcustom cperl-indent-level 2
   "Indentation of CPerl statements with respect to containing block."
   :type 'integer
@@ -537,20 +563,6 @@ This way enabling/disabling of menu items is more correct."
   :type 'boolean
   :group 'cperl-speed)
 
-(defcustom cperl-file-style nil
-  "Indentation style to use in cperl-mode."
-  :type '(choice (const "CPerl")
-                 (const "PBP")
-                 (const "PerlStyle")
-                 (const "GNU")
-                 (const "C++")
-                 (const "K&R")
-                 (const "BSD")
-                 (const "Whitesmith")
-                 (const :tag "Default" nil))
-  :version "29.1")
-;;;###autoload(put 'cperl-file-style 'safe-local-variable 'stringp)
-
 (defcustom cperl-fontify-trailer
   'perl-code
   "How to fontify text after an \"__END__\" or \"__DATA__\" token.
@@ -1121,7 +1133,7 @@ Unless KEEP, removes the old indentation."
      ["Fix whitespace on indent" cperl-toggle-construct-fix t]
      ["Auto-help on Perl constructs" cperl-toggle-autohelp t]
      ["Auto fill" auto-fill-mode t])
-    ("Indent styles..."
+    ("Default indent styles..."
      ["CPerl" (cperl-set-style "CPerl") t]
      ["PBP" (cperl-set-style  "PBP") t]
      ["PerlStyle" (cperl-set-style "PerlStyle") t]
@@ -1132,6 +1144,15 @@ Unless KEEP, removes the old indentation."
      ["Whitesmith" (cperl-set-style "Whitesmith") t]
      ["Memorize Current" (cperl-set-style "Current") t]
      ["Memorized" (cperl-set-style-back) cperl-old-style])
+    ("Indent styles for current buffer..."
+     ["CPerl" (cperl-set-style "CPerl") t]
+     ["PBP" (cperl-file-style  "PBP") t]
+     ["PerlStyle" (cperl-file-style "PerlStyle") t]
+     ["GNU" (cperl-file-style "GNU") t]
+     ["C++" (cperl-file-style "C++") t]
+     ["K&R" (cperl-file-style "K&R") t]
+     ["BSD" (cperl-file-style "BSD") t]
+     ["Whitesmith" (cperl-file-style "Whitesmith") t])
     ("Micro-docs"
      ["Tips" (describe-variable 'cperl-tips) t]
      ["Problems" (describe-variable 'cperl-problems) t]
@@ -1463,7 +1484,7 @@ function tests that property."
 
 (defun cperl-block-declaration-p ()
   "Test whether the following ?\\{ opens a declaration block.
-Returns the column where the declarating keyword is found, or nil
+Returns the column where the declaring keyword is found, or nil
 if this isn't a declaration block.  Declaration blocks are named
 subroutines, packages and the like.  They start with a keyword
 and a name, to be followed by various descriptive items which are
@@ -1696,19 +1717,18 @@ into
 
 \\{cperl-mode-map}
 
-Setting the variable `cperl-font-lock' to t switches on `font-lock-mode'
-\(even with older Emacsen), `cperl-electric-lbrace-space' to t switches
-on electric space between $ and {, `cperl-electric-parens-string' is
-the string that contains parentheses that should be electric in CPerl
-\(see also `cperl-electric-parens-mark' and `cperl-electric-parens'),
-setting `cperl-electric-keywords' enables electric expansion of
-control structures in CPerl.  `cperl-electric-linefeed' governs which
-one of two linefeed behavior is preferable.  You can enable all these
-options simultaneously (recommended mode of use) by setting
-`cperl-hairy' to t.  In this case you can switch separate options off
-by setting them to `null'.  Note that one may undo the extra
-whitespace inserted by semis and braces in `auto-newline'-mode by
-consequent \\[cperl-electric-backspace].
+Setting the variable `cperl-font-lock' to t switches on `font-lock-mode',
+`cperl-electric-lbrace-space' to t switches on electric space between $
+and {, `cperl-electric-parens-string' is the string that contains
+parentheses that should be electric in CPerl (see also
+`cperl-electric-parens-mark' and `cperl-electric-parens'), setting
+`cperl-electric-keywords' enables electric expansion of control
+structures in CPerl.  `cperl-electric-linefeed' governs which one of two
+linefeed behavior is preferable.  You can enable all these options
+simultaneously by setting `cperl-hairy' to t.  In this case you can
+switch separate options off by setting them to `null'.  Note that one may
+undo the extra whitespace inserted by semis and braces in
+`auto-newline'-mode by consequent \\[cperl-electric-backspace].
 
 Short one-liner-style help is available on \\[cperl-get-help],
 and one can run perldoc or man via menu.
@@ -1916,7 +1936,8 @@ or as help on variables `cperl-tips', `cperl-problems',
 
 (defun cperl--set-file-style ()
   (when cperl-file-style
-    (cperl-set-style cperl-file-style)))
+    (cperl-file-style cperl-file-style)))
+
 
 ;; Fix for perldb - make default reasonable
 (defun cperl-db ()
@@ -4206,7 +4227,7 @@ recursive calls in starting lines of here-documents."
                    (setq tmpend tb))
                (put-text-property b (point) 'syntax-type 'format))
               ;; quotelike operator or regexp: capture groups 10 or 11
-               ;; matches some false postives, to be eliminated here
+               ;; matches some false positives, to be eliminated here
               ((or (match-beginning 10) (match-beginning 11))
                (setq b1 (if (match-beginning 10) 10 11)
                      argument (buffer-substring
@@ -5877,7 +5898,7 @@ functions (which they are not).  Inherits from 
`default'.")
                                              (eval cperl--ws*-rx))
                                    ;; ... or the start of a "sloppy" signature
                                    (sequence (eval cperl--sloppy-signature-rx)
-                                             ;; arbtrarily continue "a few 
lines"
+                                             ;; arbitrarily continue "a few 
lines"
                                              (repeat 0 200 (not (in "{"))))
                                    ;; make sure we have a reasonably
                                    ;; short match for an incomplete sub
@@ -6488,6 +6509,10 @@ See examples in `cperl-style-examples'.")
 
 (defun cperl-set-style (style)
   "Set CPerl mode variables to use one of several different indentation styles.
+This command sets the default values for the variables.  It does
+not affect buffers visiting files where the style has been set as
+a file or directory variable.  To change the indentation style of
+a buffer, use the command `cperl-file-style' instead.
 The arguments are a string representing the desired style.
 The list of styles is in `cperl-style-alist', available styles
 are \"CPerl\", \"PBP\", \"PerlStyle\", \"GNU\", \"K&R\", \"BSD\", \"C++\"
@@ -6508,7 +6533,8 @@ side-effect of memorizing only.  Examples in 
`cperl-style-examples'."
   (let ((style (cdr (assoc style cperl-style-alist))) setting)
     (while style
       (setq setting (car style) style (cdr style))
-      (set (car setting) (cdr setting)))))
+      (set-default-toplevel-value (car setting) (cdr setting))))
+  (set-default-toplevel-value 'cperl-file-style style))
 
 (defun cperl-set-style-back ()
   "Restore a style memorized by `cperl-set-style'."
@@ -6518,7 +6544,20 @@ side-effect of memorizing only.  Examples in 
`cperl-style-examples'."
     (while cperl-old-style
       (setq setting (car cperl-old-style)
            cperl-old-style (cdr cperl-old-style))
-      (set (car setting) (cdr setting)))))
+      (set-default-toplevel-value (car setting) (cdr setting)))))
+
+(defun cperl-file-style (style)
+  "Set the indentation style for the current buffer to STYLE.
+The list of styles is in `cperl-style-alist', available styles
+are \"CPerl\", \"PBP\", \"PerlStyle\", \"GNU\", \"K&R\", \"BSD\", \"C++\"
+and \"Whitesmith\"."
+  (interactive
+   (list (completing-read "Enter style: " cperl-style-alist nil 'insist)))
+  (dolist (setting (cdr (assoc style cperl-style-alist)) style)
+    (let ((option (car setting))
+          (value (cdr setting)))
+      (set (make-local-variable option) value)))
+  (set (make-local-variable 'cperl-file-style) style))
 
 (declare-function Info-find-node "info"
                  (filename nodename &optional no-going-back strict-case
@@ -6573,14 +6612,13 @@ side-effect of memorizing only.  Examples in 
`cperl-style-examples'."
             read))))
 
   (let ((cmd-desc (concat "^" (regexp-quote command) "[^a-zA-Z_0-9]")) ; 
"tr///"
-       pos isvar height iniheight frheight buf win fr1 fr2 iniwin not-loner
+       pos isvar height iniheight frheight buf win iniwin not-loner
        max-height char-height buf-list)
     (if (string-match "^-[a-zA-Z]$" command)
        (setq cmd-desc "^-X[ \t\n]"))
     (setq isvar (string-match "^[$@%]" command)
          buf (cperl-info-buffer isvar)
-         iniwin (selected-window)
-         fr1 (window-frame iniwin))
+         iniwin (selected-window))
     (set-buffer buf)
     (goto-char (point-min))
     (or isvar
@@ -6601,11 +6639,7 @@ side-effect of memorizing only.  Examples in 
`cperl-style-examples'."
          (or (not win)
              (eq (window-buffer win) buf)
              (set-window-buffer win buf))
-         (and win (setq fr2 (window-frame win)))
-         (if (or (not fr2) (eq fr1 fr2))
-             (pop-to-buffer buf)
-           (special-display-popup-frame buf) ; Make it visible
-           (select-window win))
+         (pop-to-buffer buf)
          (goto-char pos)               ; Needed (?!).
          ;; Resize
          (setq iniheight (window-height)
@@ -8824,6 +8858,7 @@ Delay of auto-help controlled by `cperl-lazy-help-time'."
 ;;; Plug for wrong font-lock:
 
 (defun cperl-font-lock-unfontify-region-function (beg end)
+  (declare (obsolete nil "30.1"))
   (with-silent-modifications
     (remove-text-properties beg end '(face nil))))
 
diff --git a/lisp/progmodes/cpp.el b/lisp/progmodes/cpp.el
index ebc76c10fdb..827ad6d24ee 100644
--- a/lisp/progmodes/cpp.el
+++ b/lisp/progmodes/cpp.el
@@ -1,6 +1,6 @@
 ;;; cpp.el --- highlight or hide text according to cpp conditionals -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: c, faces, tools
diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el
index c550c9670c8..7bf57bcbe21 100644
--- a/lisp/progmodes/csharp-mode.el
+++ b/lisp/progmodes/csharp-mode.el
@@ -1,6 +1,6 @@
 ;;; csharp-mode.el --- Support for editing C#  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author     : Theodor Thornhill <theo@thornhill.no>
 ;;              Jostein Kjønigsen <jostein@kjonigsen.net>
diff --git a/lisp/progmodes/cwarn.el b/lisp/progmodes/cwarn.el
index cf0e6508011..0f4fca3664e 100644
--- a/lisp/progmodes/cwarn.el
+++ b/lisp/progmodes/cwarn.el
@@ -1,6 +1,6 @@
 ;;; cwarn.el --- highlight suspicious C and C++ constructions  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Anders Lindgren
 ;; Keywords: c, languages, faces
diff --git a/lisp/progmodes/dcl-mode.el b/lisp/progmodes/dcl-mode.el
index cf589762e8f..b8ca1f2d600 100644
--- a/lisp/progmodes/dcl-mode.el
+++ b/lisp/progmodes/dcl-mode.el
@@ -1,6 +1,6 @@
 ;;; dcl-mode.el --- major mode for editing DCL command files  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Odd Gripenstam <gripenstamol@decus.se>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/dockerfile-ts-mode.el 
b/lisp/progmodes/dockerfile-ts-mode.el
index 0305bea5182..f6587018513 100644
--- a/lisp/progmodes/dockerfile-ts-mode.el
+++ b/lisp/progmodes/dockerfile-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; dockerfile-ts-mode.el --- tree-sitter support for Dockerfiles  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author     : Randy Taylor <dev@rjt.dev>
 ;; Maintainer : Randy Taylor <dev@rjt.dev>
@@ -31,10 +31,8 @@
 (eval-when-compile (require 'rx))
 
 (declare-function treesit-parser-create "treesit.c")
-(declare-function treesit-induce-sparse-tree "treesit.c")
 (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-type "treesit.c")
 
 (defvar dockerfile-ts-mode--syntax-table
@@ -118,38 +116,15 @@ continuation to the previous entry."
    '((ERROR) @font-lock-warning-face))
   "Tree-sitter font-lock settings.")
 
-(defun dockerfile-ts-mode--imenu ()
-  "Return Imenu alist for the current buffer."
-  (let* ((node (treesit-buffer-root-node))
-         (stage-tree (treesit-induce-sparse-tree
-                      node "from_instruction"
-                      nil 1000))
-         (stage-index (dockerfile-ts-mode--imenu-1 stage-tree)))
-    (when stage-index `(("Stage" . ,stage-index)))))
-
-(defun dockerfile-ts-mode--imenu-1 (node)
-  "Helper for `dockerfile-ts-mode--imenu'.
-Find string representation for NODE and set marker, then recurse
-the subtrees."
-  (let* ((ts-node (car node))
-         (children (cdr node))
-         (subtrees (mapcan #'dockerfile-ts-mode--imenu-1
-                           children))
-         (name (when ts-node
-                 (pcase (treesit-node-type ts-node)
-                   ("from_instruction"
-                    (treesit-node-text
-                     (or (treesit-node-child-by-field-name ts-node "as")
-                         (treesit-node-child ts-node 1)) t)))))
-         (marker (when ts-node
-                   (set-marker (make-marker)
-                               (treesit-node-start ts-node)))))
-    (cond
-     ((or (null ts-node) (null name)) subtrees)
-     (subtrees
-      `((,name ,(cons name marker) ,@subtrees)))
-     (t
-      `((,name . ,marker))))))
+(defun dockerfile-ts-mode--stage-name (node)
+  "Return the stage name of NODE.
+Return nil if there is no name or if NODE is not a stage node."
+  (pcase (treesit-node-type node)
+    ("from_instruction"
+     (treesit-node-text
+      (or (treesit-node-child-by-field-name node "as")
+          (treesit-node-child node 1))
+      t))))
 
 ;;;###autoload
 (define-derived-mode dockerfile-ts-mode prog-mode "Dockerfile"
@@ -166,8 +141,8 @@ the subtrees."
     (setq-local comment-start-skip (rx "#" (* (syntax whitespace))))
 
     ;; Imenu.
-    (setq-local imenu-create-index-function
-                #'dockerfile-ts-mode--imenu)
+    (setq-local treesit-simple-imenu-settings
+                `(("Stage" "\\`from_instruction\\'" nil 
dockerfile-ts-mode--stage-name)))
     (setq-local which-func-functions nil)
 
     ;; Indent.
diff --git a/lisp/progmodes/ebnf-abn.el b/lisp/progmodes/ebnf-abn.el
index d05128b88ad..2037696bf2f 100644
--- a/lisp/progmodes/ebnf-abn.el
+++ b/lisp/progmodes/ebnf-abn.el
@@ -1,9 +1,9 @@
 ;;; ebnf-abn.el --- parser for ABNF (Augmented BNF)  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
 ;; Old-Version: 1.2
 ;; Package: ebnf2ps
 
diff --git a/lisp/progmodes/ebnf-bnf.el b/lisp/progmodes/ebnf-bnf.el
index d746efbe690..c1862843368 100644
--- a/lisp/progmodes/ebnf-bnf.el
+++ b/lisp/progmodes/ebnf-bnf.el
@@ -1,9 +1,9 @@
 ;;; ebnf-bnf.el --- parser for EBNF  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
 ;; Old-Version: 1.10
 ;; Package: ebnf2ps
 
diff --git a/lisp/progmodes/ebnf-dtd.el b/lisp/progmodes/ebnf-dtd.el
index 3a2add32d77..a9d1cc5e2b8 100644
--- a/lisp/progmodes/ebnf-dtd.el
+++ b/lisp/progmodes/ebnf-dtd.el
@@ -1,9 +1,9 @@
 ;;; ebnf-dtd.el --- parser for DTD (Data Type Description for XML)  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
 ;; Old-Version: 1.1
 ;; Package: ebnf2ps
 
diff --git a/lisp/progmodes/ebnf-ebx.el b/lisp/progmodes/ebnf-ebx.el
index 29a50005494..b88e68dc4a6 100644
--- a/lisp/progmodes/ebnf-ebx.el
+++ b/lisp/progmodes/ebnf-ebx.el
@@ -1,9 +1,9 @@
 ;;; ebnf-ebx.el --- parser for EBNF used to specify XML (EBNFX)  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
 ;; Old-Version: 1.2
 ;; Package: ebnf2ps
 
diff --git a/lisp/progmodes/ebnf-iso.el b/lisp/progmodes/ebnf-iso.el
index c4d11c97fff..e8d3e65976d 100644
--- a/lisp/progmodes/ebnf-iso.el
+++ b/lisp/progmodes/ebnf-iso.el
@@ -1,9 +1,9 @@
 ;;; ebnf-iso.el --- parser for ISO EBNF  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
 ;; Old-Version: 1.9
 ;; Package: ebnf2ps
 
diff --git a/lisp/progmodes/ebnf-otz.el b/lisp/progmodes/ebnf-otz.el
index 4155dc0d2cd..15141e762d4 100644
--- a/lisp/progmodes/ebnf-otz.el
+++ b/lisp/progmodes/ebnf-otz.el
@@ -1,9 +1,9 @@
 ;;; ebnf-otz.el --- syntactic chart OpTimiZer  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
 ;; Old-Version: 1.0
 ;; Package: ebnf2ps
 
diff --git a/lisp/progmodes/ebnf-yac.el b/lisp/progmodes/ebnf-yac.el
index aaec71daa73..0ef98bd2d14 100644
--- a/lisp/progmodes/ebnf-yac.el
+++ b/lisp/progmodes/ebnf-yac.el
@@ -1,9 +1,9 @@
 ;;; ebnf-yac.el --- parser for Yacc/Bison  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
 ;; Old-Version: 1.4
 ;; Package: ebnf2ps
 
diff --git a/lisp/progmodes/ebnf2ps.el b/lisp/progmodes/ebnf2ps.el
index 819f39cb4e5..c74a523808f 100644
--- a/lisp/progmodes/ebnf2ps.el
+++ b/lisp/progmodes/ebnf2ps.el
@@ -1,9 +1,9 @@
 ;;; ebnf2ps.el --- translate an EBNF to a syntactic chart on PostScript  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
 ;; Old-Version: 4.4
 ;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
 
diff --git a/lisp/progmodes/ebrowse.el b/lisp/progmodes/ebrowse.el
index 5ca2f09b141..37b3a5f190b 100644
--- a/lisp/progmodes/ebrowse.el
+++ b/lisp/progmodes/ebrowse.el
@@ -1,6 +1,6 @@
 ;;; ebrowse.el --- Emacs C++ class browser & tags facility  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: Gerd Moellmann <gerd@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index d410367f902..df8a287b4f2 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -1,13 +1,13 @@
 ;;; eglot.el --- The Emacs Client for LSP servers  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
-;; Version: 1.15
+;; Version: 1.17
 ;; Author: João Távora <joaotavora@gmail.com>
 ;; Maintainer: João Távora <joaotavora@gmail.com>
 ;; URL: https://github.com/joaotavora/eglot
 ;; Keywords: convenience, languages
-;; Package-Requires: ((emacs "26.3") (jsonrpc "1.0.16") (flymake "1.2.1") 
(project "0.9.8") (xref "1.6.2") (eldoc "1.14.0") (seq "2.23") 
(external-completion "0.1"))
+;; Package-Requires: ((emacs "26.3") (jsonrpc "1.0.24") (flymake "1.2.1") 
(project "0.9.8") (xref "1.6.2") (eldoc "1.14.0") (seq "2.23") 
(external-completion "0.1"))
 
 ;; This is a GNU ELPA :core package.  Avoid adding functionality
 ;; that is not available in the version of Emacs recorded above or any
@@ -116,13 +116,22 @@
 ;; having installed them, didn't correctly re-load them over the
 ;; built-in versions.
 (eval-and-compile
-  (load "project")
-  (load "eldoc")
-  (load "seq")
-  (load "flymake")
-  (load "xref")
-  (load "jsonrpc")
-  (load "external-completion"))
+  ;; For those packages that are preloaded, reload them if needed,
+  ;; since that's the best we can do anyway.
+  ;; FIXME: Maybe the ELPA packages for those preloaded packages should
+  ;; force-reload themselves eagerly when the package is activated!
+  (let ((reload (if (fboundp 'require-with-check) ;Emacs≥30
+                    #'require-with-check
+                  (lambda (feature &rest _)
+                    ;; Just blindly reload like we used to do before
+                    ;; `require-with-check'.
+                    (load (symbol-name feature) nil 'nomessage)))))
+
+    (funcall reload 'eldoc nil 'reload)
+    (funcall reload 'seq nil 'reload)
+    ;; For those packages which are not preloaded OTOH, signal an error if
+    ;; the loaded file is not the one that should have been loaded.
+    (mapc reload '(project flymake xref jsonrpc external-completion))))
 
 ;; forward-declare, but don't require (Emacs 28 doesn't seem to care)
 (defvar markdown-fontify-code-blocks-natively)
@@ -138,27 +147,29 @@
                         'eglot-managed-mode-hook "1.6")
 (define-obsolete-variable-alias 'eglot-confirm-server-initiated-edits
   'eglot-confirm-server-edits "1.16")
-(define-obsolete-function-alias 'eglot--uri-to-path 'eglot-uri-to-path "1.16")
-(define-obsolete-function-alias 'eglot--path-to-uri 'eglot-path-to-uri "1.16")
-(define-obsolete-function-alias 'eglot--range-region 'eglot-range-region 
"1.16")
-(define-obsolete-function-alias 'eglot--server-capable 'eglot-server-capable 
"1.16")
-(define-obsolete-function-alias 'eglot--server-capable-or-lose 
'eglot-server-capable-or-lose "1.16")
+(make-obsolete-variable 'eglot-events-buffer-size
+  'eglot-events-buffer-config "1.16")
+(define-obsolete-function-alias 'eglot--uri-to-path #'eglot-uri-to-path "1.16")
+(define-obsolete-function-alias 'eglot--path-to-uri #'eglot-path-to-uri "1.16")
+(define-obsolete-function-alias 'eglot--range-region #'eglot-range-region 
"1.16")
+(define-obsolete-function-alias 'eglot--server-capable #'eglot-server-capable 
"1.16")
+(define-obsolete-function-alias 'eglot--server-capable-or-lose 
#'eglot-server-capable-or-lose "1.16")
 (define-obsolete-function-alias
-  'eglot-lsp-abiding-column 'eglot-utf-16-linepos "1.12")
+  'eglot-lsp-abiding-column #'eglot-utf-16-linepos "1.12")
 (define-obsolete-function-alias
-  'eglot-current-column 'eglot-utf-32-linepos "1.12")
+  'eglot-current-column #'eglot-utf-32-linepos "1.12")
 (define-obsolete-variable-alias
   'eglot-current-column-function 'eglot-current-linepos-function "1.12")
 (define-obsolete-function-alias
-  'eglot-move-to-current-column 'eglot-move-to-utf-32-linepos "1.12")
+  'eglot-move-to-current-column #'eglot-move-to-utf-32-linepos "1.12")
 (define-obsolete-function-alias
-  'eglot-move-to-lsp-abiding-column 'eglot-move-to-utf-16-linepos "1.12")
+  'eglot-move-to-lsp-abiding-column #'eglot-move-to-utf-16-linepos "1.12")
 (define-obsolete-variable-alias
-'eglot-move-to-column-function 'eglot-move-to-linepos-function "1.12")
+  'eglot-move-to-column-function 'eglot-move-to-linepos-function "1.12")
 (define-obsolete-variable-alias 'eglot-ignored-server-capabilites
   'eglot-ignored-server-capabilities "1.8")
 ;;;###autoload
-(define-obsolete-function-alias 'eglot-update 'eglot-upgrade-eglot "29.1")
+(define-obsolete-function-alias 'eglot-update #'eglot-upgrade-eglot "29.1")
 
 
 ;;; User tweakable stuff
@@ -171,11 +182,12 @@
   "Compute server-choosing function for `eglot-server-programs'.
 Each element of ALTERNATIVES is a string PROGRAM or a list of
 strings (PROGRAM ARGS...) where program names an LSP server
-program to start with ARGS.  Returns a function of one argument.
-When invoked, that function will return a list (ABSPATH ARGS),
-where ABSPATH is the absolute path of the PROGRAM that was
-chosen (interactively or automatically)."
-  (lambda (&optional interactive)
+program to start with ARGS.  Returns a function to be invoked
+automatically by Eglot on startup.  When invoked, that function
+will return a list (ABSPATH ARGS), where ABSPATH is the absolute
+path of the PROGRAM that was chosen (interactively or
+automatically)."
+  (lambda (&optional interactive _project)
     ;; JT@2021-06-13: This function is way more complicated than it
     ;; could be because it accounts for the fact that
     ;; `eglot--executable-find' may take much longer to execute on
@@ -185,7 +197,10 @@ chosen (interactively or automatically)."
            (err (lambda ()
                   (error "None of '%s' are valid executables"
                          (mapconcat #'car listified ", ")))))
-      (cond (interactive
+      (cond ((and interactive current-prefix-arg)
+             ;; A C-u always lets user input something manually,
+             nil)
+            (interactive
              (let* ((augmented (mapcar (lambda (a)
                                          (let ((found (eglot--executable-find
                                                        (car a) t)))
@@ -216,7 +231,7 @@ chosen (interactively or automatically)."
                                 (vimrc-mode . ("vim-language-server" 
"--stdio"))
                                 ((python-mode python-ts-mode)
                                  . ,(eglot-alternatives
-                                     '("pylsp" "pyls" ("pyright-langserver" 
"--stdio") "jedi-language-server")))
+                                     '("pylsp" "pyls" ("pyright-langserver" 
"--stdio") "jedi-language-server" "ruff-lsp")))
                                 ((js-json-mode json-mode json-ts-mode)
                                  . ,(eglot-alternatives 
'(("vscode-json-language-server" "--stdio")
                                                           
("vscode-json-languageserver" "--stdio")
@@ -228,7 +243,7 @@ chosen (interactively or automatically)."
                                   (typescript-mode :language-id "typescript"))
                                  . ("typescript-language-server" "--stdio"))
                                 ((bash-ts-mode sh-mode) . 
("bash-language-server" "start"))
-                                ((php-mode phps-mode)
+                                ((php-mode phps-mode php-ts-mode)
                                  . ,(eglot-alternatives
                                      '(("phpactor" "language-server")
                                        ("php" 
"vendor/felixfbecker/language-server/bin/php-language-server.php"))))
@@ -244,7 +259,7 @@ chosen (interactively or automatically)."
                                  . ("haskell-language-server-wrapper" "--lsp"))
                                 (elm-mode . ("elm-language-server"))
                                 (mint-mode . ("mint" "ls"))
-                                (kotlin-mode . ("kotlin-language-server"))
+                                ((kotlin-mode kotlin-ts-mode) . 
("kotlin-language-server"))
                                 ((go-mode go-dot-mod-mode go-dot-work-mode 
go-ts-mode go-mod-ts-mode)
                                  . ("gopls"))
                                 ((R-mode ess-r-mode) . ("R" "--slave" "-e"
@@ -269,6 +284,7 @@ chosen (interactively or automatically)."
                                 ((yaml-ts-mode yaml-mode) . 
("yaml-language-server" "--stdio"))
                                 (nix-mode . ,(eglot-alternatives '("nil" 
"rnix-lsp" "nixd")))
                                 (nickel-mode . ("nls"))
+                                ((nushell-mode nushell-ts-mode) . ("nu" 
"--lsp"))
                                 (gdscript-mode . ("localhost" 6008))
                                 ((fortran-mode f90-mode) . ("fortls"))
                                 (futhark-mode . ("futhark" "lsp"))
@@ -293,7 +309,8 @@ chosen (interactively or automatically)."
                                      '(("marksman" "server")
                                        ("vscode-markdown-language-server" 
"--stdio"))))
                                 (graphviz-dot-mode . ("dot-language-server" 
"--stdio"))
-                                (terraform-mode . ("terraform-ls" "serve")))
+                                (terraform-mode . ("terraform-ls" "serve"))
+                                ((uiua-ts-mode uiua-mode) . ("uiua" "lsp")))
   "How the command `eglot' guesses the server to start.
 An association list of (MAJOR-MODE . CONTACT) pairs.  MAJOR-MODE
 identifies the buffers that are to be managed by a specific
@@ -349,16 +366,16 @@ CONTACT can be:
   which you should see for the semantics of the mandatory
   :PROCESS argument.
 
-* A function of a single argument producing any of the above
-  values for CONTACT.  The argument's value is non-nil if the
-  connection was requested interactively (e.g. from the `eglot'
-  command), and nil if it wasn't (e.g. from `eglot-ensure').  If
-  the call is interactive, the function can ask the user for
-  hints on finding the required programs, etc.  Otherwise, it
-  should not ask the user for any input, and return nil or signal
-  an error if it can't produce a valid CONTACT.  The helper
-  function `eglot-alternatives' (which see) can be used to
-  produce a function that offers more than one server for a given
+* A function of two arguments (INTERACTIVE PROJECT) producing any
+  of the above values for CONTACT.  INTERACTIVE will be t if an
+  interactive `M-x eglot' was used, and nil otherwise (e.g. from
+  `eglot-ensure').  Interactive calls may ask the user for hints
+  on finding the required programs, etc.  PROJECT is whatever
+  project Eglot discovered via `project-find-functions' (which
+  see).  The function should return nil or signal an error if it
+  can't produce a valid CONTACT.  The helper function
+  `eglot-alternatives' (which see) can be used to produce a
+  function that offers more than one server for a given
   MAJOR-MODE.")
 
 (defface eglot-highlight-symbol-face
@@ -412,17 +429,29 @@ as 0, i.e. don't block at all."
   "Don't tell server of changes before Emacs's been idle for this many 
seconds."
   :type 'number)
 
-(defcustom eglot-events-buffer-size 2000000
-  "Control the size of the Eglot events buffer.
-If a number, don't let the buffer grow larger than that many
-characters.  If 0, don't use an event's buffer at all.  If nil,
-let the buffer grow forever.
-
-For changes on this variable to take effect on a connection
-already started, you need to restart the connection.  That can be
-done by `eglot-reconnect'."
-  :type '(choice (const :tag "No limit" nil)
-                 (integer :tag "Number of characters")))
+(defcustom eglot-events-buffer-config
+  (list :size (or (bound-and-true-p eglot-events-buffer-size) 2000000)
+        :format 'full)
+  "Configure the Eglot events buffer.
+
+Value is a plist accepting the keys `:size', which controls the
+size in characters of the buffer (0 disables, nil means
+infinite), and `:format', which controls the shape of each log
+entry (`full' includes the original JSON, `lisp' uses
+pretty-printed Lisp).
+
+For changes on this variable to take effect, you need to restart
+the LSP connection.  That can be done by `eglot-reconnect'."
+  :type '(plist :key-type (symbol :tag "Keyword")
+                :options (((const :tag "Size" :size)
+                           (choice
+                            (const :tag "No limit" nil)
+                            (integer :tag "Number of characters")))
+                          ((const :tag "Format" :format)
+                           (choice
+                            (const :tag "Full with original JSON" full)
+                            (const :tag "Shortened" short)
+                            (const :tag "Pretty-printed lisp" lisp))))))
 
 (defcustom eglot-confirm-server-edits '((eglot-rename . nil)
                                         (t . maybe-summary))
@@ -547,7 +576,7 @@ It is nil if Eglot is not byte-complied.")
 
 (defvaralias 'eglot-{} 'eglot--{})
 
-(defconst eglot--{} (make-hash-table :size 1) "The empty JSON object.")
+(defconst eglot--{} (make-hash-table :size 0) "The empty JSON object.")
 
 (defun eglot--executable-find (command &optional remote)
   "Like Emacs 27's `executable-find', ignore REMOTE on Emacs 26."
@@ -993,6 +1022,7 @@ ACTION is an LSP object of either `CodeAction' or 
`Command' type."
     :documentation "Flag set when server is shutting down."
     :accessor eglot--shutdown-requested)
    (project
+    :initform nil
     :documentation "Project associated with server."
     :accessor eglot--project)
    (progress-reporters
@@ -1011,10 +1041,7 @@ ACTION is an LSP object of either `CodeAction' or 
`Command' type."
     :accessor eglot--managed-buffers)
    (saved-initargs
     :documentation "Saved initargs for reconnection purposes."
-    :accessor eglot--saved-initargs)
-   (inferior-process
-    :documentation "Server subprocess started automatically."
-    :accessor eglot--inferior-process))
+    :accessor eglot--saved-initargs))
   :documentation
   "Represents a server. Wraps a process for LSP communication.")
 
@@ -1151,9 +1178,6 @@ PRESERVE-BUFFERS as in `eglot-shutdown', which see."
   (maphash (lambda (_dir watch-and-ids)
              (file-notify-rm-watch (car watch-and-ids)))
            (eglot--file-watches server))
-  ;; Kill any autostarted inferior processes
-  (when-let (proc (eglot--inferior-process server))
-    (delete-process proc))
   ;; Sever the project/server relationship for `server'
   (setf (gethash (eglot--project server) eglot--servers-by-project)
         (delq server
@@ -1222,7 +1246,8 @@ CONTACT-PROXY is the value of the corresponding
 Return (MANAGED-MODES PROJECT CLASS CONTACT LANG-IDS).  If INTERACTIVE is
 non-nil, maybe prompt user, else error as soon as something can't
 be guessed."
-  (let* ((guessed-mode (if buffer-file-name major-mode))
+  (let* ((project (eglot--current-project))
+         (guessed-mode (if buffer-file-name major-mode))
          (guessed-mode-name (and guessed-mode (symbol-name guessed-mode)))
          (main-mode
           (cond
@@ -1242,7 +1267,9 @@ be guessed."
          (language-ids (mapcar #'cdr (car languages-and-contact)))
          (guess (cdr languages-and-contact))
          (guess (if (functionp guess)
-                    (funcall guess interactive)
+                    (pcase (cdr (func-arity guess))
+                      (1 (funcall guess interactive))
+                      (_ (funcall guess interactive project)))
                   guess))
          (class (or (and (consp guess) (symbolp (car guess))
                          (prog1 (unless current-prefix-arg (car guess))
@@ -1278,21 +1305,25 @@ be guessed."
                                   "\n" base-prompt)
                         (eglot--error
                          (concat "`%s' not found in PATH, but can't form"
-                                 " an interactive prompt for to fix %s!")
+                                 " an interactive prompt for help you fix"
+                                 " this.")
                          program guess))))))
+         (input (and prompt (read-shell-command prompt
+                                                full-program-invocation
+                                                'eglot-command-history)))
          (contact
-          (or (and prompt
-                   (split-string-and-unquote
-                    (read-shell-command
-                     prompt
-                     full-program-invocation
-                     'eglot-command-history)))
-              guess)))
-    (list managed-modes (eglot--current-project) class contact language-ids)))
-
-(defvar eglot-lsp-context)
-(put 'eglot-lsp-context 'variable-documentation
-     "Dynamically non-nil when searching for projects in LSP context.")
+          (if input
+              (if (string-match
+                   "^[\s\t]*\\(.*\\):\\([[:digit:]]+\\)[\s\t]*$" input)
+                  ;; <host>:<port> special case (bug#67682)
+                  (list (match-string 1 input)
+                        (string-to-number (match-string 2 input)))
+                (split-string-and-unquote input))
+            guess)))
+    (list managed-modes project class contact language-ids)))
+
+(defvar eglot-lsp-context nil
+  "Dynamically non-nil when searching for projects in LSP context.")
 
 (defun eglot--current-project ()
   "Return a project object for Eglot's LSP purposes.
@@ -1305,6 +1336,9 @@ suitable root directory for a given LSP server's 
purposes."
     (or (project-current)
         `(transient . ,(expand-file-name default-directory)))))
 
+(cl-defmethod project-root ((project (head eglot--project)))
+  (cadr project))
+
 ;;;###autoload
 (defun eglot (managed-major-modes project class contact language-ids
                                  &optional _interactive)
@@ -1460,7 +1494,6 @@ This docstring appeases checkdoc, that's all."
   (let* ((default-directory (project-root project))
          (nickname (project-name project))
          (readable-name (format "EGLOT (%s/%s)" nickname managed-modes))
-         autostart-inferior-process
          server-info
          (contact (if (functionp contact) (funcall contact) contact))
          (initargs
@@ -1473,16 +1506,16 @@ This docstring appeases checkdoc, that's all."
                                       readable-name nil
                                       (car contact) (cadr contact)
                                       (cddr contact)))))
-                ((and (stringp (car contact)) (memq :autoport contact))
+                ((and (stringp (car contact))
+                      (cl-find-if (lambda (x)
+                                    (or (eq x :autoport)
+                                        (eq (car-safe x) :autoport)))
+                                  contact))
                  (setq server-info (list "<inferior process>"))
-                 `(:process ,(lambda ()
-                               (pcase-let ((`(,connection . ,inferior)
-                                            (eglot--inferior-bootstrap
+                 `(:process ,(jsonrpc-autoport-bootstrap
                                              readable-name
                                              contact
-                                             '(:noquery t))))
-                                 (setq autostart-inferior-process inferior)
-                                 connection))))
+                                             :connect-args '(:noquery t))))
                 ((stringp (car contact))
                  (let* ((probe (cl-position-if #'keywordp contact))
                         (more-initargs (and probe (cl-subseq contact probe)))
@@ -1515,7 +1548,7 @@ This docstring appeases checkdoc, that's all."
           (apply
            #'make-instance class
            :name readable-name
-           :events-buffer-scrollback-size eglot-events-buffer-size
+           :events-buffer-config eglot-events-buffer-config
            :notification-dispatcher (funcall spread 
#'eglot-handle-notification)
            :request-dispatcher (funcall spread #'eglot-handle-request)
            :on-shutdown #'eglot--on-shutdown
@@ -1531,7 +1564,6 @@ This docstring appeases checkdoc, that's all."
     (setf (eglot--languages server)
           (cl-loop for m in managed-modes for l in language-ids
                    collect (cons m l)))
-    (setf (eglot--inferior-process server) autostart-inferior-process)
     (run-hook-with-args 'eglot-server-initialized-hook server)
     ;; Now start the handshake.  To honor `eglot-sync-connect'
     ;; maybe-sync-maybe-async semantics we use `jsonrpc-async-request'
@@ -1624,55 +1656,6 @@ in project `%s'."
           (quit (jsonrpc-shutdown server) (setq canceled 'quit)))
       (setq tag nil))))
 
-(defun eglot--inferior-bootstrap (name contact &optional connect-args)
-  "Use CONTACT to start a server, then connect to it.
-Return a cons of two process objects (CONNECTION . INFERIOR).
-Name both based on NAME.
-CONNECT-ARGS are passed as additional arguments to
-`open-network-stream'."
-  (let* ((port-probe (make-network-process :name "eglot-port-probe-dummy"
-                                           :server t
-                                           :host "localhost"
-                                           :service 0))
-         (port-number (unwind-protect
-                          (process-contact port-probe :service)
-                        (delete-process port-probe)))
-         inferior connection)
-    (unwind-protect
-        (progn
-          (setq inferior
-                (make-process
-                 :name (format "autostart-inferior-%s" name)
-                 :stderr (format "*%s stderr*" name)
-                 :noquery t
-                 :command (cl-subst
-                           (format "%s" port-number) :autoport contact)))
-          (setq connection
-                (cl-loop
-                 repeat 10 for i from 1
-                 do (accept-process-output nil 0.5)
-                 while (process-live-p inferior)
-                 do (eglot--message
-                     "Trying to connect to localhost and port %s (attempt %s)"
-                     port-number i)
-                 thereis (ignore-errors
-                           (apply #'open-network-stream
-                                  (format "autoconnect-%s" name)
-                                  nil
-                                  "localhost" port-number connect-args))))
-          (cons connection inferior))
-      (cond ((and (process-live-p connection)
-                  (process-live-p inferior))
-             (eglot--message "Done, connected to %s!" port-number))
-            (t
-             (when inferior (delete-process inferior))
-             (when connection (delete-process connection))
-             (eglot--error "Could not start and connect to server%s"
-                           (if inferior
-                               (format " started with %s"
-                                       (process-command inferior))
-                             "!")))))))
-
 
 ;;; Helpers (move these to API?)
 ;;;
@@ -1815,6 +1798,12 @@ If optional MARKER, return a marker instead"
 
 
 ;;; More helpers
+(defconst eglot--uri-path-allowed-chars
+  (let ((vec (copy-sequence url-path-allowed-chars)))
+    (aset vec ?: nil) ;; see github#639
+    vec)
+  "Like `url-path-allowed-chars' but more restrictive.")
+
 (defun eglot--snippet-expansion-fn ()
   "Compute a function to expand snippets.
 Doubles as an indicator of snippet support."
@@ -1953,23 +1942,23 @@ Use `eglot-managed-p' to determine if current buffer is 
managed.")
       ("utf-8"
        (eglot--setq-saving eglot-current-linepos-function 
#'eglot-utf-8-linepos)
        (eglot--setq-saving eglot-move-to-linepos-function 
#'eglot-move-to-utf-8-linepos)))
-    (add-hook 'after-change-functions 'eglot--after-change nil t)
-    (add-hook 'before-change-functions 'eglot--before-change nil t)
+    (add-hook 'after-change-functions #'eglot--after-change nil t)
+    (add-hook 'before-change-functions #'eglot--before-change nil t)
     (add-hook 'kill-buffer-hook #'eglot--managed-mode-off nil t)
     ;; Prepend "didClose" to the hook after the "nonoff", so it will run first
-    (add-hook 'kill-buffer-hook 'eglot--signal-textDocument/didClose nil t)
-    (add-hook 'before-revert-hook 'eglot--signal-textDocument/didClose nil t)
-    (add-hook 'after-revert-hook 'eglot--after-revert-hook nil t)
-    (add-hook 'before-save-hook 'eglot--signal-textDocument/willSave nil t)
-    (add-hook 'after-save-hook 'eglot--signal-textDocument/didSave nil t)
+    (add-hook 'kill-buffer-hook #'eglot--signal-textDocument/didClose nil t)
+    (add-hook 'before-revert-hook #'eglot--signal-textDocument/didClose nil t)
+    (add-hook 'after-revert-hook #'eglot--after-revert-hook nil t)
+    (add-hook 'before-save-hook #'eglot--signal-textDocument/willSave nil t)
+    (add-hook 'after-save-hook #'eglot--signal-textDocument/didSave nil t)
     (unless (eglot--stay-out-of-p 'xref)
-      (add-hook 'xref-backend-functions 'eglot-xref-backend nil t))
+      (add-hook 'xref-backend-functions #'eglot-xref-backend nil t))
     (add-hook 'completion-at-point-functions #'eglot-completion-at-point nil t)
     (add-hook 'completion-in-region-mode-hook #'eglot--capf-session-flush nil 
t)
     (add-hook 'company-after-completion-hook #'eglot--capf-session-flush nil t)
     (add-hook 'change-major-mode-hook #'eglot--managed-mode-off nil t)
-    (add-hook 'post-self-insert-hook 'eglot--post-self-insert-hook nil t)
-    (add-hook 'pre-command-hook 'eglot--pre-command-hook nil t)
+    (add-hook 'post-self-insert-hook #'eglot--post-self-insert-hook nil t)
+    (add-hook 'pre-command-hook #'eglot--pre-command-hook nil t)
     (eglot--setq-saving xref-prompt-for-identifier nil)
     (eglot--setq-saving flymake-diagnostic-functions '(eglot-flymake-backend))
     (eglot--setq-saving company-backends '(company-capf))
@@ -1988,21 +1977,21 @@ Use `eglot-managed-p' to determine if current buffer is 
managed.")
       (eldoc-mode 1))
     (cl-pushnew (current-buffer) (eglot--managed-buffers 
(eglot-current-server))))
    (t
-    (remove-hook 'after-change-functions 'eglot--after-change t)
-    (remove-hook 'before-change-functions 'eglot--before-change t)
+    (remove-hook 'after-change-functions #'eglot--after-change t)
+    (remove-hook 'before-change-functions #'eglot--before-change t)
     (remove-hook 'kill-buffer-hook #'eglot--managed-mode-off t)
-    (remove-hook 'kill-buffer-hook 'eglot--signal-textDocument/didClose t)
-    (remove-hook 'before-revert-hook 'eglot--signal-textDocument/didClose t)
-    (remove-hook 'after-revert-hook 'eglot--after-revert-hook t)
-    (remove-hook 'before-save-hook 'eglot--signal-textDocument/willSave t)
-    (remove-hook 'after-save-hook 'eglot--signal-textDocument/didSave t)
-    (remove-hook 'xref-backend-functions 'eglot-xref-backend t)
+    (remove-hook 'kill-buffer-hook #'eglot--signal-textDocument/didClose t)
+    (remove-hook 'before-revert-hook #'eglot--signal-textDocument/didClose t)
+    (remove-hook 'after-revert-hook #'eglot--after-revert-hook t)
+    (remove-hook 'before-save-hook #'eglot--signal-textDocument/willSave t)
+    (remove-hook 'after-save-hook #'eglot--signal-textDocument/didSave t)
+    (remove-hook 'xref-backend-functions #'eglot-xref-backend t)
     (remove-hook 'completion-at-point-functions #'eglot-completion-at-point t)
     (remove-hook 'completion-in-region-mode-hook #'eglot--capf-session-flush t)
     (remove-hook 'company-after-completion-hook #'eglot--capf-session-flush t)
     (remove-hook 'change-major-mode-hook #'eglot--managed-mode-off t)
-    (remove-hook 'post-self-insert-hook 'eglot--post-self-insert-hook t)
-    (remove-hook 'pre-command-hook 'eglot--pre-command-hook t)
+    (remove-hook 'post-self-insert-hook #'eglot--post-self-insert-hook t)
+    (remove-hook 'pre-command-hook #'eglot--pre-command-hook t)
     (remove-hook 'eldoc-documentation-functions #'eglot-hover-eldoc-function t)
     (remove-hook 'eldoc-documentation-functions 
#'eglot-signature-eldoc-function t)
     (cl-loop for (var . saved-binding) in eglot--saved-bindings
@@ -2030,13 +2019,15 @@ Use `eglot-managed-p' to determine if current buffer is 
managed.")
   "Return logical Eglot server for current buffer, nil if none."
   (setq eglot--cached-server
         (or eglot--cached-server
-            (cl-find-if #'eglot--languageId
-                        (gethash (eglot--current-project)
-                                 eglot--servers-by-project))
-            (and eglot-extend-to-xref
-                 buffer-file-name
-                 (gethash (expand-file-name buffer-file-name)
-                          eglot--servers-by-xrefed-file)))))
+            (and (not (eq major-mode 'fundamental-mode)) ; gh#1330
+                 (or
+                  (cl-find-if #'eglot--languageId
+                              (gethash (eglot--current-project)
+                                       eglot--servers-by-project))
+                  (and eglot-extend-to-xref
+                       buffer-file-name
+                       (gethash (expand-file-name buffer-file-name)
+                                eglot--servers-by-xrefed-file)))))))
 
 (defun eglot--current-server-or-lose ()
   "Return current logical Eglot server connection or error."
@@ -2067,7 +2058,7 @@ If it is activated, also signal textDocument/didOpen."
       (eglot-inlay-hints-mode 1)
       (run-hooks 'eglot-managed-mode-hook))))
 
-(add-hook 'after-change-major-mode-hook 'eglot--maybe-activate-editing-mode)
+(add-hook 'after-change-major-mode-hook #'eglot--maybe-activate-editing-mode)
 
 (defun eglot-clear-status (server)
   "Clear the last JSONRPC error for SERVER."
@@ -2187,8 +2178,7 @@ Uses THING, FACE, DEFS and PREPEND."
   "Compose Eglot's mode-line."
   (let* ((server (eglot-current-server))
          (nick (and server (eglot-project-nickname server)))
-         (pending (and server (hash-table-count
-                               (jsonrpc--request-continuations server))))
+         (pending (and server (jsonrpc-continuation-count server)))
          (last-error (and server (jsonrpc-last-error server))))
     (append
      `(,(propertize
@@ -2241,12 +2231,12 @@ still unanswered LSP requests to the server\n")))
 (put 'eglot-warning 'flymake-category 'flymake-warning)
 (put 'eglot-error 'flymake-category 'flymake-error)
 
-(defalias 'eglot--make-diag 'flymake-make-diagnostic)
-(defalias 'eglot--diag-data 'flymake-diagnostic-data)
+(defalias 'eglot--make-diag #'flymake-make-diagnostic)
+(defalias 'eglot--diag-data #'flymake-diagnostic-data)
 
 (defvar eglot-diagnostics-map
   (let ((map (make-sparse-keymap)))
-    (define-key map [mouse-2] 'eglot-code-actions-at-mouse)
+    (define-key map [mouse-2] #'eglot-code-actions-at-mouse)
     map)
   "Keymap active in Eglot-backed Flymake diagnostic overlays.")
 
@@ -2644,7 +2634,7 @@ root of the current project.  It should return an object 
of the
 format described above.")
 
 ;;;###autoload
-(put 'eglot-workspace-configuration 'safe-local-variable 'listp)
+(put 'eglot-workspace-configuration 'safe-local-variable #'listp)
 
 (defun eglot-show-workspace-configuration (&optional server)
   "Dump `eglot-workspace-configuration' as JSON for debugging."
@@ -3071,9 +3061,14 @@ for which LSP on-type-formatting should be requested."
            finally (cl-return comp)))
 
 (defun eglot--dumb-allc (pat table pred _point) (funcall table pat pred t))
+(defun eglot--dumb-tryc (pat table pred point)
+  (let ((probe (funcall table pat pred nil)))
+    (cond ((eq probe t) t)
+          (probe (cons probe (length probe)))
+          (t (cons pat point)))))
 
 (add-to-list 'completion-category-defaults '(eglot-capf (styles 
eglot--dumb-flex)))
-(add-to-list 'completion-styles-alist '(eglot--dumb-flex ignore 
eglot--dumb-allc))
+(add-to-list 'completion-styles-alist '(eglot--dumb-flex eglot--dumb-tryc 
eglot--dumb-allc))
 
 (defun eglot-completion-at-point ()
   "Eglot's `completion-at-point' function."
@@ -3082,6 +3077,7 @@ for which LSP on-type-formatting should be requested."
     (let* ((server (eglot--current-server-or-lose))
            (bounds (or (bounds-of-thing-at-point 'symbol)
                        (cons (point) (point))))
+           (bounds-string (buffer-substring (car bounds) (cdr bounds)))
            (sort-completions
             (lambda (completions)
               (cl-sort completions
@@ -3131,7 +3127,8 @@ for which LSP on-type-formatting should be requested."
                          items)))
                   ;; (trace-values "Requested" (length proxies) cachep bounds)
                   (setq eglot--capf-session
-                        (if cachep (list bounds retval resolved orig-pos) 
:none))
+                        (if cachep (list bounds retval resolved orig-pos
+                                         bounds-string) :none))
                   (setq local-cache retval)))))
            (resolve-maybe
             ;; Maybe completion/resolve JSON object `lsp-comp' into
@@ -3151,7 +3148,8 @@ for which LSP on-type-formatting should be requested."
                  (>= (cdr bounds) (cdr (nth 0 eglot--capf-session))))
         (setq local-cache (nth 1 eglot--capf-session)
               resolved (nth 2 eglot--capf-session)
-              orig-pos (nth 3 eglot--capf-session))
+              orig-pos (nth 3 eglot--capf-session)
+              bounds-string (nth 4 eglot--capf-session))
         ;; (trace-values "Recalling cache" (length local-cache) bounds 
orig-pos)
         )
       (list
@@ -3264,9 +3262,10 @@ for which LSP on-type-formatting should be requested."
                         ;; Revert buffer back to state when the edit
                         ;; was obtained from server. If a `proxy'
                         ;; "bar" was obtained from a buffer with
-                        ;; "foo.b", the LSP edit applies to that'
+                        ;; "foo.b", the LSP edit applies to that
                         ;; state, _not_ the current "foo.bar".
                         (delete-region orig-pos (point))
+                        (insert (substring bounds-string (- orig-pos (car 
bounds))))
                         (eglot--dbind ((TextEdit) range newText) textEdit
                           (pcase-let ((`(,beg . ,end)
                                        (eglot-range-region range)))
@@ -3620,16 +3619,17 @@ edit proposed by the server."
 
 (defun eglot--code-action-bounds ()
   "Calculate appropriate bounds depending on region and point."
-  (let (diags)
+  (let (diags boftap)
     (cond ((use-region-p) `(,(region-beginning) ,(region-end)))
           ((setq diags (flymake-diagnostics (point)))
            (cl-loop for d in diags
                     minimizing (flymake-diagnostic-beg d) into beg
                     maximizing (flymake-diagnostic-end d) into end
                     finally (cl-return (list beg end))))
+          ((setq boftap (bounds-of-thing-at-point 'sexp))
+           (list (car boftap) (cdr boftap)))
           (t
-           (let ((boftap (bounds-of-thing-at-point 'sexp)))
-             (list (car boftap) (cdr boftap)))))))
+           (list (point) (point))))))
 
 (defun eglot-code-actions (beg &optional end action-kind interactive)
   "Find LSP code actions of type ACTION-KIND between BEG and END.
@@ -3664,7 +3664,8 @@ at point.  With prefix argument, prompt for ACTION-KIND."
          ;; Redo filtering, in case the `:only' didn't go through.
          (actions (cl-loop for a across actions
                            when (or (not action-kind)
-                                    (equal action-kind (plist-get a :kind)))
+                                    ;; github#847
+                                    (string-prefix-p action-kind (plist-get a 
:kind)))
                            collect a)))
     (if interactive
         (eglot--read-execute-code-action actions server action-kind)
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 4745b28a38e..3161d2e5a9a 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -1,6 +1,6 @@
 ;;; elisp-mode.el --- Emacs Lisp mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1986, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1999-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: lisp, languages
@@ -85,10 +85,10 @@ All commands in `lisp-mode-shared-map' are inherited by 
this map."
     ["Byte-recompile Directory..." byte-recompile-directory
      :help "Recompile every `.el' file in DIRECTORY that needs recompilation"]
     ["Native-compile This File" emacs-lisp-native-compile
-     :help "Compile the current file containing the current buffer to native 
code"
+     :help "Compile this buffer's file to native code"
      :active (native-comp-available-p)]
     ["Native-compile and Load" emacs-lisp-native-compile-and-load
-     :help "Compile the current file to native code, then load compiled native 
code"
+     :help "Compile this buffer's file to native code, then load compiled 
native code"
      :active (native-comp-available-p)]
     ["Disassemble Byte Compiled Object..." disassemble
      :help "Print disassembled code for OBJECT in a buffer"]
@@ -224,7 +224,9 @@ All commands in `lisp-mode-shared-map' are inherited by 
this map."
 (declare-function comp-write-bytecode-file "comp")
 
 (defun emacs-lisp-native-compile ()
-  "Native-compile synchronously the current file (if it has changed)."
+  "Native-compile the current buffer's file (if it has changed).
+This invokes a synchronous native-compilation of the file that is
+visited by the current buffer."
   (interactive nil emacs-lisp-mode)
   (emacs-lisp--before-compile-buffer)
   (let* ((byte+native-compile t)
@@ -234,12 +236,14 @@ All commands in `lisp-mode-shared-map' are inherited by 
this map."
       (comp-write-bytecode-file eln))))
 
 (defun emacs-lisp-native-compile-and-load ()
-  "Native-compile synchronously the current file (if it has changed).
-Load the compiled code when finished.
+  "Native-compile the current buffer's file (if it has changed), then load it.
+This invokes a synchronous native-compilation of the file that is
+visited by the current buffer, then loads the compiled native code
+when the compilation is finished.
 
 Use `emacs-lisp-byte-compile-and-load' in combination with
 `native-comp-jit-compilation' set to t to achieve asynchronous
-native compilation."
+native compilation of the current buffer's file."
   (interactive nil emacs-lisp-mode)
   (when-let ((byte-file (emacs-lisp-native-compile)))
     (load (file-name-sans-extension byte-file))))
@@ -653,12 +657,13 @@ functions are annotated with \"<f>\" via the
                    (save-excursion
                      (backward-sexp 1)
                      (skip-chars-forward "`',‘#")
-                     (point))
+                     (min (point) pos))
                  (scan-error pos)))
           (end
-           (unless (or (eq beg (point-max))
-                       (member (char-syntax (char-after beg))
-                                '(?\" ?\()))
+           (cond
+            ((and (< beg (point-max))
+                  (memq (char-syntax (char-after beg))
+                                  '(?w ?\\ ?_)))
              (condition-case nil
                  (save-excursion
                    (goto-char beg)
@@ -666,7 +671,11 @@ functions are annotated with \"<f>\" via the
                     (skip-chars-backward "'’")
                    (when (>= (point) pos)
                      (point)))
-               (scan-error pos))))
+               (scan-error pos)))
+             ((or (>= beg (point-max))
+                  (memq (char-syntax (char-after beg))
+                       '(?\) ?\s)))
+              beg)))
            ;; t if in function position.
            (funpos (eq (char-before beg) ?\())
            (quoted (elisp--form-quoted-p beg))
diff --git a/lisp/progmodes/elixir-ts-mode.el b/lisp/progmodes/elixir-ts-mode.el
index 62429308d96..b493195eedd 100644
--- a/lisp/progmodes/elixir-ts-mode.el
+++ b/lisp/progmodes/elixir-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; elixir-ts-mode.el --- Major mode for Elixir with tree-sitter support -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Wilhelm H Kirschbaum <wkirschbaum@gmail.com>
 ;; Created: November 2022
diff --git a/lisp/progmodes/erts-mode.el b/lisp/progmodes/erts-mode.el
index 5ff74082461..0cb77b30a75 100644
--- a/lisp/progmodes/erts-mode.el
+++ b/lisp/progmodes/erts-mode.el
@@ -1,6 +1,6 @@
 ;;; erts-mode.el --- major mode to edit erts files  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Keywords: tools
 
diff --git a/lisp/progmodes/etags-regen.el b/lisp/progmodes/etags-regen.el
new file mode 100644
index 00000000000..6cd78d3577a
--- /dev/null
+++ b/lisp/progmodes/etags-regen.el
@@ -0,0 +1,431 @@
+;;; etags-regen.el --- Auto-(re)regenerating tags  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+
+;; Author: Dmitry Gutov <dmitry@gutov.dev>
+;; Keywords: tools
+
+;; 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:
+
+;; Simple automatic tags generation with updates on save.
+;;
+;; This mode provides automatic indexing for Emacs "go to definition"
+;; feature, the `xref-go-forward' command (bound to `M-.' by default).
+;;
+;; At the moment reindexing works off before/after-save-hook, but to
+;; handle more complex changes (for example, the user switching to
+;; another branch from the terminal) we can look into plugging into
+;; something like `filenotify'.
+;;
+;; Note that this feature disables itself if the user has some tags
+;; table already visited (with `M-x visit-tags-table', or through an
+;; explicit prompt triggered by some feature that requires tags).
+
+;;; Code:
+
+(require 'cl-lib)
+
+(defgroup etags-regen nil
+  "Auto-(re)generating tags."
+  :group 'tools)
+
+(defvar etags-regen--tags-file nil)
+(defvar etags-regen--tags-root nil)
+(defvar etags-regen--new-file nil)
+
+(declare-function project-root "project")
+(declare-function project-files "project")
+(declare-function dired-glob-regexp "dired")
+
+(defcustom etags-regen-program (executable-find "etags")
+  "Name of the etags program used by `etags-regen-mode'.
+
+If you only have `ctags' installed, you can also set this to
+\"ctags -e\".  Some features might not be supported this way."
+  ;; Always having our 'etags' here would be easier, but we can't
+  ;; always rely on it being installed.  So it might be ctags's etags.
+  :type 'file
+  :version "30.1")
+
+(defcustom etags-regen-tags-file "TAGS"
+  "Name of the tags file to create inside the project by `etags-regen-mode'.
+
+The value should either be a simple file name (no directory
+specified), or a function that accepts the project root directory
+and returns a distinct absolute file name for its tags file.  The
+latter possibility is useful when you prefer to store the tag
+files somewhere else, for example in `temporary-file-directory'."
+  :type '(choice (string :tag "File name")
+                 (function :tag "Function that returns file name"))
+  :version "30.1")
+
+(defcustom etags-regen-program-options nil
+  "List of additional options for etags program invoked by `etags-regen-mode'."
+  :type '(repeat string)
+  :version "30.1")
+
+(defcustom etags-regen-regexp-alist nil
+  "Mapping of languages to etags regexps for `etags-regen-mode'.
+
+These regexps are used in addition to the tags made with the
+standard parsing based on the language.
+
+The value must be a list where each element has the
+form (LANGUAGES . TAG-REGEXPS) where both LANGUAGES and
+TAG-REGEXPS are lists of strings.
+
+Each language should be one of the recognized by etags, see
+`etags --help'.  Each tag regexp should be a string in the format
+documented for the `--regex' arguments (without `{language}').
+
+We currently support only Emacs's etags program with this option."
+  :type '(repeat
+          (cons
+           :tag "Languages group"
+           (repeat (string :tag "Language name"))
+           (repeat (string :tag "Tag Regexp"))))
+  :version "30.1")
+
+;;;###autoload
+(put 'etags-regen-regexp-alist 'safe-local-variable
+     (lambda (value)
+       (and (listp value)
+            (seq-every-p
+             (lambda (group)
+               (and (consp group)
+                    (listp (car group))
+                    (listp (cdr group))
+                    (seq-every-p #'stringp (car group))
+                    (seq-every-p #'stringp (cdr group))))
+             value))))
+
+;; We have to list all extensions: etags falls back to Fortran
+;; when it cannot determine the type of the file.
+;; http://lists.gnu.org/archive/html/emacs-devel/2018-01/msg00323.html
+(defcustom etags-regen-file-extensions
+  '("rb" "js" "py" "pl" "el" "c" "cpp" "cc" "h" "hh" "hpp"
+    "java" "go" "cl" "lisp" "prolog" "php" "erl" "hrl"
+    "F" "f" "f90" "for" "cs" "a" "asm" "ads" "adb" "ada")
+  "Code file extensions for `etags-regen-mode'.
+
+File extensions to generate the tags for."
+  :type '(repeat (string :tag "File extension"))
+  :version "30.1")
+
+;;;###autoload
+(put 'etags-regen-file-extensions 'safe-local-variable
+     (lambda (value) (and (listp value) (seq-every-p #'stringp value))))
+
+;; FIXME: We don't support root anchoring yet.
+(defcustom etags-regen-ignores nil
+  "Additional ignore rules, in the format of `project-ignores'."
+  :type '(repeat
+          (string :tag "Glob to ignore"))
+  :version "30.1")
+
+;;;###autoload
+(put 'etags-regen-ignores 'safe-local-variable
+     (lambda (value) (and (listp value) (seq-every-p #'stringp value))))
+
+(defvar etags-regen--errors-buffer-name "*etags-regen-tags-errors*")
+
+(defvar etags-regen--rescan-files-limit 100)
+
+(defun etags-regen--all-mtimes (proj)
+  (let ((files (etags-regen--all-files proj))
+        (mtimes (make-hash-table :test 'equal))
+        file-name-handler-alist)
+    (dolist (f files)
+      (condition-case nil
+          (puthash f
+                   (file-attribute-modification-time
+                    (file-attributes f))
+                   mtimes)
+        (file-missing nil)))
+    mtimes))
+
+(defun etags-regen--choose-tags-file (proj)
+  (if (functionp etags-regen-tags-file)
+      (funcall etags-regen-tags-file (project-root proj))
+    (expand-file-name etags-regen-tags-file (project-root proj))))
+
+(defun etags-regen--refresh (proj)
+  (save-excursion
+    (let* ((tags-file (etags-regen--choose-tags-file proj))
+           (tags-mtime (file-attribute-modification-time
+                        (file-attributes tags-file)))
+           (all-mtimes (etags-regen--all-mtimes proj))
+           added-files
+           changed-files
+           removed-files)
+      (etags-regen--visit-table tags-file (project-root proj))
+      (set-buffer (get-file-buffer tags-file))
+      (dolist (file (tags-table-files))
+        (let ((mtime (gethash file all-mtimes)))
+          (cond
+           ((null mtime)
+            (push file removed-files))
+           ((time-less-p tags-mtime mtime)
+            (push file changed-files)
+            (remhash file all-mtimes))
+           (t
+            (remhash file all-mtimes)))))
+      (maphash
+       (lambda (key _value)
+         (push key added-files))
+       all-mtimes)
+      (if (> (+ (length added-files)
+                (length changed-files)
+                (length removed-files))
+             etags-regen--rescan-files-limit)
+          (progn
+            (message "etags-regen: Too many changes, falling back to full 
rescan")
+            (etags-regen--tags-cleanup))
+        (dolist (file (nconc removed-files changed-files))
+          (etags-regen--remove-tag file))
+        (when (or changed-files added-files)
+          (apply #'etags-regen--append-tags
+                 (nconc changed-files added-files)))
+        (when (or changed-files added-files removed-files)
+          (let ((save-silently t)
+                (message-log-max nil))
+            (save-buffer 0)))))))
+
+(defun etags-regen--maybe-generate ()
+  (let (proj)
+    (when (and etags-regen--tags-root
+               (not (file-in-directory-p default-directory
+                                         etags-regen--tags-root)))
+      (etags-regen--tags-cleanup))
+    (when (and (not etags-regen--tags-root)
+               ;; If existing table is visited that's not generated by
+               ;; this mode, skip all functionality.
+               (not (or tags-file-name
+                        tags-table-list))
+               (file-exists-p (etags-regen--choose-tags-file
+                               (setq proj (project-current)))))
+      (message "Found existing tags table, refreshing...")
+      (etags-regen--refresh proj))
+    (when (and (not (or tags-file-name
+                        tags-table-list))
+               (setq proj (or proj (project-current))))
+      (message "Generating new tags table...")
+      (let ((start (time-to-seconds)))
+        (etags-regen--tags-generate proj)
+        (message "...done (%.2f s)" (- (time-to-seconds) start))))))
+
+(defun etags-regen--all-files (proj)
+  (let* ((root (project-root proj))
+         (default-directory root)
+         ;; TODO: Make the scanning more efficient, e.g. move the
+         ;; filtering by glob to project (project-files-filtered...).
+         (files (project-files proj))
+         (match-re (concat
+                    "\\."
+                    (regexp-opt etags-regen-file-extensions)
+                    "\\'"))
+         (ir-start (1- (length root)))
+         (ignores-regexps
+          (mapcar #'etags-regen--ignore-regexp
+                  etags-regen-ignores)))
+    (cl-delete-if
+     (lambda (f) (or (not (string-match-p match-re f))
+                (string-match-p "/\\.#" f) ;Backup files.
+                (cl-some (lambda (ignore) (string-match ignore f ir-start))
+                         ignores-regexps)))
+     files)))
+
+(defun etags-regen--ignore-regexp (ignore)
+  (require 'dired)
+  ;; It's somewhat brittle to rely on Dired.
+  (let ((re (dired-glob-regexp ignore)))
+    ;; We could implement root anchoring here, but \\= doesn't work in
+    ;; string-match :-(.
+    (concat (unless (eq ?/ (aref re 3)) "/")
+            ;; Cutting off the anchors added by `dired-glob-regexp'.
+            (substring re 2 (- (length re) 2))
+            ;; This way we allow a glob to match against a directory
+            ;; name, or a file name.  And when it ends with / already,
+            ;; no need to add the anchoring.
+            (unless (eq ?/ (aref re (- (length re) 3)))
+              ;; Either match a full name segment, or eos.
+              "\\(?:/\\|\\'\\)"))))
+
+(defun etags-regen--tags-generate (proj)
+  (let* ((root (project-root proj))
+         (default-directory root)
+         (files (etags-regen--all-files proj))
+         (tags-file (etags-regen--choose-tags-file proj))
+         (ctags-p (etags-regen--ctags-p))
+         (command (format "%s %s %s - -o %s"
+                          etags-regen-program
+                          (mapconcat #'identity
+                                     (etags-regen--build-program-options 
ctags-p)
+                                     " ")
+                          ;; ctags's etags requires '-L' for stdin input.
+                          (if ctags-p "-L" "")
+                          tags-file)))
+    (with-temp-buffer
+      (mapc (lambda (f)
+              (insert f "\n"))
+            files)
+      (shell-command-on-region (point-min) (point-max) command
+                               nil nil etags-regen--errors-buffer-name t))
+    (etags-regen--visit-table tags-file root)))
+
+(defun etags-regen--visit-table (tags-file root)
+  ;; Invalidate the scanned tags after any change is written to disk.
+  (add-hook 'after-save-hook #'etags-regen--update-file)
+  (add-hook 'before-save-hook #'etags-regen--mark-as-new)
+  (setq etags-regen--tags-file tags-file
+        etags-regen--tags-root root)
+  (visit-tags-table etags-regen--tags-file))
+
+(defun etags-regen--ctags-p ()
+  (string-search "Ctags"
+                 (shell-command-to-string
+                  (format "%s --version" etags-regen-program))))
+
+(defun etags-regen--build-program-options (ctags-p)
+  (when (and etags-regen-regexp-alist ctags-p)
+    (user-error "etags-regen-regexp-alist is not supported with Ctags"))
+  (nconc
+   (mapcan
+    (lambda (group)
+      (mapcan
+       (lambda (lang)
+         (mapcar (lambda (regexp)
+                   (concat "--regex="
+                           (shell-quote-argument
+                            (format "{%s}%s" lang regexp))))
+                 (cdr group)))
+       (car group)))
+    etags-regen-regexp-alist)
+   (mapcar #'shell-quote-argument
+           etags-regen-program-options)))
+
+(defun etags-regen--update-file ()
+  ;; TODO: Maybe only do this when Emacs is idle for a bit.  Or defer
+  ;; the updates and do them later in bursts when the table is used.
+  (let* ((file-name buffer-file-name)
+         (tags-file-buf (and etags-regen--tags-root
+                             (get-file-buffer etags-regen--tags-file)))
+         (relname (concat "/" (file-relative-name file-name
+                                                  etags-regen--tags-root)))
+         (ignores etags-regen-ignores)
+         pr should-scan)
+    (save-excursion
+      (when tags-file-buf
+        (cond
+         ((and etags-regen--new-file
+               (kill-local-variable 'etags-regen--new-file)
+               (setq pr (project-current))
+               (equal (project-root pr) etags-regen--tags-root)
+               (member file-name (project-files pr)))
+          (set-buffer tags-file-buf)
+          (setq should-scan t))
+         ((progn (set-buffer tags-file-buf)
+                 (etags-regen--remove-tag file-name))
+          (setq should-scan t))))
+      (when (and should-scan
+                 (not (cl-some
+                       (lambda (ignore)
+                         (string-match-p
+                          (etags-regen--ignore-regexp ignore)
+                          relname))
+                       ignores)))
+        (etags-regen--append-tags file-name)
+        (let ((save-silently t)
+              (message-log-max nil))
+          (save-buffer 0))))))
+
+(defun etags-regen--remove-tag (file-name)
+  (goto-char (point-min))
+  (when (search-forward (format "\f\n%s," file-name) nil t)
+    (let ((start (match-beginning 0)))
+      (search-forward "\f\n" nil 'move)
+      (let ((inhibit-read-only t))
+        (delete-region start
+                       (if (eobp)
+                           (point)
+                         (- (point) 2)))))
+    t))
+
+(defun etags-regen--append-tags (&rest file-names)
+  (goto-char (point-max))
+  (let ((options (etags-regen--build-program-options (etags-regen--ctags-p)))
+        (inhibit-read-only t))
+    ;; XXX: call-process is significantly faster, though.
+    ;; Like 10ms vs 20ms here.  But `shell-command' makes it easy to
+    ;; direct stderr to a separate buffer.
+    (shell-command
+     (format "%s %s %s -o -"
+             etags-regen-program (mapconcat #'identity options " ")
+             (mapconcat #'identity file-names " "))
+     t etags-regen--errors-buffer-name))
+  ;; FIXME: Is there a better way to do this?
+  ;; Completion table is the only remaining place where the
+  ;; update is not incremental.
+  (setq-default tags-completion-table nil))
+
+(defun etags-regen--mark-as-new ()
+  (when (and etags-regen--tags-root
+             (not buffer-file-number))
+    (setq-local etags-regen--new-file t)))
+
+(defun etags-regen--tags-cleanup ()
+  (when etags-regen--tags-file
+    (let ((buffer (get-file-buffer etags-regen--tags-file)))
+      (and buffer
+           (kill-buffer buffer)))
+    (tags-reset-tags-tables)
+    (setq tags-file-name nil
+          tags-table-list nil
+          etags-regen--tags-file nil
+          etags-regen--tags-root nil))
+  (remove-hook 'after-save-hook #'etags-regen--update-file)
+  (remove-hook 'before-save-hook #'etags-regen--mark-as-new))
+
+(defvar etags-regen-mode-map (make-sparse-keymap))
+
+;;;###autoload
+(define-minor-mode etags-regen-mode
+  "Minor mode to automatically generate and update tags tables.
+
+This minor mode generates the tags table automatically based on
+the current project configuration, and later updates it as you
+edit the files and save the changes.
+
+If you select a tags table manually (for example, using
+\\[visit-tags-table]), then this mode will be effectively
+disabled for the entire session.  Use \\[tags-reset-tags-tables]
+to countermand the effect of a previous \\[visit-tags-table]."
+  :global t
+  (if etags-regen-mode
+      (progn
+        (advice-add 'etags--xref-backend :before
+                    #'etags-regen--maybe-generate)
+        (advice-add 'tags-completion-at-point-function :before
+                    #'etags-regen--maybe-generate))
+    (advice-remove 'etags--xref-backend #'etags-regen--maybe-generate)
+    (advice-remove 'tags-completion-at-point-function 
#'etags-regen--maybe-generate)
+    (etags-regen--tags-cleanup)))
+
+(provide 'etags-regen)
+
+;;; etags-regen.el ends here
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index d48dcc6659d..b9bd772ddfc 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -1,6 +1,6 @@
 ;;; etags.el --- etags facility for Emacs  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Author: Roland McGrath <roland@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
@@ -732,6 +732,7 @@ Returns t if it visits a tags table, or nil if there are no 
more in the list."
                       "File %s does not exist")
                     local-tags-file-name)))))
 
+;;;###autoload
 (defun tags-reset-tags-tables ()
   "Reset tags state to cancel effect of any previous \\[visit-tags-table] or 
\\[find-tag]."
   (interactive)
diff --git a/lisp/progmodes/executable.el b/lisp/progmodes/executable.el
index c15997dce3a..cb4a5eedb80 100644
--- a/lisp/progmodes/executable.el
+++ b/lisp/progmodes/executable.el
@@ -1,6 +1,6 @@
 ;;; executable.el --- base functionality for executable interpreter scripts  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1994-1996, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1996, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
 ;; Keywords: languages, unix
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
index 815c7352281..ec9d1995547 100644
--- a/lisp/progmodes/f90.el
+++ b/lisp/progmodes/f90.el
@@ -1,6 +1,6 @@
 ;;; f90.el --- Fortran-90 mode (free format)  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1995-1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1997, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Torbjörn Einarsson <Torbjorn.Einarsson@era.ericsson.se>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/flymake-cc.el b/lisp/progmodes/flymake-cc.el
index eb17006fbeb..60e7da5d617 100644
--- a/lisp/progmodes/flymake-cc.el
+++ b/lisp/progmodes/flymake-cc.el
@@ -1,6 +1,6 @@
 ;;; flymake-cc.el --- Flymake support for GNU tools for C/C++     -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: João Távora <joaotavora@gmail.com>
 ;; Keywords: languages, c
diff --git a/lisp/progmodes/flymake-proc.el b/lisp/progmodes/flymake-proc.el
index 2e9c28a92d5..2c7bb542489 100644
--- a/lisp/progmodes/flymake-proc.el
+++ b/lisp/progmodes/flymake-proc.el
@@ -1,6 +1,6 @@
 ;;; flymake-proc.el --- Flymake backend for external tools  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Pavel Kobyakov <pk_at_work@yahoo.com>
 ;; Maintainer: João Távora <joaotavora@gmail.com>
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index fb000517655..5974f076556 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -1,6 +1,6 @@
 ;;; flymake.el --- A universal on-the-fly syntax checker  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Pavel Kobyakov <pk_at_work@yahoo.com>
 ;; Maintainer: João Távora <joaotavora@gmail.com>
@@ -715,7 +715,7 @@ associated `flymake-category' return DEFAULT."
     (delete-overlay ov)))
 
 (defun flymake--eol-overlay-summary (src-ovs)
-  "Helper function for `flymake--eol-overlay-update'."
+  "Helper function for `flymake--update-eol-overlays'."
   (cl-flet ((summarize (d)
               (propertize (flymake-diagnostic-oneliner d t) 'face
                           (flymake--lookup-type-property (flymake--diag-type d)
@@ -1637,14 +1637,16 @@ correctly.")
 
 (defvar flymake--mode-line-counter-map
   (let ((map (make-sparse-keymap)))
+    ;; BEWARE: `mouse-wheel-UP-event' corresponds to `wheel-DOWN' events
+    ;; and vice versa!!
     (define-key map (vector 'mode-line mouse-wheel-down-event)
                 #'flymake--mode-line-counter-scroll-prev)
     (define-key map [mode-line wheel-down]
-                #'flymake--mode-line-counter-scroll-prev)
+                #'flymake--mode-line-counter-scroll-next)
     (define-key map (vector 'mode-line mouse-wheel-up-event)
                 #'flymake--mode-line-counter-scroll-next)
     (define-key map [mode-line wheel-up]
-                #'flymake--mode-line-counter-scroll-next)
+                #'flymake--mode-line-counter-scroll-prev)
     map))
 
 (defun flymake--mode-line-counter-1 (type)
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
index 02c40943ebf..8a726dfe66e 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -1,6 +1,6 @@
 ;;; fortran.el --- Fortran mode for GNU Emacs -*- lexical-binding: t -*-
 
-;; Copyright (C) 1986-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael D. Prange <prange@erl.mit.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index 7ae4bcea1e1..e08653f7f9e 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -1,6 +1,6 @@
 ;;; gdb-mi.el --- User Interface for running GDB  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Nick Roberts <nickrob@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
@@ -817,6 +817,42 @@ NOARG must be t when this macro is used outside `gud-def'."
 
 (defvar gdb-control-level 0)
 
+(defun gdb-load-history ()
+  "Load GDB history from a history file.
+The name of the history file is given by environment variable GDBHISTFILE,
+falling back to \".gdb_history\" and \".gdbinit\"."
+  (when (ring-empty-p comint-input-ring) ; cf shell-mode
+    (let ((hfile (expand-file-name (or (getenv "GDBHISTFILE")
+                                      (if (eq system-type 'ms-dos)
+                                          "_gdb_history"
+                                        ".gdb_history"))))
+         ;; gdb defaults to 256, but we'll default to comint-input-ring-size.
+         (hsize (getenv "HISTSIZE")))
+      (dolist (file (append '("~/.gdbinit")
+                           (unless (string-equal (expand-file-name ".")
+                                                  (expand-file-name "~"))
+                             '(".gdbinit"))))
+       (if (file-readable-p (setq file (expand-file-name file)))
+           (with-temp-buffer
+             (insert-file-contents file)
+             ;; TODO? check for "set history save\\(  *on\\)?" and do
+             ;; not use history otherwise?
+             (while (re-search-forward
+                     "^ *set history \\(filename\\|size\\)  *\\(.*\\)" nil t)
+               (cond ((string-equal (match-string 1) "filename")
+                      (setq hfile (expand-file-name
+                                   (match-string 2)
+                                   (file-name-directory file))))
+                     ((string-equal (match-string 1) "size")
+                      (setq hsize (match-string 2))))))))
+      (and (stringp hsize)
+          (integerp (setq hsize (string-to-number hsize)))
+          (> hsize 0)
+           (setq-local comint-input-ring-size hsize))
+      (if (stringp hfile)
+          (setq-local comint-input-ring-file-name hfile))
+      (comint-read-input-ring t))))
+
 ;;;###autoload
 (defun gdb (command-line)
   "Run gdb passing it COMMAND-LINE as arguments.
@@ -902,37 +938,8 @@ detailed description of this mode.
   (setq-local gud-minor-mode 'gdbmi)
   (setq-local gdb-control-level 0)
   (setq comint-input-sender 'gdb-send)
-  (when (ring-empty-p comint-input-ring) ; cf shell-mode
-    (let ((hfile (expand-file-name (or (getenv "GDBHISTFILE")
-                                      (if (eq system-type 'ms-dos)
-                                          "_gdb_history"
-                                        ".gdb_history"))))
-         ;; gdb defaults to 256, but we'll default to comint-input-ring-size.
-         (hsize (getenv "HISTSIZE")))
-      (dolist (file (append '("~/.gdbinit")
-                           (unless (string-equal (expand-file-name ".")
-                                                  (expand-file-name "~"))
-                             '(".gdbinit"))))
-       (if (file-readable-p (setq file (expand-file-name file)))
-           (with-temp-buffer
-             (insert-file-contents file)
-             ;; TODO? check for "set history save\\(  *on\\)?" and do
-             ;; not use history otherwise?
-             (while (re-search-forward
-                     "^ *set history \\(filename\\|size\\)  *\\(.*\\)" nil t)
-               (cond ((string-equal (match-string 1) "filename")
-                      (setq hfile (expand-file-name
-                                   (match-string 2)
-                                   (file-name-directory file))))
-                     ((string-equal (match-string 1) "size")
-                      (setq hsize (match-string 2))))))))
-      (and (stringp hsize)
-          (integerp (setq hsize (string-to-number hsize)))
-          (> hsize 0)
-           (setq-local comint-input-ring-size hsize))
-      (if (stringp hfile)
-          (setq-local comint-input-ring-file-name hfile))
-      (comint-read-input-ring t)))
+  (gdb-load-history)
+
   (gud-def gud-tbreak "tbreak %f:%l" "\C-t"
           "Set temporary breakpoint at current line." t)
   (gud-def gud-jump
diff --git a/lisp/progmodes/glasses.el b/lisp/progmodes/glasses.el
index efa191786db..92de2a2581f 100644
--- a/lisp/progmodes/glasses.el
+++ b/lisp/progmodes/glasses.el
@@ -1,6 +1,6 @@
 ;;; glasses.el --- make cantReadThis readable  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Milan Zamazal <pdm@zamazal.org>
 ;; Keywords: tools
diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el
index 46b631e5af2..65adc1c55ea 100644
--- a/lisp/progmodes/go-ts-mode.el
+++ b/lisp/progmodes/go-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; go-ts-mode.el --- tree-sitter support for Go  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author     : Randy Taylor <dev@rjt.dev>
 ;; Maintainer : Randy Taylor <dev@rjt.dev>
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index 5f9da352f77..657349cbdff 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -1,6 +1,6 @@
 ;;; grep.el --- run `grep' and display the results  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1987, 1993-1999, 2001-2023 Free Software
+;; Copyright (C) 1985-1987, 1993-1999, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Roland McGrath <roland@gnu.org>
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index 70af736372e..b7c85fe7f43 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -1,6 +1,6 @@
 ;;; gud.el --- Grand Unified Debugger mode for running GDB and other debuggers 
 -*- lexical-binding:t -*-
 
-;; Copyright (C) 1992-1996, 1998, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1992-1996, 1998, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Eric S. Raymond <esr@thyrsus.com>
@@ -243,7 +243,7 @@ Check it when `gud-running' is t")
      :visible (eq gud-minor-mode 'gdbmi)]
     ["Print Expression" gud-print
      :enable (not gud-running)]
-    ["Dump object-Derefenrece" gud-pstar
+    ["Dump object-Dereference" gud-pstar
      :label (if (eq gud-minor-mode 'jdb)
                "Dump object"
               "Print Dereference")
@@ -3974,11 +3974,11 @@ def gud_complete(s, max):
         print(f'\"{string_list.GetStringAtIndex(i)}\" ')
     print(')##')
 "
-  "Python code sent to LLDB for gud-specific initialisation.")
+  "Python code sent to LLDB for gud-specific initialization.")
 
 (defun gud-lldb-fetch-completions (context command)
   "Return the data to complete the LLDB command before point.
-This is what the Python function we installed at initialzation
+This is what the Python function we installed at initialization
 time returns, as a Lisp list.
 Maximum number of completions requested from LLDB is controlled
 by `gud-lldb-max-completions', which see."
@@ -4057,7 +4057,7 @@ Please note that completion framework that complete while 
you
 type, like Corfu, do not work well with this mode.  You should
 consider to turn them off in this mode.
 
-This command runs functions from `lldb-mode-hook'. "
+This command runs functions from `lldb-mode-hook'."
   (interactive (list (gud-query-cmdline 'lldb)))
 
   (when (and gud-comint-buffer
diff --git a/lisp/progmodes/heex-ts-mode.el b/lisp/progmodes/heex-ts-mode.el
index 5237c767330..7b53a44deb2 100644
--- a/lisp/progmodes/heex-ts-mode.el
+++ b/lisp/progmodes/heex-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; heex-ts-mode.el --- Major mode for Heex with tree-sitter support -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Wilhelm H Kirschbaum <wkirschbaum@gmail.com>
 ;; Created: November 2022
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el
index 836db83c2f3..71f55379d96 100644
--- a/lisp/progmodes/hideif.el
+++ b/lisp/progmodes/hideif.el
@@ -1,6 +1,6 @@
 ;;; hideif.el --- hides selected code within ifdef  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1988, 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Brian Marick
 ;;     Daniel LaLiberte <liberte@holonexus.org>
@@ -1750,7 +1750,7 @@ and `+='...)."
                ;; Split REM-BODY @ __VA_ARGS__ into LEFT and right
                (setq part nil)
                (if (zerop va)
-                   (setq left nil ; __VA_ARGS__ trimed
+                   (setq left nil ; __VA_ARGS__ trimmed
                          rem-body (cdr rem-body))
                  (setq left rem-body
                        rem-body (cdr (nthcdr va rem-body))) ; _V_ removed
@@ -1801,7 +1801,7 @@ and `+='...)."
                    actual-parms nil)))
 
           (t
-           (error "Interal error: impossible case."))))
+           (error "Internal error: impossible case"))))
 
        (pop actual-parms)
        while actual-parms) ; end cl-loop
diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el
index 78e39fad740..b181b21118f 100644
--- a/lisp/progmodes/hideshow.el
+++ b/lisp/progmodes/hideshow.el
@@ -1,6 +1,6 @@
 ;;; hideshow.el --- minor mode cmds to selectively display code/comment blocks 
 -*- lexical-binding:t -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Thien-Thi Nguyen <ttn@gnu.org>
 ;;      Dan Nicolaescu <dann@gnu.org>
diff --git a/lisp/progmodes/icon.el b/lisp/progmodes/icon.el
index e1f9049c364..d4816b416df 100644
--- a/lisp/progmodes/icon.el
+++ b/lisp/progmodes/icon.el
@@ -1,6 +1,6 @@
 ;;; icon.el --- mode for editing Icon code  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1989, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Chris Smith <csmith@convex.com>
 ;; Created: 15 Feb 89
diff --git a/lisp/progmodes/idlw-complete-structtag.el 
b/lisp/progmodes/idlw-complete-structtag.el
index cbc94ac0ba4..bcc2ee2f005 100644
--- a/lisp/progmodes/idlw-complete-structtag.el
+++ b/lisp/progmodes/idlw-complete-structtag.el
@@ -1,6 +1,6 @@
 ;;; idlw-complete-structtag.el --- Completion of structure tags.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@astro.uva.nl>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/idlw-help.el b/lisp/progmodes/idlw-help.el
index a57a0c32ac7..217b2ab6691 100644
--- a/lisp/progmodes/idlw-help.el
+++ b/lisp/progmodes/idlw-help.el
@@ -1,6 +1,6 @@
 ;;; idlw-help.el --- HTML Help code for IDLWAVE  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 ;;
 ;; Authors: JD Smith <jd.smith@utoledo.edu>
 ;;          Carsten Dominik <dominik@science.uva.nl>
diff --git a/lisp/progmodes/idlw-shell.el b/lisp/progmodes/idlw-shell.el
index 37c501ae4e2..0f11103cf02 100644
--- a/lisp/progmodes/idlw-shell.el
+++ b/lisp/progmodes/idlw-shell.el
@@ -1,6 +1,6 @@
 ;;; idlw-shell.el --- run IDL as an inferior process of Emacs.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Authors: JD Smith <jd.smith@utoledo.edu>
 ;;          Carsten Dominik <dominik@astro.uva.nl>
@@ -829,7 +829,7 @@ IDL has currently stepped.")
 
 3. Routine Info
    ------------
-   `\\[idlwave-routine-info]' displays information about an IDL routine near 
point,
+   \\[idlwave-routine-info] displays information about an IDL routine near 
point,
    just like in `idlwave-mode'.  The module used is the one at point or
    the one whose argument list is being edited.
    To update IDLWAVE's knowledge about compiled or edited modules, use
diff --git a/lisp/progmodes/idlw-toolbar.el b/lisp/progmodes/idlw-toolbar.el
index 4319bba0e63..c6cb47baa40 100644
--- a/lisp/progmodes/idlw-toolbar.el
+++ b/lisp/progmodes/idlw-toolbar.el
@@ -1,6 +1,6 @@
 ;;; idlw-toolbar.el --- a debugging toolbar for IDLWAVE  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@astro.uva.nl>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el
index f60cc9372eb..30442fa0d34 100644
--- a/lisp/progmodes/idlwave.el
+++ b/lisp/progmodes/idlwave.el
@@ -1,6 +1,6 @@
 ;;; idlwave.el --- IDL editing mode for GNU Emacs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Authors: JD Smith <jd.smith@utoledo.edu>
 ;;          Carsten Dominik <dominik@science.uva.nl>
@@ -657,7 +657,7 @@ When you specify a class, this information can be stored as 
a text
 property on the `->' arrow in the source code, so that during the same
 editing session, IDLWAVE will not have to ask again.  When this
 variable is non-nil, IDLWAVE will store and reuse the class information.
-The class stored can be checked and removed with `\\[idlwave-routine-info]'
+The class stored can be checked and removed with \\[idlwave-routine-info]
 on the arrow.
 
 The default of this variable is nil, since the result of commands then
diff --git a/lisp/progmodes/inf-lisp.el b/lisp/progmodes/inf-lisp.el
index e98e00dee7a..141bd18cf1e 100644
--- a/lisp/progmodes/inf-lisp.el
+++ b/lisp/progmodes/inf-lisp.el
@@ -1,6 +1,6 @@
 ;;; inf-lisp.el --- an inferior-lisp mode  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1988-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988-2024 Free Software Foundation, Inc.
 
 ;; Author: Olin Shivers <shivers@cs.cmu.edu>
 ;; Keywords: processes, lisp
diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el
index 6ca7a473411..0b1ac49b99f 100644
--- a/lisp/progmodes/java-ts-mode.el
+++ b/lisp/progmodes/java-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; java-ts-mode.el --- tree-sitter support for Java  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author     : Theodor Thornhill <theo@thornhill.no>
 ;; Maintainer : Theodor Thornhill <theo@thornhill.no>
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 5a669fdbd42..ebc098e6a75 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -1,6 +1,6 @@
 ;;; js.el --- Major mode for editing JavaScript  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Karl Landstrom <karl.landstrom@brgeight.se>
 ;;         Daniel Colascione <dancol@dancol.org>
@@ -3418,6 +3418,26 @@ This function is intended for use in 
`after-change-functions'."
 
 ;;; Tree sitter integration
 
+(defun js--treesit-font-lock-compatibility-definition-feature ()
+  "Font lock helper, to handle different releases of tree-sitter-javascript.
+Check if a node type is available, then return the right font lock rules
+for \"definition\" feature."
+  (condition-case nil
+      (progn (treesit-query-capture 'javascript '((function_expression) @cap))
+             ;; Starting from version 0.20.2 of the grammar.
+             '((function_expression
+                name: (identifier) @font-lock-function-name-face)
+               (variable_declarator
+                name: (identifier) @font-lock-function-name-face
+                value: [(function_expression) (arrow_function)])))
+    (error
+     ;; An older version of the grammar.
+     '((function
+        name: (identifier) @font-lock-function-name-face)
+       (variable_declarator
+        name: (identifier) @font-lock-function-name-face
+        value: [(function) (arrow_function)])))))
+
 (defun js-jsx--treesit-indent-compatibility-bb1f97b ()
   "Indent rules helper, to handle different releases of tree-sitter-javascript.
 Check if a node type is available, then return the right indent rules."
@@ -3463,6 +3483,11 @@ Check if a node type is available, then return the right 
indent rules."
        ((parent-is "class_body") parent-bol js-indent-level)
        ((parent-is ,switch-case) parent-bol js-indent-level)
        ((parent-is "statement_block") parent-bol js-indent-level)
+       ((match "while" "do_statement") parent-bol 0)
+       ((match "else" "if_statement") parent-bol 0)
+       ((parent-is ,(rx (or (seq (or "if" "for" "for_in" "while" "do") 
"_statement")
+                            "else_clause")))
+        parent-bol js-indent-level)
 
        ;; JSX
        ,@(js-jsx--treesit-indent-compatibility-bb1f97b)
@@ -3497,7 +3522,7 @@ Check if a node type is available, then return the right 
indent rules."
 
    :language 'javascript
    :feature 'comment
-   '((comment) @font-lock-comment-face)
+   '([(comment) (hash_bang_line)] @font-lock-comment-face)
 
    :language 'javascript
    :feature 'constant
@@ -3524,8 +3549,7 @@ Check if a node type is available, then return the right 
indent rules."
 
    :language 'javascript
    :feature 'definition
-   '((function
-      name: (identifier) @font-lock-function-name-face)
+   `(,@(js--treesit-font-lock-compatibility-definition-feature)
 
      (class_declaration
       name: (identifier) @font-lock-type-face)
@@ -3536,22 +3560,14 @@ Check if a node type is available, then return the 
right indent rules."
      (method_definition
       name: (property_identifier) @font-lock-function-name-face)
 
-     (method_definition
-      parameters: (formal_parameters (identifier) 
@font-lock-variable-name-face))
-
-     (arrow_function
-      parameters: (formal_parameters (identifier) 
@font-lock-variable-name-face))
-
-     (function_declaration
-      parameters: (formal_parameters (identifier) 
@font-lock-variable-name-face))
+     (formal_parameters
+      [(identifier) @font-lock-variable-name-face
+       (array_pattern (identifier) @font-lock-variable-name-face)
+       (object_pattern (shorthand_property_identifier_pattern) 
@font-lock-variable-name-face)])
 
      (variable_declarator
       name: (identifier) @font-lock-variable-name-face)
 
-     (variable_declarator
-      name: (identifier) @font-lock-function-name-face
-      value: [(function) (arrow_function)])
-
      (variable_declarator
       name: [(array_pattern (identifier) @font-lock-variable-name-face)
              (object_pattern
@@ -3570,16 +3586,6 @@ Check if a node type is available, then return the right 
indent rules."
      ;; full namespace import (* as alias)
      (import_clause (namespace_import (identifier) 
@font-lock-variable-name-face)))
 
-   :language 'javascript
-   :feature 'property
-   '(((property_identifier) @font-lock-property-use-face
-      (:pred js--treesit-property-not-function-p
-             @font-lock-property-use-face))
-
-     (pair value: (identifier) @font-lock-variable-use-face)
-
-     ((shorthand_property_identifier) @font-lock-property-use-face))
-
    :language 'javascript
    :feature 'assignment
    '((assignment_expression
@@ -3591,13 +3597,7 @@ Check if a node type is available, then return the right 
indent rules."
       function: [(identifier) @font-lock-function-call-face
                  (member_expression
                   property:
-                  (property_identifier) @font-lock-function-call-face)])
-     (method_definition
-      name: (property_identifier) @font-lock-function-name-face)
-     (function_declaration
-      name: (identifier) @font-lock-function-call-face)
-     (function
-      name: (identifier) @font-lock-function-name-face))
+                  (property_identifier) @font-lock-function-call-face)]))
 
    :language 'javascript
    :feature 'jsx
@@ -3606,6 +3606,12 @@ Check if a node type is available, then return the right 
indent rules."
      (jsx_self_closing_element name: (_) @font-lock-function-call-face)
      (jsx_attribute (property_identifier) @font-lock-constant-face))
 
+   :language 'javascript
+   :feature 'property
+   '(((property_identifier) @font-lock-property-use-face)
+     (pair value: (identifier) @font-lock-variable-use-face)
+     ((shorthand_property_identifier) @font-lock-property-use-face))
+
    :language 'javascript
    :feature 'number
    '((number) @font-lock-number-face
@@ -3657,18 +3663,11 @@ OVERRIDE is the override flag described in
       (setq font-beg (treesit-node-end child)
             child (treesit-node-next-sibling child)))))
 
-(defun js--treesit-property-not-function-p (node)
-  "Check that NODE, a property_identifier, is not used as a function."
-  (not (equal (treesit-node-type
-               (treesit-node-parent ; Maybe call_expression.
-                (treesit-node-parent ; Maybe member_expression.
-                 node)))
-              "call_expression")))
-
 (defvar js--treesit-lhs-identifier-query
   (when (treesit-available-p)
     (treesit-query-compile 'javascript '((identifier) @id
-                                         (property_identifier) @id)))
+                                         (property_identifier) @id
+                                         
(shorthand_property_identifier_pattern) @id)))
   "Query that captures identifier and query_identifier.")
 
 (defun js--treesit-fontify-assignment-lhs (node override start end &rest _)
@@ -3680,7 +3679,8 @@ For OVERRIDE, START, END, see `treesit-font-lock-rules'."
      (treesit-node-start node) (treesit-node-end node)
      (pcase (treesit-node-type node)
        ("identifier" 'font-lock-variable-use-face)
-       ("property_identifier" 'font-lock-property-use-face))
+       ("property_identifier" 'font-lock-property-use-face)
+       ("shorthand_property_identifier_pattern" 'font-lock-variable-use-face))
      override start end)))
 
 (defun js--treesit-defun-name (node)
@@ -3717,6 +3717,9 @@ Currently there are `js-mode' and `js-ts-mode'."
 (define-derived-mode js-mode js-base-mode "JavaScript"
   "Major mode for editing JavaScript."
   :group 'js
+  (js--mode-setup))
+
+(defun js--mode-setup ()
   ;; Ensure all CC Mode "lang variables" are set to valid values.
   (c-init-language-vars js-mode)
   (setq-local indent-line-function #'js-indent-line)
@@ -3939,7 +3942,9 @@ See `treesit-thing-settings' for more information.")
         (put-text-property (1- ne) ne 'syntax-table syntax)))))
 
 ;;;###autoload
-(define-derived-mode js-json-mode js-mode "JSON"
+(define-derived-mode js-json-mode prog-mode "JSON"
+  :syntax-table js-mode-syntax-table
+  (js--mode-setup) ;Reuse most of `js-mode', but not as parent (bug#67463).
   (setq-local js-enabled-frameworks nil)
   ;; Speed up `syntax-ppss': JSON files can be big but can't hold
   ;; regexp matchers nor #! thingies (and `js-enabled-frameworks' is nil).
diff --git a/lisp/progmodes/json-ts-mode.el b/lisp/progmodes/json-ts-mode.el
index 78117356821..32bc10bbda9 100644
--- a/lisp/progmodes/json-ts-mode.el
+++ b/lisp/progmodes/json-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; json-ts-mode.el --- tree-sitter support for JSON  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author     : Theodor Thornhill <theo@thornhill.no>
 ;; Maintainer : Theodor Thornhill <theo@thornhill.no>
diff --git a/lisp/progmodes/ld-script.el b/lisp/progmodes/ld-script.el
index 01e8fd9e5e2..0b5ef6edeab 100644
--- a/lisp/progmodes/ld-script.el
+++ b/lisp/progmodes/ld-script.el
@@ -1,6 +1,6 @@
 ;;; ld-script.el --- GNU linker script editing mode for Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Masatake YAMATO <yamato@redhat.com>
 ;; Keywords: languages, faces
diff --git a/lisp/progmodes/lua-ts-mode.el b/lisp/progmodes/lua-ts-mode.el
index 7307a5b13f1..05a3ff6d7c6 100644
--- a/lisp/progmodes/lua-ts-mode.el
+++ b/lisp/progmodes/lua-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; lua-ts-mode.el --- Major mode for editing Lua files -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: John Muhl <jm@pub.pink>
 ;; Created: June 27, 2023
@@ -122,6 +122,28 @@
   :group 'lua-ts
   :version "30.1")
 
+(defcustom lua-ts-indent-continuation-lines t
+  "Controls how multi-line if/else statements are aligned.
+
+If t, then continuation lines are indented by `lua-ts-indent-offset':
+
+  if a
+      and b then
+      print(1)
+  end
+
+If nil, then continuation lines are aligned with the beginning of
+the statement:
+
+  if a
+  and b then
+      print(1)
+  end"
+  :type 'boolean
+  :safe 'booleanp
+  :group 'lua-ts
+  :version "30.1")
+
 (defvar lua-ts--builtins
   '("assert" "bit32" "collectgarbage" "coroutine" "debug" "dofile"
     "error" "getmetatable" "io" "ipairs" "load" "loadfile"
@@ -329,6 +351,17 @@ values of OVERRIDE."
      ((or (match "end" "function_definition")
           (node-is "end"))
       standalone-parent 0)
+     ((n-p-gp "expression_list" "assignment_statement" "variable_declaration")
+      lua-ts--variable-declaration-continuation-anchor
+      lua-ts-indent-offset)
+     ((and (parent-is "binary_expression")
+           lua-ts--variable-declaration-continuation)
+      lua-ts--variable-declaration-continuation-anchor
+      lua-ts-indent-offset)
+     ((and (lambda (&rest _) lua-ts-indent-continuation-lines)
+           (parent-is "binary_expression"))
+      standalone-parent lua-ts-indent-offset)
+     ((parent-is "binary_expression") standalone-parent 0)
      ((or (parent-is "function_declaration")
           (parent-is "function_definition")
           (parent-is "do_statement")
@@ -415,6 +448,22 @@ values of OVERRIDE."
          (treesit-induce-sparse-tree parent #'lua-ts--function-definition-p)))
     (= 1 (length (cadr sparse-tree)))))
 
+(defun lua-ts--variable-declaration-continuation (node &rest _)
+  "Matches if NODE is part of a multi-line variable declaration."
+  (treesit-parent-until node
+                        (lambda (p)
+                          (equal "variable_declaration"
+                                 (treesit-node-type p)))))
+
+(defun lua-ts--variable-declaration-continuation-anchor (node &rest _)
+  "Return the start position of the variable declaration for NODE."
+  (save-excursion
+    (goto-char (treesit-node-start
+                (lua-ts--variable-declaration-continuation node)))
+    (when (looking-back (rx bol (* whitespace))
+                        (line-beginning-position))
+      (point))))
+
 (defvar lua-ts--syntax-table
   (let ((table (make-syntax-table)))
     (modify-syntax-entry ?+  "."    table)
@@ -552,7 +601,6 @@ Calls REPORT-FN directly."
     (with-current-buffer lua-ts-inferior-buffer
       (setq-local comint-input-ignoredups t
                   comint-input-ring-file-name lua-ts-inferior-history
-                  comint-use-prompt-regexp t
                   comint-prompt-read-only t
                   comint-prompt-regexp (rx-to-string `(: bol
                                                          
,lua-ts-inferior-prompt
@@ -560,9 +608,7 @@ Calls REPORT-FN directly."
       (comint-read-input-ring t)
       (add-hook 'comint-preoutput-filter-functions
                 (lambda (string)
-                  (if (or (not (equal (buffer-name) lua-ts-inferior-buffer))
-                          (equal string
-                                 (concat lua-ts-inferior-prompt-continue " ")))
+                  (if (equal string (concat lua-ts-inferior-prompt-continue " 
"))
                       string
                     (concat
                      ;; Filter out the extra prompt characters that
@@ -576,7 +622,8 @@ Calls REPORT-FN directly."
                                                     (group (* nonl))))
                                                "\\1" string)
                      ;; Re-add the prompt for the next line.
-                     lua-ts-inferior-prompt " "))))))
+                     lua-ts-inferior-prompt " ")))
+                nil t)))
   (select-window (display-buffer lua-ts-inferior-buffer
                                  '((display-buffer-reuse-window
                                     display-buffer-pop-up-frame)
diff --git a/lisp/progmodes/m4-mode.el b/lisp/progmodes/m4-mode.el
index 2291fe60919..ec632ada98c 100644
--- a/lisp/progmodes/m4-mode.el
+++ b/lisp/progmodes/m4-mode.el
@@ -1,6 +1,6 @@
 ;;; m4-mode.el --- m4 code editing commands for Emacs  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1996-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrew Csillag <drew@thecsillags.com>
 ;; Keywords: languages, faces
diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el
index 37e4c439dca..be5884604da 100644
--- a/lisp/progmodes/make-mode.el
+++ b/lisp/progmodes/make-mode.el
@@ -1,6 +1,6 @@
 ;;; make-mode.el --- makefile editing commands for Emacs -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: Thomas Neumann <tom@smart.bo.open.de>
 ;;     Eric S. Raymond <esr@thyrsus.com>
diff --git a/lisp/progmodes/meta-mode.el b/lisp/progmodes/meta-mode.el
index eb83be3e317..6b34997799f 100644
--- a/lisp/progmodes/meta-mode.el
+++ b/lisp/progmodes/meta-mode.el
@@ -1,6 +1,6 @@
 ;;; meta-mode.el --- major mode for editing Metafont or MetaPost sources -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Ulrik Vieth <vieth@thphy.uni-duesseldorf.de>
 ;; Version: 1.0
diff --git a/lisp/progmodes/mixal-mode.el b/lisp/progmodes/mixal-mode.el
index ecf29ddffaf..7dd233479f0 100644
--- a/lisp/progmodes/mixal-mode.el
+++ b/lisp/progmodes/mixal-mode.el
@@ -1,6 +1,6 @@
 ;;; mixal-mode.el --- Major mode for the mix asm language.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Pieter E.J. Pareit <pieter.pareit@gmail.com>
 ;; Maintainer: Jose A Ortega Ruiz <jao@gnu.org>
diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el
index 6fd59ed3f93..cc47880bcbb 100644
--- a/lisp/progmodes/octave.el
+++ b/lisp/progmodes/octave.el
@@ -1,6 +1,6 @@
 ;;; octave.el --- editing octave source files under emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
 ;;        John Eaton <jwe@octave.org>
diff --git a/lisp/progmodes/opascal.el b/lisp/progmodes/opascal.el
index 0c503ab0fab..5e8263cb646 100644
--- a/lisp/progmodes/opascal.el
+++ b/lisp/progmodes/opascal.el
@@ -1,6 +1,6 @@
 ;;; opascal.el --- major mode for editing Object Pascal source in Emacs  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1998-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Authors: Ray Blaak <blaak@infomatch.com>,
 ;;          Simon South <ssouth@member.fsf.org>
diff --git a/lisp/progmodes/pascal.el b/lisp/progmodes/pascal.el
index 0c73ea086a4..bd39b64aefc 100644
--- a/lisp/progmodes/pascal.el
+++ b/lisp/progmodes/pascal.el
@@ -1,6 +1,6 @@
 ;;; pascal.el --- major mode for editing pascal source in Emacs -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
 ;; Author: Espen Skoglund <esk@gnu.org>
 ;; Keywords: languages
diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el
index b8d811baf0d..f74390841fe 100644
--- a/lisp/progmodes/perl-mode.el
+++ b/lisp/progmodes/perl-mode.el
@@ -1,6 +1,6 @@
 ;;; perl-mode.el --- Perl code editing commands for GNU Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1990, 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990, 1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: William F. Mann
 ;; Maintainer: emacs-devel@gnu.org
@@ -468,7 +468,7 @@
                      (scan-error (goto-char startpos) nil))
                  (not (or (nth 8 (parse-partial-sexp
                                   ;; Since we don't know if point is within
-                                  ;; the first or the scond arg, we have to
+                                  ;; the first or the second arg, we have to
                                   ;; start from the beginning.
                                   (if twoargs (1+ (nth 8 state)) (point))
                                   limit nil nil state 'syntax-table))
@@ -514,7 +514,7 @@
                                     (string-to-syntax "|e")
                                   (string-to-syntax "\"e")))
              (forward-char 1)
-             ;; Re-use perl-syntax-propertize-special-constructs to handle the
+             ;; Reuse perl-syntax-propertize-special-constructs to handle the
              ;; second part (the first delimiter of second part can't be
              ;; preceded by "s" or "tr" or "y", so it will not be considered
              ;; as twoarg).
diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index 37c54a90f42..d4e0514a6c3 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -1,6 +1,6 @@
 ;;; prog-mode.el --- Generic major mode for programming  -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index a81bb63fba4..da782ad5537 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1,6 +1,6 @@
 ;;; project.el --- Operations on the current project  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 ;; Version: 0.10.0
 ;; Package-Requires: ((emacs "26.1") (xref "1.4.0"))
 
@@ -1110,10 +1110,9 @@ This has the effect of sharing more history between 
projects."
 
 (defun project--transplant-file-name (filename project)
   (when-let ((old-root (get-text-property 0 'project filename)))
-    (abbreviate-file-name
-     (expand-file-name
-      (file-relative-name filename old-root)
-      (project-root project)))))
+    (expand-file-name
+     (file-relative-name filename old-root)
+     (project-root project))))
 
 (defun project--read-file-cpd-relative (prompt
                                         all-files &optional predicate
@@ -1146,15 +1145,17 @@ by the user at will."
          (_ (when included-cpd
               (setq substrings (cons "./" substrings))))
          (new-collection (project--file-completion-table substrings))
-         (abbr-cpd (abbreviate-file-name common-parent-directory))
-         (abbr-cpd-length (length abbr-cpd))
-         (relname (cl-letf (((symbol-value hist)
-                             (mapcan
-                              (lambda (s)
-                                (and (string-prefix-p abbr-cpd s)
-                                     (not (eq abbr-cpd-length (length s)))
-                                     (list (substring s abbr-cpd-length))))
-                              (symbol-value hist))))
+         (abs-cpd (expand-file-name common-parent-directory))
+         (abs-cpd-length (length abs-cpd))
+         (relname (cl-letf* ((non-essential t) ;Avoid new Tramp connections.
+                             ((symbol-value hist)
+                              (mapcan
+                               (lambda (s)
+                                 (setq s (expand-file-name s))
+                                 (and (string-prefix-p abs-cpd s)
+                                      (not (eq abs-cpd-length (length s)))
+                                      (list (substring s abs-cpd-length))))
+                               (symbol-value hist))))
                     (project--completing-read-strict prompt
                                                      new-collection
                                                      predicate
@@ -1362,6 +1363,7 @@ If you exit the `query-replace', you can later continue 
the
 
 (defvar compilation-read-command)
 (declare-function compilation-read-command "compile")
+(declare-function recompile "compile")
 
 (defun project-prefixed-buffer-name (mode)
   (concat "*"
@@ -1395,6 +1397,18 @@ If non-nil, it overrides 
`compilation-buffer-name-function' for
              compilation-buffer-name-function)))
     (call-interactively #'compile)))
 
+(defun project-recompile (&optional edit-command)
+  "Run `recompile' with appropriate buffer."
+  (declare (interactive-only recompile))
+  (interactive "P")
+  (let ((compilation-buffer-name-function
+         (or project-compilation-buffer-name-function
+             ;; Should we error instead?  When there's no
+             ;; project-specific naming, there is no point in using
+             ;; this command.
+             compilation-buffer-name-function)))
+    (recompile edit-command)))
+
 (defcustom project-ignore-buffer-conditions nil
   "List of conditions to filter the buffers to be switched to.
 If any of these conditions are satisfied for a buffer in the
@@ -1693,7 +1707,10 @@ With some possible metadata (to be decided).")
                  (let ((name (car elem)))
                    (list (if (file-remote-p name) name
                            (abbreviate-file-name name)))))
-               (read (current-buffer))))))
+               (condition-case nil
+                   (read (current-buffer))
+                 (end-of-file
+                  (warn "Failed to read the projects list file due to 
unexpected EOF")))))))
     (unless (seq-every-p
              (lambda (elt) (stringp (car-safe elt)))
              project--list)
@@ -1841,10 +1858,12 @@ It's also possible to enter an arbitrary directory not 
in the list."
 ;;;###autoload
 (defun project-any-command (&optional overriding-map prompt-format)
   "Run the next command in the current project.
-If the command is in `project-prefix-map', it gets passed that
-info with `project-current-directory-override'.  Otherwise,
-`default-directory' is temporarily set to the current project's
-root.
+
+If the command name starts with `project-', or its symbol has
+property `project-aware', it gets passed the project to use
+with the variable `project-current-directory-override'.
+Otherwise, `default-directory' is temporarily set to the current
+project's root.
 
 If OVERRIDING-MAP is non-nil, it will be used as
 `overriding-local-map' to provide shorter bindings from that map
@@ -1856,15 +1875,11 @@ which will take priority over the global ones."
                     (key-binding (read-key-sequence
                                   (format prompt-format (project-root pr)))
                                  t)))
-         (root (project-root pr))
-         found)
+         (root (project-root pr)))
     (when command
-      ;; We could also check the command name against "\\`project-",
-      ;; and/or (get command 'project-command).
-      (map-keymap
-       (lambda (_evt cmd) (if (eq cmd command) (setq found t)))
-       project-prefix-map)
-      (if found
+      (if (when (symbolp command)
+            (or (string-prefix-p "project-" (symbol-name command))
+                (get command 'project-aware)))
           (let ((project-current-directory-override root))
             (call-interactively command))
         (let ((default-directory root))
diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el
index 66dea8803b3..97f08a79ccd 100644
--- a/lisp/progmodes/prolog.el
+++ b/lisp/progmodes/prolog.el
@@ -1,6 +1,6 @@
 ;;; prolog.el --- major mode for Prolog (and Mercury) -*- lexical-binding:t -*-
 
-;; Copyright (C) 1986-1987, 1997-1999, 2002-2003, 2011-2023 Free
+;; Copyright (C) 1986-1987, 1997-1999, 2002-2003, 2011-2024 Free
 ;; Software Foundation, Inc.
 
 ;; Authors: Emil Åström <emil_astrom(at)hotmail(dot)com>
@@ -1148,7 +1148,7 @@ line and comments can also be enclosed in /* ... */.
 If an optional argument SYSTEM is non-nil, set up mode for the given system.
 
 To find out what version of Prolog mode you are running, enter
-`\\[prolog-mode-version]'.
+\\[prolog-mode-version].
 
 Commands:
 \\{prolog-mode-map}"
@@ -1268,7 +1268,7 @@ imitating normal Unix input editing.
 \\[comint-quit-subjob] sends quit signal, likewise.
 
 To find out what version of Prolog mode you are running, enter
-`\\[prolog-mode-version]'."
+\\[prolog-mode-version]."
   (require 'compile)
   (setq comint-input-filter 'prolog-input-filter)
   (setq mode-line-process '(": %s"))
diff --git a/lisp/progmodes/ps-mode.el b/lisp/progmodes/ps-mode.el
index 01a075d6512..7fa6d9dca8c 100644
--- a/lisp/progmodes/ps-mode.el
+++ b/lisp/progmodes/ps-mode.el
@@ -1,6 +1,6 @@
 ;;; ps-mode.el --- PostScript mode for GNU Emacs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author:     Peter Kleiweg <p.c.j.kleiweg@rug.nl>
 ;; Created:    20 Aug 1997
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index ab3bf1b4ec0..9d840efb9da 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1,6 +1,6 @@
 ;;; python.el --- Python's flying circus support for Emacs -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Fabián E. Gallina <fgallina@gnu.org>
 ;; URL: https://github.com/fgallina/python.el
@@ -909,6 +909,7 @@ is used to limit the scan."
   "Put `syntax-table' property correctly on single/triple quotes."
   (let* ((ppss (save-excursion (backward-char 3) (syntax-ppss)))
          (string-start (and (eq t (nth 3 ppss)) (nth 8 ppss)))
+         (string-literal-concat (numberp (nth 3 ppss)))
          (quote-starting-pos (- (point) 3))
          (quote-ending-pos (point)))
     (cond ((or (nth 4 ppss)             ;Inside a comment
@@ -921,6 +922,8 @@ is used to limit the scan."
           ((nth 5 ppss)
            ;; The first quote is escaped, so it's not part of a triple quote!
            (goto-char (1+ quote-starting-pos)))
+          ;; Handle string literal concatenation (bug#45897)
+          (string-literal-concat nil)
           ((null string-start)
            ;; This set of quotes delimit the start of a string.  Put
            ;; string fence syntax on last quote. (bug#49518)
@@ -979,19 +982,30 @@ It makes underscores and dots word constituent chars.")
     "raise" "return" "try" "while" "with" "yield"
     ;; These are technically operators, but we fontify them as
     ;; keywords.
-    "and" "in" "is" "not" "or" "not in"))
+    "and" "in" "is" "not" "or" "not in" "is not"))
+
+(defvar python--treesit-builtin-types
+  '("int" "float" "complex" "bool" "list" "tuple" "range" "str"
+    "bytes" "bytearray" "memoryview" "set" "frozenset" "dict"))
+
+(defvar python--treesit-type-regex
+  (rx-to-string `(seq bol (or
+                           ,@python--treesit-builtin-types
+                           (seq (?  "_") (any "A-Z") (+ (any "a-zA-Z_0-9"))))
+                  eol)))
 
 (defvar python--treesit-builtins
-  '("abs" "all" "any" "ascii" "bin" "bool" "breakpoint" "bytearray"
-    "bytes" "callable" "chr" "classmethod" "compile" "complex"
-    "delattr" "dict" "dir" "divmod" "enumerate" "eval" "exec"
-    "filter" "float" "format" "frozenset" "getattr" "globals"
-    "hasattr" "hash" "help" "hex" "id" "input" "int" "isinstance"
-    "issubclass" "iter" "len" "list" "locals" "map" "max"
-    "memoryview" "min" "next" "object" "oct" "open" "ord" "pow"
-    "print" "property" "range" "repr" "reversed" "round" "set"
-    "setattr" "slice" "sorted" "staticmethod" "str" "sum" "super"
-    "tuple" "type" "vars" "zip" "__import__"))
+  (append python--treesit-builtin-types
+          '("abs" "all" "any" "ascii" "bin" "breakpoint"
+            "callable" "chr" "classmethod" "compile"
+            "delattr" "dir" "divmod" "enumerate" "eval" "exec"
+            "filter" "format" "getattr" "globals"
+            "hasattr" "hash" "help" "hex" "id" "input" "isinstance"
+            "issubclass" "iter" "len" "locals" "map" "max"
+            "min" "next" "object" "oct" "open" "ord" "pow"
+            "print" "property" "repr" "reversed" "round"
+            "setattr" "slice" "sorted" "staticmethod" "sum" "super"
+            "type" "vars" "zip" "__import__")))
 
 (defvar python--treesit-constants
   '("Ellipsis" "False" "None" "NotImplemented" "True" "__debug__"
@@ -1042,9 +1056,7 @@ NODE is the string node.  Do not fontify the initial f for
 f-strings.  OVERRIDE is the override flag described in
 `treesit-font-lock-rules'.  START and END mark the region to be
 fontified."
-  (let* ((string-beg (treesit-node-start node))
-         (string-end (treesit-node-end node))
-         (maybe-expression (treesit-node-parent node))
+  (let* ((maybe-expression (treesit-node-parent node))
          (grandparent (treesit-node-parent
                        (treesit-node-parent
                         maybe-expression)))
@@ -1072,28 +1084,92 @@ fontified."
                         (equal (treesit-node-type maybe-expression)
                                "expression_statement"))
                    'font-lock-doc-face
-                 'font-lock-string-face)))
-    ;; Don't highlight string prefixes like f/r/b.
-    (save-excursion
-      (goto-char string-beg)
-      (when (re-search-forward "[\"']" string-end t)
-        (setq string-beg (match-beginning 0))))
-    (treesit-fontify-with-override
-     string-beg string-end face override start end)))
-
-(defun python--treesit-fontify-string-interpolation
-    (node _ start end &rest _)
-  "Fontify string interpolation.
-NODE is the string node.  Do not fontify the initial f for
-f-strings.  START and END mark the region to be
+                 'font-lock-string-face))
+
+         (ignore-interpolation (not
+                                (seq-some
+                                 (lambda (feats) (memq 'string-interpolation 
feats))
+                                 (seq-take treesit-font-lock-feature-list 
treesit-font-lock-level))))
+         ;; If interpolation is enabled, highlight only
+         ;; string_start/string_content/string_end children.  Do not
+         ;; touch interpolation node that can occur inside of the
+         ;; string.
+         (string-nodes (if ignore-interpolation
+                           (list node)
+                         (treesit-filter-child
+                          node
+                          (lambda (ch) (member (treesit-node-type ch)
+                                               '("string_start"
+                                                 "string_content"
+                                                 "string_end")))
+                          t))))
+
+    (dolist (string-node string-nodes)
+      (let ((string-beg (treesit-node-start string-node))
+            (string-end (treesit-node-end string-node)))
+        (when (or ignore-interpolation
+                  (equal (treesit-node-type string-node) "string_start"))
+          ;; Don't highlight string prefixes like f/r/b.
+          (save-excursion
+            (goto-char string-beg)
+            (when (re-search-forward "[\"']" string-end t)
+              (setq string-beg (match-beginning 0)))))
+
+        (treesit-fontify-with-override
+         string-beg string-end face override start end)))))
+
+(defun python--treesit-fontify-union-types (node override start end &optional 
type-regex &rest _)
+  "Fontify nested union types in the type hints.
+For example, Lvl1 | Lvl2[Lvl3[Lvl4[Lvl5 | None]], Lvl2].  This
+structure is represented via nesting binary_operator and
+subscript nodes.  This function iterates over all levels and
+highlight identifier nodes. If TYPE-REGEX is not nil fontify type
+identifier only if it matches against TYPE-REGEX. NODE is the
+binary_operator node.  OVERRIDE is the override flag described in
+`treesit-font-lock-rules'.  START and END mark the region to be
+fontified."
+  (dolist (child (treesit-node-children node t))
+    (let (font-node)
+      (pcase (treesit-node-type child)
+        ((or "identifier" "none")
+         (setq font-node child))
+        ("attribute"
+         (when-let ((type-node (treesit-node-child-by-field-name child 
"attribute")))
+           (setq font-node type-node)))
+        ((or "binary_operator" "subscript")
+         (python--treesit-fontify-union-types child override start end 
type-regex)))
+
+      (when (and font-node
+                 (or (null type-regex)
+                     (let ((case-fold-search nil))
+                       (string-match-p type-regex (treesit-node-text 
font-node)))))
+        (treesit-fontify-with-override
+         (treesit-node-start font-node) (treesit-node-end font-node)
+         'font-lock-type-face override start end)))))
+
+(defun python--treesit-fontify-union-types-strict (node override start end 
&rest _)
+  "Fontify nested union types.
+Same as `python--treesit-fontify-union-types' but type identifier
+should match against `python--treesit-type-regex'.  For NODE,
+OVERRIDE, START and END description see
+`python--treesit-fontify-union-types'."
+  (python--treesit-fontify-union-types node override start end 
python--treesit-type-regex))
+
+(defun python--treesit-fontify-dotted-decorator (node override start end &rest 
_)
+  "Fontify dotted decorators.
+For example @pytes.mark.skip.  Iterate over all nested attribute
+nodes and highlight identifier nodes.  NODE is the first attribute
+node.  OVERRIDE is the override flag described in
+`treesit-font-lock-rules'.  START and END mark the region to be
 fontified."
-  ;; This is kind of a hack, it basically removes the face applied by
-  ;; the string feature, so that following features can apply their
-  ;; face.
-  (let ((n-start (treesit-node-start node))
-        (n-end (treesit-node-end node)))
-    (remove-text-properties
-     (max start n-start) (min end n-end) '(face))))
+  (dolist (child (treesit-node-children node t))
+    (pcase (treesit-node-type child)
+      ("identifier"
+       (treesit-fontify-with-override
+        (treesit-node-start child) (treesit-node-end child)
+        'font-lock-type-face override start end))
+      ("attribute"
+       (python--treesit-fontify-dotted-decorator child override start end)))))
 
 (defvar python--treesit-settings
   (treesit-font-lock-rules
@@ -1103,14 +1179,9 @@ fontified."
 
    :feature 'string
    :language 'python
-   '((string) @python--treesit-fontify-string)
+   '((string) @python--treesit-fontify-string
+     (interpolation ["{" "}"] @font-lock-misc-punctuation-face))
 
-   ;; HACK: This feature must come after the string feature and before
-   ;; other features.  Maybe we should make string-interpolation an
-   ;; option rather than a feature.
-   :feature 'string-interpolation
-   :language 'python
-   '((interpolation) @python--treesit-fontify-string-interpolation)
 
    :feature 'keyword
    :language 'python
@@ -1124,13 +1195,8 @@ fontified."
       name: (identifier) @font-lock-function-name-face)
      (class_definition
       name: (identifier) @font-lock-type-face)
-     (parameters (identifier) @font-lock-variable-name-face))
-
-   :feature 'function
-   :language 'python
-   '((call function: (identifier) @font-lock-function-call-face)
-     (call function: (attribute
-                      attribute: (identifier) @font-lock-function-call-face)))
+     (parameters (identifier) @font-lock-variable-name-face)
+     (parameters (default_parameter name: (identifier) 
@font-lock-variable-name-face)))
 
    :feature 'builtin
    :language 'python
@@ -1142,6 +1208,19 @@ fontified."
                       eol))
               @font-lock-builtin-face)))
 
+   :feature 'decorator
+   :language 'python
+   '((decorator "@" @font-lock-type-face)
+     (decorator (call function: (identifier) @font-lock-type-face))
+     (decorator (identifier) @font-lock-type-face)
+     (decorator [(attribute) (call (attribute))] 
@python--treesit-fontify-dotted-decorator))
+
+   :feature 'function
+   :language 'python
+   '((call function: (identifier) @font-lock-function-call-face)
+     (call function: (attribute
+                      attribute: (identifier) @font-lock-function-call-face)))
+
    :feature 'constant
    :language 'python
    '([(true) (false) (none)] @font-lock-constant-face)
@@ -1153,30 +1232,71 @@ fontified."
                  @font-lock-variable-name-face)
      (assignment left: (attribute
                         attribute: (identifier)
-                        @font-lock-property-use-face))
-     (pattern_list (identifier)
+                        @font-lock-variable-name-face))
+     (augmented_assignment left: (identifier)
+                           @font-lock-variable-name-face)
+     (named_expression name: (identifier)
+                       @font-lock-variable-name-face)
+     (pattern_list [(identifier)
+                    (list_splat_pattern (identifier))]
                    @font-lock-variable-name-face)
-     (tuple_pattern (identifier)
+     (tuple_pattern [(identifier)
+                     (list_splat_pattern (identifier))]
                     @font-lock-variable-name-face)
-     (list_pattern (identifier)
-                   @font-lock-variable-name-face)
-     (list_splat_pattern (identifier)
-                         @font-lock-variable-name-face))
+     (list_pattern [(identifier)
+                    (list_splat_pattern (identifier))]
+                   @font-lock-variable-name-face))
 
-   :feature 'decorator
-   :language 'python
-   '((decorator "@" @font-lock-type-face)
-     (decorator (call function: (identifier) @font-lock-type-face))
-     (decorator (identifier) @font-lock-type-face))
 
    :feature 'type
    :language 'python
+   ;; Override built-in faces when dict/list are used for type hints.
+   :override t
    `(((identifier) @font-lock-type-face
       (:match ,(rx-to-string
                 `(seq bol (or ,@python--treesit-exceptions)
-                      eol))
+                  eol))
               @font-lock-type-face))
-     (type (identifier) @font-lock-type-face))
+     (type [(identifier) (none)] @font-lock-type-face)
+     (type (attribute attribute: (identifier) @font-lock-type-face))
+     ;; We don't want to highlight a package of the type
+     ;; (e.g. pack.ClassName).  So explicitly exclude patterns with
+     ;; attribute, since we handle dotted type name in the previous
+     ;; rule.  The following rule handle
+     ;; generic_type/list/tuple/splat_type nodes.
+     (type (_ !attribute [[(identifier) (none)] @font-lock-type-face
+                          (attribute attribute: (identifier) 
@font-lock-type-face) ]))
+     ;; collections.abc.Iterator[T] case.
+     (type (subscript (attribute attribute: (identifier) 
@font-lock-type-face)))
+     ;; Nested optional type hints, e.g. val: Lvl1 | Lvl2[Lvl3[Lvl4]].
+     (type (binary_operator) @python--treesit-fontify-union-types)
+     ;;class Type(Base1, Sequence[T]).
+     (class_definition
+      superclasses:
+      (argument_list [(identifier) @font-lock-type-face
+                      (attribute attribute: (identifier) @font-lock-type-face)
+                      (subscript (identifier) @font-lock-type-face)
+                      (subscript (attribute attribute: (identifier) 
@font-lock-type-face))]))
+
+     ;; Pattern matching: case [str(), pack0.Type0()].  Take only the
+     ;; last identifier.
+     (class_pattern (dotted_name (identifier) @font-lock-type-face :anchor))
+
+     ;; Highlight the second argument as a type in isinstance/issubclass.
+     ((call function: (identifier) @func-name
+            (argument_list :anchor (_)
+                           [(identifier) @font-lock-type-face
+                            (attribute attribute: (identifier) 
@font-lock-type-face)
+                            (tuple (identifier) @font-lock-type-face)
+                            (tuple (attribute attribute: (identifier) 
@font-lock-type-face))]
+                           (:match ,python--treesit-type-regex 
@font-lock-type-face)))
+      (:match "^is\\(?:instance\\|subclass\\)$" @func-name))
+
+     ;; isinstance(t, int|float).
+     ((call function: (identifier) @func-name
+            (argument_list :anchor (_)
+                           (binary_operator) 
@python--treesit-fontify-union-types-strict))
+      (:match "^is\\(?:instance\\|subclass\\)$" @func-name)))
 
    :feature 'escape-sequence
    :language 'python
@@ -1237,6 +1357,21 @@ For NODE, OVERRIDE, START, END, and ARGS, see
      (treesit-node-start node) (treesit-node-end node)
      'font-lock-variable-use-face override start end)))
 
+(defun python--treesit-syntax-propertize (start end)
+  "Propertize triple-quote strings between START and END."
+  (save-excursion
+    (goto-char start)
+    (while (re-search-forward (rx (or "\"\"\"" "'''")) end t)
+      (let ((node (treesit-node-at (- (point) 3))))
+        ;; Handle triple-quoted strings.
+        (pcase (treesit-node-type node)
+          ("string_start"
+           (put-text-property (1- (point)) (point)
+                              'syntax-table (string-to-syntax "|")))
+          ("string_end"
+           (put-text-property (- (point) 3) (- (point) 2)
+                              'syntax-table (string-to-syntax "|"))))))))
+
 
 ;;; Indentation
 
@@ -6128,7 +6263,9 @@ point's current `syntax-ppss'."
                 counter)))
         (python-util-forward-comment -1)
         (python-nav-beginning-of-statement)
-        (cond ((bobp))
+        (cond ((and (bobp) (save-excursion
+                             (python-util-forward-comment)
+                             (looking-at-p re))))
               ((python-info-assignment-statement-p) t)
               ((python-info-looking-at-beginning-of-defun))
               (t nil))))))
@@ -6853,6 +6990,8 @@ implementations: `python-mode' and `python-ts-mode'."
                 #'python--treesit-defun-name)
     (treesit-major-mode-setup)
 
+    (setq-local syntax-propertize-function #'python--treesit-syntax-propertize)
+
     (python-skeleton-add-menu-items)
 
     (when python-indent-guess-indent-offset
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 5c34ddc562b..999fbebfb08 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -1,6 +1,6 @@
 ;;; ruby-mode.el --- Major mode for editing Ruby files -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Authors: Yukihiro Matsumoto
 ;;     Nobuyoshi Nakada
@@ -2106,12 +2106,6 @@ or `gem' statement around point."
     "\\(%\\)[qQrswWxIi]?\\([[:punct:]]\\)"
     "Regexp to match the beginning of percent literal.")
 
-  (defconst ruby-syntax-methods-before-regexp
-    '("gsub" "gsub!" "sub" "sub!" "scan" "split" "split!" "index" "match"
-      "assert_match" "Given" "Then" "When")
-    "Methods that can take regexp as the first argument.
-It will be properly highlighted even when the call omits parens.")
-
   (defvar ruby-syntax-before-regexp-re
     (concat
      ;; Special tokens that can't be followed by a division operator.
@@ -2123,11 +2117,9 @@ It will be properly highlighted even when the call omits 
parens.")
      "\\|\\(?:^\\|\\s \\)"
      (regexp-opt '("if" "elsif" "unless" "while" "until" "when" "and"
                    "or" "not" "&&" "||"))
-     ;; Method name from the list.
-     "\\|\\_<"
-     (regexp-opt ruby-syntax-methods-before-regexp)
      "\\)\\s *")
-    "Regexp to match text that can be followed by a regular expression."))
+    "Regexp to match text that disambiguates a regular expression.
+A slash character after any of these should begin a regexp."))
 
 (defun ruby-syntax-propertize (start end)
   "Syntactic keywords for Ruby mode.  See `syntax-propertize-function'."
@@ -2187,10 +2179,14 @@ It will be properly highlighted even when the call 
omits parens.")
             (when (or
                    ;; Beginning of a regexp.
                    (and (null (nth 8 state))
-                        (save-excursion
-                          (forward-char -1)
-                          (looking-back ruby-syntax-before-regexp-re
-                                        (line-beginning-position))))
+                        (or (not
+                             ;; Looks like division.
+                             (or (eql (char-after) ?\s)
+                                 (not (eql (char-before (1- (point))) ?\s))))
+                            (save-excursion
+                              (forward-char -1)
+                              (looking-back ruby-syntax-before-regexp-re
+                                            (line-beginning-position)))))
                    ;; End of regexp.  We don't match the whole
                    ;; regexp at once because it can have
                    ;; string interpolation inside, or span
diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el
index b339e2028ab..598eaa461ff 100644
--- a/lisp/progmodes/ruby-ts-mode.el
+++ b/lisp/progmodes/ruby-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; ruby-ts-mode.el --- Major mode for editing Ruby files using tree-sitter 
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Perry Smith <pedz@easesoftware.com>
 ;; Created: December 2022
@@ -601,7 +601,7 @@ a statement container is a node that matches
 
            ;; case expression: when, in_clause, and else are all
            ;; children of case.  when and in_clause have pattern and
-           ;; body as fields.  body has "then" and then the statemets.
+           ;; body as fields.  body has "then" and then the statements.
            ;; i.e. the statements are not children of when but then.
            ;; But for the statements are children of else.
            ((match "when" "case")
@@ -753,8 +753,9 @@ a statement container is a node that matches
 
            ((match "}" "hash")  ruby-ts--parent-call-or-bol 0)
            ((parent-is "hash")  ruby-ts--parent-call-or-bol ruby-indent-level)
-           ((match "]" "array") ruby-ts--parent-call-or-bol 0)
-           ((parent-is "array") ruby-ts--parent-call-or-bol ruby-indent-level)
+           ((match "]" "^array") ruby-ts--parent-call-or-bol 0)
+           ((parent-is "^array") ruby-ts--parent-call-or-bol ruby-indent-level)
+           ((match ")" "string_array") ruby-ts--parent-call-or-bol 0)
 
            ((parent-is "pair") ruby-ts--parent-call-or-bol 0)
 
@@ -1063,8 +1064,9 @@ leading double colon is not added."
         ('heredoc
          (put-text-property (treesit-node-start node) (1+ (treesit-node-start 
node))
                             'syntax-table (string-to-syntax "\""))
-         (put-text-property (treesit-node-end node) (1+ (treesit-node-end 
node))
-                            'syntax-table (string-to-syntax "\"")))
+         (when (< (treesit-node-end node) (point-max))
+           (put-text-property (treesit-node-end node) (1+ (treesit-node-end 
node))
+                              'syntax-table (string-to-syntax "\""))))
         ('percent
          ;; FIXME: Put the first one on the first paren in both %Q{} and %().
          ;; That would stop electric-pair-mode from pairing, though.  Hmm.
@@ -1192,21 +1194,9 @@ leading double colon is not added."
 
   (treesit-major-mode-setup)
 
-  (treesit-parser-add-notifier (car (treesit-parser-list))
-                               #'ruby-ts--parser-after-change)
-
   (setq-local syntax-propertize-function #'ruby-ts--syntax-propertize))
 
-(defun ruby-ts--parser-after-change (ranges parser)
-  ;; Make sure we re-syntax-propertize the full node that is being
-  ;; edited.  This is most pertinent to multi-line complex nodes such
-  ;; as heredocs.
-  (when ranges
-    (with-current-buffer (treesit-parser-buffer parser)
-      (syntax-ppss-flush-cache (cl-loop for r in ranges
-                                        minimize (car r))))))
-
-(if (treesit-ready-p 'ruby t)
+(if (treesit-ready-p 'ruby)
     ;; Copied from ruby-mode.el.
     (add-to-list 'auto-mode-alist
                  (cons (concat "\\(?:\\.\\(?:"
diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el
index 03ff2776d3a..c5fc57cc374 100644
--- a/lisp/progmodes/rust-ts-mode.el
+++ b/lisp/progmodes/rust-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; rust-ts-mode.el --- tree-sitter support for Rust  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author     : Randy Taylor <dev@rjt.dev>
 ;; Maintainer : Randy Taylor <dev@rjt.dev>
@@ -296,13 +296,14 @@
 (defun rust-ts-mode--comment-docstring (node override start end &rest _args)
   "Use the comment or documentation face appropriately for comments."
   (let* ((beg (treesit-node-start node))
-         (end (treesit-node-end node))
          (face (save-excursion
                  (goto-char beg)
-                 (if (looking-at "///")
+                 (if (looking-at-p
+                      "/\\(?:/\\(?:/[^/]\\|!\\)\\|\\*\\(?:\\*[^*/]\\|!\\)\\)")
                      'font-lock-doc-face
                    'font-lock-comment-face))))
-    (treesit-fontify-with-override beg end face override start end)))
+    (treesit-fontify-with-override beg (treesit-node-end node)
+                                   face override start end)))
 
 (defun rust-ts-mode--fontify-scope (node override start end &optional tail-p)
   (let* ((case-fold-search nil)
@@ -459,6 +460,10 @@ See `prettify-symbols-compose-predicate'."
     (setq-local indent-tabs-mode nil
                 treesit-simple-indent-rules rust-ts-mode--indent-rules)
 
+    ;; Electric
+    (setq-local electric-indent-chars
+                (append "{}():;,#" electric-indent-chars))
+
     ;; Navigation.
     (setq-local treesit-defun-type-regexp
                 (regexp-opt '("enum_item"
diff --git a/lisp/progmodes/scheme.el b/lisp/progmodes/scheme.el
index e6fcc684729..67abab6913d 100644
--- a/lisp/progmodes/scheme.el
+++ b/lisp/progmodes/scheme.el
@@ -1,6 +1,6 @@
 ;;; scheme.el --- Scheme (and DSSSL) editing mode    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1986-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986-2024 Free Software Foundation, Inc.
 
 ;; Author: Bill Rozas <jinx@martigny.ai.mit.edu>
 ;; Adapted-by: Dave Love <d.love@dl.ac.uk>
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index de76e175a10..43fb8a723bd 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -1,6 +1,7 @@
 ;;; sh-script.el --- shell-script editing commands for Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1997, 1999, 2001-2024 Free Software Foundation,
+;; Inc.
 
 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
 ;; Old-Version: 2.0f
@@ -1053,7 +1054,8 @@ subshells can nest."
                     ;; a normal command rather than the real `in' keyword.
                     ;; I.e. we should look back to try and find the
                     ;; corresponding `case'.
-                    (and (looking-at ";\\(?:;&?\\|[&|]\\)\\|\\_<in")
+                    ;; Also recognize OpenBSD's case X { ... } (bug#55764).
+                    (and (looking-at ";\\(?:;&?\\|[&|]\\)\\|\\_<in\\|.{")
                          ;; ";; esac )" is a case that looks
                          ;; like a case-pattern but it's really just a close
                          ;; paren after a case statement.  I.e. if we skipped
@@ -2056,9 +2058,9 @@ May return nil if the line should not be treated as 
continued."
                              (sh-var-value 'sh-indent-for-case-label)))
     (`(:before . ,(or "(" "{" "[" "while" "if" "for" "case"))
      (cond
-      ((and (equal token "{") (smie-rule-parent-p "for"))
+      ((and (equal token "{") (smie-rule-parent-p "for" "case"))
        (let ((data (smie-backward-sexp "in")))
-         (when (equal (nth 2 data) "for")
+         (when (member (nth 2 data) '("for" "case"))
            `(column . ,(smie-indent-virtual)))))
       ((not (smie-rule-prev-p "&&" "||" "|"))
        (when (smie-rule-hanging-p)
@@ -2302,7 +2304,7 @@ Point should be before the newline."
 When used interactively, insert the proper starting #!-line,
 and make the visited file executable via `executable-set-magic',
 perhaps querying depending on the value of `executable-query'.
-(If given a prefix (i.e., `\\[universal-argument]') don't insert any starting 
#!
+(If given a prefix (i.e., \\[universal-argument]) don't insert any starting #!
 line.)
 
 When this function is called noninteractively, INSERT-FLAG (the third
diff --git a/lisp/progmodes/simula.el b/lisp/progmodes/simula.el
index d3061169981..94b18d32c09 100644
--- a/lisp/progmodes/simula.el
+++ b/lisp/progmodes/simula.el
@@ -1,6 +1,6 @@
 ;;; simula.el --- SIMULA 87 code editing commands for Emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: Hans Henrik Eriksen <hhe@ifi.uio.no>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index 004ae50ef50..604f04a3d57 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -1,6 +1,6 @@
 ;;; sql.el --- specialized comint.el for SQL interpreters  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <alex@gnu.org>
 ;; Maintainer: Michael Mauger <michael@mauger.com>
diff --git a/lisp/progmodes/subword.el b/lisp/progmodes/subword.el
index 18ccdd0e66e..52b2cd07cdd 100644
--- a/lisp/progmodes/subword.el
+++ b/lisp/progmodes/subword.el
@@ -1,6 +1,6 @@
 ;;; subword.el --- Handling capitalized subwords in a nomenclature -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Masatake YAMATO
 
diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el
index b983c671cd9..dc11f456cd0 100644
--- a/lisp/progmodes/tcl.el
+++ b/lisp/progmodes/tcl.el
@@ -1,6 +1,6 @@
 ;;; tcl.el --- Tcl code editing commands for Emacs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1994, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Tom Tromey <tromey@redhat.com>
 ;;    Chris Lindblad <cjl@lcs.mit.edu>
diff --git a/lisp/progmodes/typescript-ts-mode.el 
b/lisp/progmodes/typescript-ts-mode.el
index 7998b3740b6..e9c6afff440 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; typescript-ts-mode.el --- tree sitter support for TypeScript  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author     : Theodor Thornhill <theo@thornhill.no>
 ;; Maintainer : Theodor Thornhill <theo@thornhill.no>
@@ -205,7 +205,7 @@ Argument LANGUAGE is either `typescript' or `tsx'."
   (treesit-font-lock-rules
    :language language
    :feature 'comment
-   `((comment) @font-lock-comment-face)
+   `([(comment) (hash_bang_line)] @font-lock-comment-face)
 
    :language language
    :feature 'constant
diff --git a/lisp/progmodes/vera-mode.el b/lisp/progmodes/vera-mode.el
index d4f8f71b789..184cce66ae4 100644
--- a/lisp/progmodes/vera-mode.el
+++ b/lisp/progmodes/vera-mode.el
@@ -1,6 +1,6 @@
 ;;; vera-mode.el --- major mode for editing Vera files  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author:      Reto Zimmermann <reto@gnu.org>
 ;; Version:     2.28
diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el
index 2eec4bcd21a..6081372af33 100644
--- a/lisp/progmodes/verilog-mode.el
+++ b/lisp/progmodes/verilog-mode.el
@@ -1,6 +1,6 @@
 ;;; verilog-mode.el --- major mode for editing verilog source in Emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael McNamara <mac@verilog.com>
 ;;    Wilson Snyder <wsnyder@wsnyder.org>
diff --git a/lisp/progmodes/vhdl-mode.el b/lisp/progmodes/vhdl-mode.el
index b55fae3374a..f52baf049aa 100644
--- a/lisp/progmodes/vhdl-mode.el
+++ b/lisp/progmodes/vhdl-mode.el
@@ -1,6 +1,6 @@
 ;;; vhdl-mode.el --- major mode for editing VHDL code  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Authors:     Reto Zimmermann <reto@gnu.org>
 ;;              Rodney J. Whitby <software.vhdl-mode@rwhitby.net>
@@ -457,7 +457,7 @@ If no file name at all is printed out, set both \"File 
Message\" entries to 0
 \(a default file name message will be printed out instead, does not work in
 XEmacs).
 
-A compiler is selected for syntax analysis (`\\[vhdl-compile]') by
+A compiler is selected for syntax analysis (\\[vhdl-compile]) by
 assigning its name to option `vhdl-compiler'.
 
 Please send any missing or erroneous compiler properties to the maintainer for
@@ -1106,14 +1106,14 @@ For more information on format strings, see the 
documentation for the
 (defcustom vhdl-modify-date-prefix-string "-- Last update: "
   "Prefix string of modification date in VHDL file header.
 If actualization of the modification date is called (menu,
-`\\[vhdl-template-modify]'), this string is searched and the rest
+\\[vhdl-template-modify]), this string is searched and the rest
 of the line replaced by the current date."
   :type 'string
   :group 'vhdl-header)
 
 (defcustom vhdl-modify-date-on-saving t
   "Non-nil means update the modification date when the buffer is saved.
-Calls function `\\[vhdl-template-modify]').
+Calls function \\[vhdl-template-modify]).
 
 NOTE: Activate the new setting in a VHDL buffer by using the menu entry
       \"Activate Options\"."
@@ -4469,7 +4469,7 @@ Usage:
     according to option `vhdl-argument-list-indent'.
 
       If option `vhdl-indent-tabs-mode' is nil, spaces are used instead of
-    tabs.  `\\[tabify]' and `\\[untabify]' allow the conversion of spaces to
+    tabs.  \\[tabify] and \\[untabify] allow the conversion of spaces to
     tabs and vice versa.
 
       Syntax-based indentation can be very slow in large files.  Option
@@ -4780,7 +4780,7 @@ Usage:
     `vhdl-highlight-translate-off' is non-nil.
 
       For documentation and customization of the used colors see
-    customization group `vhdl-highlight-faces' (`\\[customize-group]').  For
+    customization group `vhdl-highlight-faces' (\\[customize-group]).  For
     highlighting of matching parenthesis, see customization group
     `paren-showing'.  Automatic buffer highlighting is turned on/off by
     option `global-font-lock-mode' (`font-lock-auto-fontify' in XEmacs).
@@ -4840,14 +4840,14 @@ Usage:
     sessions using the \"Save Options\" menu entry.
 
       Options and their detailed descriptions can also be accessed by using
-    the \"Customize\" menu entry or the command `\\[customize-option]'
-    (`\\[customize-group]' for groups).  Some customizations only take effect
+    the \"Customize\" menu entry or the command \\[customize-option]
+    (\\[customize-group] for groups).  Some customizations only take effect
     after some action (read the NOTE in the option documentation).
     Customization can also be done globally (i.e. site-wide, read the
     INSTALL file).
 
       Not all options are described in this documentation, so go and see
-    what other useful user options there are (`\\[vhdl-customize]' or menu)!
+    what other useful user options there are (\\[vhdl-customize] or menu)!
 
 
   FILE EXTENSIONS:
@@ -4876,7 +4876,7 @@ Usage:
 Maintenance:
 ------------
 
-To submit a bug report, enter `\\[vhdl-submit-bug-report]' within VHDL Mode.
+To submit a bug report, enter \\[vhdl-submit-bug-report] within VHDL Mode.
 Add a description of the problem and include a reproducible test case.
 
 Questions and enhancement requests can be sent to <reto@gnu.org>.
@@ -14978,9 +14978,9 @@ otherwise use cached data."
   (vhdl-aput 'vhdl-directory-alist directory (list (list directory))))
 
 (defun vhdl-speedbar-insert-hierarchy ( ent-alist-arg conf-alist-arg
-                                        package-alist ent-inst-list depth)
-  "Insert hierarchy of ENT-ALIST-ARG, CONF-ALIST-ARG, and PACKAGE-ALIST."
-  (if (not (or ent-alist-arg conf-alist-arg package-alist))
+                                        pkg-alist ent-inst-list depth)
+  "Insert hierarchy of ENT-ALIST-ARG, CONF-ALIST-ARG, and PKG-ALIST."
+  (if (not (or ent-alist-arg conf-alist-arg pkg-alist))
       (vhdl-speedbar-make-title-line "No VHDL design units!" depth)
     (let ((ent-alist ent-alist-arg)
           (conf-alist conf-alist-arg)
@@ -15010,15 +15010,15 @@ otherwise use cached data."
         'vhdl-speedbar-configuration-face depth)
        (setq conf-alist (cdr conf-alist)))
       ;; insert packages
-      (when package-alist (vhdl-speedbar-make-title-line "Packages:" depth))
-      (while package-alist
-       (setq pack-entry (car package-alist))
+      (when pkg-alist (vhdl-speedbar-make-title-line "Packages:" depth))
+      (while pkg-alist
+       (setq pack-entry (car pkg-alist))
        (vhdl-speedbar-make-pack-line
         (nth 0 pack-entry) (nth 1 pack-entry)
         (cons (nth 2 pack-entry) (nth 3 pack-entry))
         (cons (nth 7 pack-entry) (nth 8 pack-entry))
         depth)
-       (setq package-alist (cdr package-alist))))))
+       (setq pkg-alist (cdr pkg-alist))))))
 
 (declare-function speedbar-line-directory "speedbar" (&optional depth))
 
diff --git a/lisp/progmodes/which-func.el b/lisp/progmodes/which-func.el
index 0e04bab6ea4..bd68672f905 100644
--- a/lisp/progmodes/which-func.el
+++ b/lisp/progmodes/which-func.el
@@ -1,6 +1,6 @@
 ;;; which-func.el --- print current function in mode line  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Alex Rezinsky <alexr@msil.sps.mot.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 81618428bf3..717b837a2e5 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -1,6 +1,6 @@
 ;;; xref.el --- Cross-referencing commands              -*-lexical-binding:t-*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 ;; Version: 1.6.3
 ;; Package-Requires: ((emacs "26.1"))
 
diff --git a/lisp/progmodes/xscheme.el b/lisp/progmodes/xscheme.el
index 402f0fc09b1..598328dddea 100644
--- a/lisp/progmodes/xscheme.el
+++ b/lisp/progmodes/xscheme.el
@@ -1,6 +1,6 @@
 ;;; xscheme.el --- run MIT Scheme under Emacs        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1986-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: languages, lisp
diff --git a/lisp/ps-bdf.el b/lisp/ps-bdf.el
index bdc28f927ab..ee754077009 100644
--- a/lisp/ps-bdf.el
+++ b/lisp/ps-bdf.el
@@ -1,6 +1,6 @@
 ;;; ps-bdf.el --- BDF font file handler for ps-print  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1998-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-1999, 2001-2024 Free Software Foundation, Inc.
 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
 ;;   2008, 2009, 2010, 2011
 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
@@ -11,7 +11,7 @@
 
 ;; Author: Kenichi Handa <handa@gnu.org>
 ;; (according to ack.texi)
-;; Keywords: wp, BDF, font, PostScript
+;; Keywords: text, BDF, font, PostScript
 ;; Package: ps-print
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/ps-mule.el b/lisp/ps-mule.el
index a4784954627..1ea4d8f7097 100644
--- a/lisp/ps-mule.el
+++ b/lisp/ps-mule.el
@@ -1,10 +1,10 @@
 ;;; ps-mule.el --- provide multi-byte character facility to ps-print  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
 ;;     Kenichi Handa <handa@gnu.org> (multi-byte characters)
-;; Keywords: wp, print, PostScript, multibyte, mule
+;; Keywords: text, print, PostScript, multibyte, mule
 ;; Package: ps-print
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/ps-print.el b/lisp/ps-print.el
index aa3037f5273..b73d28280ef 100644
--- a/lisp/ps-print.el
+++ b/lisp/ps-print.el
@@ -1,13 +1,13 @@
 ;;; ps-print.el --- print text from the buffer as PostScript -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
 ;; Author: Jim Thompson (was <thompson@wg2.waii.com>)
 ;;     Jacques Duthen (was <duthen@cegelec-red.fr>)
 ;;     Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
 ;;     Kenichi Handa <handa@gnu.org> (multi-byte characters)
 ;; Maintainer: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, print, PostScript
+;; Keywords: text, print, PostScript
 ;; Old-Version: 7.3.5
 ;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
 
diff --git a/lisp/ps-samp.el b/lisp/ps-samp.el
index d66d1939801..828a9eb5f08 100644
--- a/lisp/ps-samp.el
+++ b/lisp/ps-samp.el
@@ -1,13 +1,13 @@
 ;;; ps-samp.el --- ps-print sample setup code  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Jim Thompson (was <thompson@wg2.waii.com>)
 ;;     Jacques Duthen (was <duthen@cegelec-red.fr>)
 ;;     Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
 ;;     Kenichi Handa <handa@gnu.org> (multi-byte characters)
 ;; Maintainer: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, print, PostScript
+;; Keywords: text, print, PostScript
 ;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
 ;; Package: ps-print
 
diff --git a/lisp/recentf.el b/lisp/recentf.el
index 94ae871763b..2529424b8eb 100644
--- a/lisp/recentf.el
+++ b/lisp/recentf.el
@@ -1,6 +1,6 @@
 ;;; recentf.el --- keep track of recently opened files  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 ;; Created: July 19 1999
@@ -805,25 +805,31 @@ Filenames are relative to the `default-directory'."
 ;;; Rule based menu filters
 ;;
 (defcustom recentf-arrange-rules
-  '(
-    ("Elisp files (%d)" ".\\.el\\'")
-    ("Java files (%d)"  ".\\.java\\'")
-    ("C/C++ files (%d)" "c\\(pp\\)?\\'")
+  `(
+    ("Elisp files (%d)" ,(rx nonl ".el" eos))
+    ("C/C++ files (%d)" ,(rx nonl "."
+                             (or "c" "cc" "cpp" "h" "hpp" "cxx" "hxx")
+                             eos))
+    ("Python files (%d)" ,(rx nonl ".py" eos))
+    ("Java files (%d)" ,(rx nonl ".java" eos))
     )
   "List of rules used by `recentf-arrange-by-rule' to build sub-menus.
+
 A rule is a pair (SUB-MENU-TITLE . MATCHER).  SUB-MENU-TITLE is the
 displayed title of the sub-menu where a `%d' `format' pattern is
 replaced by the number of items in the sub-menu.  MATCHER is a regexp
 or a list of regexps.  Items matching one of the regular expressions in
 MATCHER are added to the corresponding sub-menu.
-SUB-MENU-TITLE can be a function.  It is passed every items that
+
+SUB-MENU-TITLE can be a function.  It is passed every item that
 matched the corresponding MATCHER, and it must return a
 pair (SUB-MENU-TITLE . ITEM).  SUB-MENU-TITLE is a computed sub-menu
 title that can be another function.  ITEM is the received item which
 may have been modified to match another rule."
   :group 'recentf-filters
   :type '(repeat (cons (choice string function)
-                       (repeat regexp))))
+                       (repeat regexp)))
+  :version "30.1")
 
 (defcustom recentf-arrange-by-rule-others "Other files (%d)"
   "Title of the `recentf-arrange-by-rule' sub-menu.
diff --git a/lisp/rect.el b/lisp/rect.el
index 8dc188b1de0..0212dedcb48 100644
--- a/lisp/rect.el
+++ b/lisp/rect.el
@@ -1,6 +1,6 @@
 ;;; rect.el --- rectangle functions for GNU Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1999-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: Didier Verna <didier@didierverna.net>
 ;; Keywords: internal
@@ -212,7 +212,10 @@ The returned value has the form of (WIDTH . HEIGHT)."
       (cons width height))))
 
 (defun delete-rectangle-line (startcol endcol fill)
-  (when (= (move-to-column startcol (if fill t 'coerce)) startcol)
+  ;; We use >= here, not =, for characters that use more than one
+  ;; column on display, when STARTCOL is in the middle of such a
+  ;; character.
+  (when (>= (move-to-column startcol (if fill t 'coerce)) startcol)
     (delete-region (point)
                   (progn (move-to-column endcol 'coerce)
                          (point)))))
@@ -279,7 +282,8 @@ When called from a program the rectangle's corners are 
START and END.
 With a prefix (or a FILL) argument, also fill lines where nothing has
 to be deleted."
   (interactive "*r\nP")
-  (apply-on-rectangle 'delete-rectangle-line start end fill))
+  (let (indent-tabs-mode)
+    (apply-on-rectangle 'delete-rectangle-line start end fill)))
 
 ;;;###autoload
 (defun delete-extract-rectangle (start end &optional fill)
@@ -334,7 +338,8 @@ you can use this command to copy text from a read-only 
buffer.
 even beep.)"
   (interactive "r\nP")
   (condition-case nil
-      (setq killed-rectangle (delete-extract-rectangle start end fill))
+      (let (indent-tabs-mode)
+        (setq killed-rectangle (delete-extract-rectangle start end fill)))
     ((buffer-read-only text-read-only)
      (setq deactivate-mark t)
      (setq killed-rectangle (extract-rectangle start end))
diff --git a/lisp/register.el b/lisp/register.el
index 46ec38821e5..822467a0d72 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -1,6 +1,6 @@
 ;;; register.el --- register commands for Emacs      -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1985, 1993-1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985, 1993-1994, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -96,26 +96,75 @@ of the marked text."
 (defcustom register-preview-delay 1
   "If non-nil, time to wait in seconds before popping up register preview 
window.
 If nil, do not show register previews, unless `help-char' (or a member of
-`help-event-list') is pressed."
+`help-event-list') is pressed.
+
+This variable has no effect when `register-use-preview' is set to any
+value except \\='traditional."
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
-(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
 
 (defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a 
?z))
   "Default keys for setting a new register."
-  :type '(repeat string))
-
-(defcustom register-use-preview t
-  "Always show register preview when non nil."
-  :type 'boolean)
+  :type '(repeat string)
+  :version "30.1")
+
+(defvar register--read-with-preview-function nil
+  "Function to use for reading a register name with preview.
+Two functions are provided, one that provide navigation and highlighting
+of the selected register, filtering of register according to command in
+use, defaults register to use when setting a new register, confirmation
+and notification when you are about to overwrite a register, and generic
+functions to configure how each existing command behaves.  Use the
+function `register-read-with-preview-fancy' for this.  The other
+provided function, `register-read-with-preview-traditional', behaves
+the same as in Emacs 29 and before: no filtering, no navigation,
+and no defaults.")
+
+(defvar register-preview-function nil
+  "Function to format a register for previewing.
+Called with one argument, a cons (NAME . CONTENTS), as found
+in `register-alist'.  The function should return a string, the
+description of the argument.  The function to use is set according
+to the value of `register--read-with-preview-function'.")
+
+(defcustom register-use-preview 'traditional
+  "Whether to show register preview when modifying registers.
+
+When set to `t', show a preview buffer with navigation and
+highlighting.
+When set to \\='insist, behave as with `t', but allow exiting the
+minibuffer by pressing the register name a second time.  E.g.,
+press \"a\" to select register \"a\", then press \"a\" again to
+exit the minibuffer.
+When nil, show a preview buffer without navigation and highlighting, and
+exit the minibuffer immediately after inserting response in minibuffer.
+When set to \\='never, behave as with nil, but with no preview buffer at
+all; the preview buffer is still accessible with `help-char' (C-h).
+When set to \\='traditional (the default), provide a more basic preview
+according to `register-preview-delay'; this preserves the traditional
+behavior of Emacs 29 and before."
+  :type '(choice
+          (const :tag "Use preview" t)
+          (const :tag "Use preview and exit by pressing register name" insist)
+          (const :tag "Use quick preview" nil)
+          (const :tag "Never use preview" never)
+          (const :tag "Basic preview like Emacs-29" traditional))
+  :version "30.1"
+  :set (lambda (var val)
+         (set var val)
+         (setq register--read-with-preview-function
+               (if (eq val 'traditional)
+                   #'register-read-with-preview-traditional
+                 #'register-read-with-preview-fancy))
+         (setq register-preview-function nil)))
 
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
   (alist-get register register-alist))
 
 (defun set-register (register value)
-  "Set contents of Emacs register named REGISTER to VALUE.  Return VALUE.
+  "Set contents of Emacs register named REGISTER to VALUE, return VALUE.
 See the documentation of the variable `register-alist' for possible VALUEs."
   (setf (alist-get register register-alist) value))
 
@@ -128,70 +177,130 @@ See the documentation of the variable `register-alist' 
for possible VALUEs."
         (substring d (match-end 0))
       d)))
 
-(defun register-preview-default (r)
-  "Function that is the default value of the variable 
`register-preview-function'."
+(defun register-preview-default-1 (r)
+  "Function used to format a register for fancy previewing.
+This is used as the value of the variable `register-preview-function'
+when `register-use-preview' is set to t or nil."
   (format "%s: %s\n"
          (propertize (string (car r))
                       'display (single-key-description (car r)))
          (register-describe-oneline (car r))))
 
-(defvar register-preview-function #'register-preview-default
-  "Function to format a register for previewing.
-Called with one argument, a cons (NAME . CONTENTS) as found in 
`register-alist'.
-The function should return a string, the description of the argument.")
+(defun register-preview-default (r)
+  "Function used to format a register for traditional preview.
+This is the default value of the variable `register-preview-function',
+and is used when `register-use-preview' is set to \\='traditional."
+  (format "%s: %s\n"
+         (single-key-description (car r))
+         (register-describe-oneline (car r))))
+
+(cl-defgeneric register--preview-function (read-preview-function)
+  "Return a function to format registers for previewing by 
READ-PREVIEW-FUNCTION.")
+(cl-defmethod register--preview-function ((_read-preview-function
+                                           (eql 
register-read-with-preview-traditional)))
+  #'register-preview-default)
+(cl-defmethod register--preview-function ((_read-preview-function
+                                           (eql 
register-read-with-preview-fancy)))
+  #'register-preview-default-1)
 
 (cl-defstruct register-preview-info
   "Store data for a specific register command.
-TYPES are the types of register supported.
-MSG is the minibuffer message to send when a register is selected.
+TYPES are the supported types of registers.
+MSG is the minibuffer message to show when a register is selected.
 ACT is the type of action the command is doing on register.
-SMATCH accept a boolean value to say if command accept non matching register."
-  types msg act smatch)
+SMATCH accept a boolean value to say if the command accepts non-matching
+registers.
+If NOCONFIRM is non-nil, request confirmation of register name by RET."
+  types msg act smatch noconfirm)
 
 (cl-defgeneric register-command-info (command)
-  "Returns a `register-preview-info' object storing data for COMMAND."
+  "Return a `register-preview-info' object storing data for COMMAND."
   (ignore command))
 (cl-defmethod register-command-info ((_command (eql insert-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Insert register `%s'"
    :act 'insert
-   :smatch t))
+   :smatch t
+   :noconfirm (memq register-use-preview '(nil never))))
 (cl-defmethod register-command-info ((_command (eql jump-to-register)))
   (make-register-preview-info
    :types  '(window frame marker kmacro
              file buffer file-query)
    :msg "Jump to register `%s'"
    :act 'jump
-   :smatch t))
+   :smatch t
+   :noconfirm (memq register-use-preview '(nil never))))
 (cl-defmethod register-command-info ((_command (eql view-register)))
   (make-register-preview-info
    :types '(all)
    :msg "View register `%s'"
    :act 'view
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql append-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Append to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql prepend-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Prepend to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql increment-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Increment register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql copy-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql point-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Point to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql number-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Number to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info
+    ((_command (eql window-configuration-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Window configuration to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql frameset-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Frameset to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql 
copy-rectangle-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy rectangle to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 
 (defun register-preview-forward-line (arg)
   "Move to next or previous line in register preview buffer.
-If ARG is positive goto next line, if negative to previous.
+If ARG is positive, go to next line; if negative, go to previous line.
 Do nothing when defining or executing kmacros."
   ;; Ensure user enter manually key in minibuffer when recording a macro.
   (unless (or defining-kbd-macro executing-kbd-macro
@@ -220,31 +329,31 @@ Do nothing when defining or executing kmacros."
             (insert str)))))))
 
 (defun register-preview-next ()
-  "Goto next line in register preview buffer."
+  "Go to next line in the register preview buffer."
   (interactive)
   (register-preview-forward-line 1))
 
 (defun register-preview-previous ()
-  "Goto previous line in register preview buffer."
+  "Go to previous line in the register preview buffer."
   (interactive)
   (register-preview-forward-line -1))
 
 (defun register-type (register)
   "Return REGISTER type.
-Current register types actually returned are one of:
-- string
-- number
-- marker
-- buffer
-- file
-- file-query
-- window
-- frame
-- kmacro
+Register type that can be returned is one of the following:
+ - string
+ - number
+ - marker
+ - buffer
+ - file
+ - file-query
+ - window
+ - frame
+ - kmacro
 
 One can add new types to a specific command by defining a new `cl-defmethod'
-matching this command. Predicate for type in new `cl-defmethod' should
-satisfy `cl-typep' otherwise the new type should be defined with
+matching that command.  Predicates for type in new `cl-defmethod' should
+satisfy `cl-typep', otherwise the new type should be defined with
 `cl-deftype'."
   ;; Call register--type against the register value.
   (register--type (if (consp (cdr register))
@@ -252,15 +361,15 @@ satisfy `cl-typep' otherwise the new type should be 
defined with
                    (cdr register))))
 
 (cl-defgeneric register--type (regval)
-  "Returns type of register value REGVAL."
+  "Return the type of register value REGVAL."
   (ignore regval))
 
 (cl-defmethod register--type ((_regval string)) 'string)
 (cl-defmethod register--type ((_regval number)) 'number)
 (cl-defmethod register--type ((_regval marker)) 'marker)
-(cl-defmethod register--type ((_regval (eql 'buffer))) 'buffer)
-(cl-defmethod register--type ((_regval (eql 'file))) 'file)
-(cl-defmethod register--type ((_regval (eql 'file-query))) 'file-query)
+(cl-defmethod register--type ((_regval (eql buffer))) 'buffer)
+(cl-defmethod register--type ((_regval (eql file))) 'file)
+(cl-defmethod register--type ((_regval (eql file-query))) 'file-query)
 (cl-defmethod register--type ((_regval window-configuration)) 'window)
 (cl-deftype frame-register () '(satisfies frameset-register-p))
 (cl-defmethod register--type :extra "frame-register" (_regval) 'frame)
@@ -275,19 +384,47 @@ satisfy `cl-typep' otherwise the new type should be 
defined with
              when (memq (register-type register) types)
              collect register)))
 
-(defun register-preview (buffer &optional show-empty types)
-  "Pop up a window showing the registers preview in BUFFER.
-If SHOW-EMPTY is non-nil, show the window even if no registers.
-Argument TYPES (a list) specify the types of register to show, when nil show 
all
-registers, see `register-type' for suitable types.
+(defun register-preview (buffer &optional show-empty)
+  "Pop up a window showing the preview of registers in BUFFER.
+If SHOW-EMPTY is non-nil, show the preview window even if no registers.
+Format of each entry is controlled by the variable 
`register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
+  (when (or show-empty (consp register-alist))
+    (with-current-buffer-window buffer
+        register-preview-display-buffer-alist
+        nil
+      (with-current-buffer standard-output
+        (setq cursor-in-non-selected-windows nil)
+        (mapc (lambda (elem)
+                (when (get-register (car elem))
+                  (insert (funcall register-preview-function elem))))
+              register-alist)))))
+
+(defcustom register-preview-display-buffer-alist '(display-buffer-at-bottom
+                                                   (window-height . 
fit-window-to-buffer)
+                                                  (preserve-size . (nil . t)))
+  "Window configuration for the register preview buffer."
+  :type display-buffer--action-custom-type)
+
+(defun register-preview-1 (buffer &optional show-empty types)
+  "Pop up a window showing the preview of registers in BUFFER.
+
+This is the preview function used with the `register-read-with-preview-fancy'
+function.
+If SHOW-EMPTY is non-nil, show the preview window even if no registers.
+Optional argument TYPES (a list) specifies the types of register to show;
+if it is nil, show all the registers.  See `register-type' for suitable types.
 Format of each entry is controlled by the variable 
`register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
   (let ((registers (register-of-type-alist (or types '(all)))))
     (when (or show-empty (consp registers))
       (with-current-buffer-window
         buffer
-        (cons 'display-buffer-below-selected
-             '((window-height . fit-window-to-buffer)
-               (preserve-size . (nil . t))))
+        register-preview-display-buffer-alist
         nil
         (with-current-buffer standard-output
           (setq cursor-in-non-selected-windows nil)
@@ -297,7 +434,7 @@ Format of each entry is controlled by the variable 
`register-preview-function'."
                 registers))))))
 
 (cl-defgeneric register-preview-get-defaults (action)
-  "Returns default registers according to ACTION."
+  "Return default registers according to ACTION."
   (ignore action))
 (cl-defmethod register-preview-get-defaults ((_action (eql set)))
   (cl-loop for s in register-preview-default-keys
@@ -305,22 +442,77 @@ Format of each entry is controlled by the variable 
`register-preview-function'."
            collect s))
 
 (defun register-read-with-preview (prompt)
-  "Read and return a register name, possibly showing existing registers.
-Prompt with the string PROMPT.
+  "Read register name, prompting with PROMPT; possibly show existing registers.
+This reads and returns the name of a register.  PROMPT should be a string
+to prompt the user for the name.
+If `help-char' (or a member of `help-event-list') is pressed,
+display preview window unconditionally.
+This calls the function specified by `register--read-with-preview-function'."
+  (funcall register--read-with-preview-function prompt))
+
+(defun register-read-with-preview-traditional (prompt)
+  "Read register name, prompting with PROMPT; possibly show existing registers.
+This reads and returns the name of a register.  PROMPT should be a string
+to prompt the user for the name.
+If `register-alist' and `register-preview-delay' are both non-nil, display
+a window listing existing registers after `register-preview-delay' seconds.
 If `help-char' (or a member of `help-event-list') is pressed,
-display such a window regardless."
+display preview window unconditionally.
+
+This function is used as the value of `register--read-with-preview-function'
+when `register-use-preview' is set to \\='traditional."
   (let* ((buffer "*Register Preview*")
+        (timer (when (numberp register-preview-delay)
+                 (run-with-timer register-preview-delay nil
+                                 (lambda ()
+                                   (unless (get-buffer-window buffer)
+                                     (register-preview buffer))))))
+        (help-chars (cl-loop for c in (cons help-char help-event-list)
+                             when (not (get-register c))
+                             collect c)))
+    (unwind-protect
+       (progn
+         (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
+                      help-chars)
+           (unless (get-buffer-window buffer)
+             (register-preview buffer 'show-empty)))
+          (when (or (eq ?\C-g last-input-event)
+                    (eq 'escape last-input-event)
+                    (eq ?\C-\[ last-input-event))
+            (keyboard-quit))
+         (if (characterp last-input-event) last-input-event
+           (error "Non-character input-event")))
+      (and (timerp timer) (cancel-timer timer))
+      (let ((w (get-buffer-window buffer)))
+        (and (window-live-p w) (delete-window w)))
+      (and (get-buffer buffer) (kill-buffer buffer)))))
+
+(defun register-read-with-preview-fancy (prompt)
+  "Read register name, prompting with PROMPT; possibly show existing registers.
+This reads and returns the name of a register.  PROMPT should be a string
+to prompt the user for the name.
+If `help-char' (or a member of `help-event-list') is pressed,
+display preview window regardless.
+
+This function is used as the value of `register--read-with-preview-function'
+when `register-use-preview' is set to any value other than \\='traditional
+or \\='never."
+  (let* ((buffer "*Register Preview*")
+         (buffer1 "*Register quick preview*")
+         (buf (if register-use-preview buffer buffer1))
          (pat "")
          (map (let ((m (make-sparse-keymap)))
                 (set-keymap-parent m minibuffer-local-map)
                 m))
          (data (register-command-info this-command))
-         types msg result timer act win strs smatch)
+         (enable-recursive-minibuffers t)
+         types msg result act win strs smatch noconfirm)
     (if data
-        (setq types  (register-preview-info-types data)
-              msg    (register-preview-info-msg   data)
-              act    (register-preview-info-act   data)
-              smatch (register-preview-info-smatch data))
+        (setq types     (register-preview-info-types data)
+              msg       (register-preview-info-msg   data)
+              act       (register-preview-info-act   data)
+              smatch    (register-preview-info-smatch data)
+              noconfirm (register-preview-info-noconfirm data))
       (setq types '(all)
             msg   "Overwrite register `%s'"
             act   'set))
@@ -330,76 +522,91 @@ display such a window regardless."
     (when (and (memq act '(insert jump view)) (null strs))
       (error "No register suitable for `%s'" act))
     (dolist (k (cons help-char help-event-list))
-      (define-key map
-          (vector k) (lambda ()
-                       (interactive)
-                       (unless (get-buffer-window buffer)
-                         (with-selected-window (minibuffer-selected-window)
-                           (register-preview buffer 'show-empty types))))))
+      (define-key map (vector k)
+                  (lambda ()
+                    (interactive)
+                    ;; Do nothing when buffer1 is in use.
+                    (unless (get-buffer-window buf)
+                      (with-selected-window (minibuffer-selected-window)
+                        (register-preview-1 buffer 'show-empty types))))))
     (define-key map (kbd "<down>") 'register-preview-next)
     (define-key map (kbd "<up>")   'register-preview-previous)
     (define-key map (kbd "C-n")    'register-preview-next)
     (define-key map (kbd "C-p")    'register-preview-previous)
-    (unless (or executing-kbd-macro (null register-use-preview))
-      (register-preview buffer nil types))
+    (unless (or executing-kbd-macro (eq register-use-preview 'never))
+      (register-preview-1 buf nil types))
     (unwind-protect
-         (progn
-           (minibuffer-with-setup-hook
+        (let ((setup
                (lambda ()
-                 (setq timer
-                       (run-with-idle-timer
-                        0.01 'repeat
-                        (lambda ()
-                          (with-selected-window (minibuffer-window)
-                            (let ((input (minibuffer-contents)))
-                              (when (> (length input) 1)
-                                (let ((new (substring input 1))
-                                      (old (substring input 0 1)))
-                                  (setq input (if (or (null smatch)
-                                                      (member new strs))
-                                                  new old))
-                                  (delete-minibuffer-contents)
-                                  (insert input)))
-                              (when (and smatch (not (string= input ""))
-                                         (not (member input strs)))
-                                (setq input "")
-                                (delete-minibuffer-contents)
-                                (minibuffer-message "Not matching"))
-                              (when (not (string= input pat))
-                                (setq pat input))))
-                          (if (setq win (get-buffer-window buffer))
-                              (with-selected-window win
-                                (let ((ov (make-overlay (point-min) 
(point-min))))
-                                  (goto-char (point-min))
-                                  (remove-overlays)
-                                  (unless (string= pat "")
-                                    (if (re-search-forward (concat "^" pat) 
nil t)
-                                        (progn (move-overlay
-                                                ov
-                                                (match-beginning 0) (pos-eol))
-                                               (overlay-put ov 'face 'match)
-                                               (when msg
-                                                 (with-selected-window 
(minibuffer-window)
-                                                   (minibuffer-message msg 
pat))))
-                                      (with-selected-window (minibuffer-window)
-                                        (minibuffer-message
-                                         "Register `%s' is empty" pat))))))
-                            (unless (string= pat "")
-                              (if (member pat strs)
-                                  (with-selected-window (minibuffer-window)
-                                    (minibuffer-message msg pat))
-                                (with-selected-window (minibuffer-window)
-                                  (minibuffer-message
-                                   "Register `%s' is empty" pat)))))))))
-             (setq result (read-from-minibuffer
-                           prompt nil map nil nil 
(register-preview-get-defaults act))))
-           (cl-assert (and result (not (string= result "")))
-                      nil "No register specified")
-           (string-to-char result))
-      (when timer (cancel-timer timer))
-      (let ((w (get-buffer-window buffer)))
+                 (with-selected-window (minibuffer-window)
+                   (let ((input (minibuffer-contents)))
+                     (when (> (length input) 1)
+                       (let ((new (substring input 1))
+                             (old (substring input 0 1)))
+                         (setq input (if (or (null smatch)
+                                             (member new strs))
+                                         new old))
+                         (delete-minibuffer-contents)
+                         (insert input)
+                         ;; Exit minibuffer on second hit
+                         ;; when *-use-preview == insist.
+                         (when (and (string= new old)
+                                    (eq register-use-preview 'insist))
+                           (setq noconfirm t))))
+                     (when (and smatch (not (string= input ""))
+                                (not (member input strs)))
+                       (setq input "")
+                       (delete-minibuffer-contents)
+                       (minibuffer-message "Not matching"))
+                     (when (not (string= input pat))
+                       (setq pat input))))
+                 (if (setq win (get-buffer-window buffer))
+                     (with-selected-window win
+                       (when noconfirm
+                         ;; Happen only when
+                         ;; *-use-preview == insist.
+                         (exit-minibuffer))
+                       (let ((ov (make-overlay
+                                  (point-min) (point-min)))
+                             ;; Allow upper-case and lower-case letters
+                             ;; to refer to different registers.
+                             (case-fold-search nil))
+                         (goto-char (point-min))
+                         (remove-overlays)
+                         (unless (string= pat "")
+                           (if (re-search-forward (concat "^" pat) nil t)
+                               (progn (move-overlay
+                                       ov
+                                       (match-beginning 0) (pos-eol))
+                                      (overlay-put ov 'face 'match)
+                                      (when msg
+                                        (with-selected-window
+                                            (minibuffer-window)
+                                          (minibuffer-message msg pat))))
+                             (with-selected-window (minibuffer-window)
+                               (minibuffer-message
+                                "Register `%s' is empty" pat))))))
+                   (unless (string= pat "")
+                     (with-selected-window (minibuffer-window)
+                       (if (and (member pat strs)
+                                (null noconfirm))
+                           (with-selected-window (minibuffer-window)
+                             (minibuffer-message msg pat))
+                         ;; `:noconfirm' is specified explicitly, don't ask for
+                         ;; confirmation and exit immediately (bug#66394).
+                         (setq result pat)
+                         (exit-minibuffer))))))))
+          (minibuffer-with-setup-hook
+              (lambda () (add-hook 'post-command-hook setup nil 'local))
+            (setq result (read-from-minibuffer
+                          prompt nil map nil nil
+                          (register-preview-get-defaults act))))
+          (cl-assert (and result (not (string= result "")))
+                     nil "No register specified")
+          (string-to-char result))
+      (let ((w (get-buffer-window buf)))
         (and (window-live-p w) (delete-window w)))
-      (and (get-buffer buffer) (kill-buffer buffer)))))
+      (and (get-buffer buf) (kill-buffer buf)))))
 
 (defun point-to-register (register &optional arg)
   "Store current location of point in REGISTER.
diff --git a/lisp/registry.el b/lisp/registry.el
index c5f11714975..bd901b8a849 100644
--- a/lisp/registry.el
+++ b/lisp/registry.el
@@ -1,6 +1,6 @@
 ;;; registry.el --- Track and remember data items by various fields  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Teodor Zlatanov <tzz@lifelogs.com>
 ;; Keywords: data
diff --git a/lisp/repeat.el b/lisp/repeat.el
index 2fcac4d2ce3..0a59494c097 100644
--- a/lisp/repeat.el
+++ b/lisp/repeat.el
@@ -1,6 +1,6 @@
 ;;; repeat.el --- convenient way to repeat the previous command  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Will Mengarini <seldon@eskimo.com>
 ;; Created: Mo 02 Mar 98
diff --git a/lisp/replace.el b/lisp/replace.el
index ff7ca1145b8..fa460a16063 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -1,6 +1,6 @@
 ;;; replace.el --- replace commands for Emacs -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-1987, 1992, 1994, 1996-1997, 2000-2023 Free
+;; Copyright (C) 1985-1987, 1992, 1994, 1996-1997, 2000-2024 Free
 ;; Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/reposition.el b/lisp/reposition.el
index a422c3d88ae..83900e95f77 100644
--- a/lisp/reposition.el
+++ b/lisp/reposition.el
@@ -1,6 +1,6 @@
 ;;; reposition.el --- center a Lisp function or comment on the screen  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1991, 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael D. Ernst <mernst@theory.lcs.mit.edu>
 ;; Created: Jan 1991
diff --git a/lisp/reveal.el b/lisp/reveal.el
index 5ebc5f7c6c3..055667aa343 100644
--- a/lisp/reveal.el
+++ b/lisp/reveal.el
@@ -1,6 +1,6 @@
 ;;; reveal.el --- Automatically reveal hidden text at point -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: outlines
diff --git a/lisp/rfn-eshadow.el b/lisp/rfn-eshadow.el
index 75c407fd3d0..5cf483bf0b1 100644
--- a/lisp/rfn-eshadow.el
+++ b/lisp/rfn-eshadow.el
@@ -1,6 +1,6 @@
 ;;; rfn-eshadow.el --- Highlight `shadowed' part of read-file-name input text  
-*- lexical-binding: t; -*-
 ;;
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Miles Bader <miles@gnu.org>
 ;; Keywords: convenience minibuffer
diff --git a/lisp/rot13.el b/lisp/rot13.el
index 2d2ed904a7c..1eb027cea68 100644
--- a/lisp/rot13.el
+++ b/lisp/rot13.el
@@ -1,6 +1,6 @@
 ;;; rot13.el --- display a buffer in ROT13  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1988, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Howard Gayle
 ;;         Simon Josefsson
diff --git a/lisp/rtree.el b/lisp/rtree.el
index 4749629cd59..be2a6da4cfa 100644
--- a/lisp/rtree.el
+++ b/lisp/rtree.el
@@ -1,6 +1,6 @@
 ;;; rtree.el --- functions for manipulating range trees  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 
diff --git a/lisp/ruler-mode.el b/lisp/ruler-mode.el
index db8b891dc62..bce6a1805bc 100644
--- a/lisp/ruler-mode.el
+++ b/lisp/ruler-mode.el
@@ -1,6 +1,6 @@
 ;;; ruler-mode.el --- display a ruler in the header line  -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 ;; Created: 24 Mar 2001
diff --git a/lisp/savehist.el b/lisp/savehist.el
index ea8968c771b..5ae8a5e0340 100644
--- a/lisp/savehist.el
+++ b/lisp/savehist.el
@@ -1,6 +1,6 @@
 ;;; savehist.el --- Save minibuffer history  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Hrvoje Nikšić <hrvoje.niksic@avl.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/saveplace.el b/lisp/saveplace.el
index 1330d00f10a..a4942cb484b 100644
--- a/lisp/saveplace.el
+++ b/lisp/saveplace.el
@@ -1,6 +1,6 @@
 ;;; saveplace.el --- automatically save place in files  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Karl Fogel <kfogel@red-bean.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/scroll-all.el b/lisp/scroll-all.el
index 518dd3fb6cc..dc561f9115e 100644
--- a/lisp/scroll-all.el
+++ b/lisp/scroll-all.el
@@ -1,6 +1,6 @@
 ;;; scroll-all.el --- scroll all buffers together minor mode  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Gary D. Foster <Gary.Foster@corp.sun.com>
 ;; Keywords: convenience scroll lock
diff --git a/lisp/scroll-bar.el b/lisp/scroll-bar.el
index f4c1217a5a9..1358bff6da8 100644
--- a/lisp/scroll-bar.el
+++ b/lisp/scroll-bar.el
@@ -1,6 +1,6 @@
 ;;; scroll-bar.el --- window system-independent scroll bar support  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1995, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 1999-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: hardware
diff --git a/lisp/scroll-lock.el b/lisp/scroll-lock.el
index 12cdf2d0723..a9281c4bd61 100644
--- a/lisp/scroll-lock.el
+++ b/lisp/scroll-lock.el
@@ -1,6 +1,6 @@
 ;;; scroll-lock.el --- Scroll lock scrolling.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Ralf Angeli <angeli@iwi.uni-sb.de>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/select.el b/lisp/select.el
index f62f7b07239..ab78e88478b 100644
--- a/lisp/select.el
+++ b/lisp/select.el
@@ -1,6 +1,6 @@
 ;;; select.el --- lisp portion of standard selection support  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
diff --git a/lisp/server.el b/lisp/server.el
index a2671165bfc..66e6d729f8a 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -1,6 +1,6 @@
 ;;; server.el --- Lisp code for GNU Emacs running as server process -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1986-1987, 1992, 1994-2023 Free Software Foundation,
+;; Copyright (C) 1986-1987, 1992, 1994-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: William Sommerfeld <wesommer@athena.mit.edu>
@@ -729,7 +729,9 @@ the `server-process' variable."
         (concat "Unable to start the Emacs server.\n"
                 (cadr err)
                 (substitute-command-keys
-                 "\nTo start the server in this Emacs process, stop the 
existing server or call `\\[server-force-delete]' to forcibly disconnect it."))
+                 (concat "\nTo start the server in this Emacs process, stop "
+                         "the existing server or call \\[server-force-delete] "
+                         "to forcibly disconnect it.")))
         :warning)
        (setq leave-dead t)))
       ;; Now any previous server is properly stopped.
diff --git a/lisp/ses.el b/lisp/ses.el
index 30bf33e47bf..fcbb0567901 100644
--- a/lisp/ses.el
+++ b/lisp/ses.el
@@ -1,6 +1,6 @@
 ;;; ses.el --- Simple Emacs Spreadsheet  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Jonathan Yavner <jyavner@member.fsf.org>
 ;; Maintainer: Vincent Belaïche <vincentb1@users.sourceforge.net>
@@ -69,6 +69,8 @@
 (require 'macroexp)
 (eval-when-compile (require 'cl-lib))
 
+;; Autoloaded, but we have not loaded cl-loaddefs yet.
+(declare-function cl-member "cl-seq" (cl-item cl-list &rest cl-keys))
 
 ;;----------------------------------------------------------------------------
 ;; User-customizable variables
@@ -556,13 +558,15 @@ the corresponding cell with name PROPERTY-NAME."
 
 (defun ses-is-cell-sym-p (sym)
   "Check whether SYM point at a cell of this spread sheet."
-  (let ((rowcol (get sym 'ses-cell)))
-    (and rowcol
-        (if (eq rowcol :ses-named)
-            (and ses--named-cell-hashmap (gethash sym ses--named-cell-hashmap))
-          (and (< (car rowcol) ses--numrows)
-               (< (cdr rowcol) ses--numcols)
-               (eq (ses-cell-symbol (car rowcol) (cdr rowcol)) sym))))))
+  (and (symbolp sym)
+       (local-variable-p sym)
+       (let ((rowcol (get sym 'ses-cell)))
+         (and rowcol
+             (if (eq rowcol :ses-named)
+                 (and ses--named-cell-hashmap (gethash sym 
ses--named-cell-hashmap))
+               (and (< (car rowcol) ses--numrows)
+                    (< (cdr rowcol) ses--numcols)
+                    (eq (ses-cell-symbol (car rowcol) (cdr rowcol)) sym)))))))
 
 (defun ses--cell (sym value formula printer references)
   "Load a cell SYM from the spreadsheet file.
@@ -735,10 +739,8 @@ checking that it is a valid printer function."
 (defun ses-formula-record (formula)
   "If FORMULA is of the form \\='SYMBOL, add it to the list of symbolic 
formulas
 for this spreadsheet."
-  (when (and (eq (car-safe formula) 'quote)
-            (symbolp (cadr formula)))
-    (add-to-list 'ses--symbolic-formulas
-                (list (symbol-name (cadr formula))))))
+  (and (ses-is-cell-sym-p formula)
+    (cl-pushnew (symbol-name formula) ses--symbolic-formulas :test #'string=)))
 
 (defun ses-column-letter (col)
   "Return the alphabetic name of column number COL.
@@ -884,33 +886,36 @@ means Emacs will crash if FORMULA contains a circular 
list."
          (newref (ses-formula-references formula))
          (inhibit-quit t)
           not-a-cell-ref-list
-         x xrow xcol)
+         x xref xrow xcol)
       (cl-pushnew sym ses--deferred-recalc)
       ;;Delete old references from this cell.  Skip the ones that are also
       ;;in the new list.
       (dolist (ref oldref)
        (unless (memq ref newref)
-          ;; because we do not cancel edit when the user provides a
+          ;; Because we do not cancel edit when the user provides a
           ;; false reference in it, then we need to check that ref
           ;; points to a cell that is within the spreadsheet.
-         (setq x    (ses-sym-rowcol ref))
-          (and x
-               (< (setq xrow (car x)) ses--numrows)
-               (< (setq xcol (cdr x)) ses--numcols)
-               (ses-set-cell xrow xcol 'references
-                            (delq sym (ses-cell-references xrow xcol))))))
+         (when
+              (and (setq x (ses-sym-rowcol ref))
+                   (< (setq xrow (car x)) ses--numrows)
+                   (< (setq xcol (cdr x)) ses--numcols))
+            ;; Cell reference has to be re-written to data area as its
+            ;; reference list is changed.
+            (cl-pushnew x  ses--deferred-write  :test #'equal)
+            (ses-set-cell xrow xcol 'references
+                          (delq sym (ses-cell-references xrow xcol))))))
       ;;Add new ones.  Skip ones left over from old list
       (dolist (ref newref)
-       (setq x    (ses-sym-rowcol ref))
         ;;Do not trust the user, the reference may be outside the spreadsheet
         (if (and
-             x
+             (setq x    (ses-sym-rowcol ref))
              (<  (setq xrow (car x)) ses--numrows)
              (<  (setq xcol (cdr x)) ses--numcols))
-          (progn
-            (setq x (ses-cell-references xrow xcol))
-            (or (memq sym x)
-                (ses-set-cell xrow xcol 'references (cons sym x))))
+            (unless (memq sym (setq xref (ses-cell-references xrow xcol)))
+              ;; Cell reference has to be re-written to data area as
+              ;; its reference list is changed.
+              (cl-pushnew x  ses--deferred-write  :test #'equal)
+              (ses-set-cell xrow xcol 'references (cons sym xref)))
           (cl-pushnew ref not-a-cell-ref-list)))
       (ses-formula-record formula)
       (ses-set-cell row col 'formula formula)
@@ -2245,7 +2250,7 @@ Based on the current set of columns and `window-hscroll' 
position."
 ;; Redisplay and recalculation
 ;;----------------------------------------------------------------------------
 (defun ses-jump-prefix (prefix-int)
-  "Convert an integer (unversal prefix) into a (ROW . COL).
+  "Convert an integer (universal prefix) into a (ROW . COL).
 Does it by numbering cells starting from 0 from top left to bottom right,
 going row by row."
   (and (>= prefix-int 0)
@@ -2762,6 +2767,18 @@ See `ses-read-cell-printer' for input forms."
 ;;----------------------------------------------------------------------------
 ;; Spreadsheet size adjustments
 ;;----------------------------------------------------------------------------
+(defun ses--blank-line-needs-printing-p ()
+  "Returns `t' when blank new line print-out needs to be initialized
+by calling the printers on it, `nil' otherwise."
+  (let (ret
+        printer
+        (printers (append ses--col-printers (list ses--default-printer))))
+    (while printers
+      (if (and (setq printer (pop printers))
+               (null (string= "" (ses-call-printer printer))))
+          (setq ret t
+                printers nil)))
+    ret))
 
 (defun ses-insert-row (count)
   "Insert a new row before the current one.
@@ -2794,15 +2811,13 @@ With prefix, insert COUNT rows before current one."
     (ses-goto-data row 0)
     (insert (make-string (* (1+ ses--numcols) count) ?\n))
     (ses-relocate-all row 0 count 0)
-    ;;If any cell printers insert constant text, insert that text
-    ;;into the line.
-    (let ((cols   (mapconcat #'ses-call-printer ses--col-printers nil))
-         (global (ses-call-printer ses--default-printer)))
-      (if (or (> (length cols) 0) (> (length global) 0))
-         (dotimes (x count)
-           (dotimes (col ses--numcols)
-             ;;These cells are always nil, only constant formatting printed
-             (1value (ses-print-cell (+ x row) col))))))
+    ;;If any cell printers insert constant text, insert that text into
+    ;;the line.
+    (if (ses--blank-line-needs-printing-p)
+       (dotimes (x count)
+         (dotimes (col ses--numcols)
+           ;;These cells are always nil, only constant formatting printed
+           (1value (ses-print-cell (+ x row) col)))))
     (when (> ses--header-row row)
       ;;Inserting before header
       (ses-set-parameter 'ses--header-row (+ ses--header-row count))
@@ -3667,9 +3682,8 @@ highlighted range in the spreadsheet."
   "Rename current cell."
   (interactive "*SEnter new name: ")
   (or
-   (and  (local-variable-p new-name)
-        (ses-is-cell-sym-p new-name)
-        (error "Already a cell name"))
+   (and (ses-is-cell-sym-p new-name)
+       (error "Already a cell name"))
    (and (boundp new-name)
        (null (yes-or-no-p
               (format-message
diff --git a/lisp/shadowfile.el b/lisp/shadowfile.el
index 33340a371f1..877b2c8b5ee 100644
--- a/lisp/shadowfile.el
+++ b/lisp/shadowfile.el
@@ -1,6 +1,6 @@
 ;;; shadowfile.el --- automatic file copying  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Boris Goldowsky <boris@gnu.org>
 ;; Keywords: comm files
diff --git a/lisp/shell.el b/lisp/shell.el
index 48978fecbdd..c5cfbd985ed 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -1,6 +1,6 @@
 ;;; shell.el --- specialized comint.el for running the shell -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1988, 1993-1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1988, 1993-1997, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Olin Shivers <shivers@cs.cmu.edu>
diff --git a/lisp/simple.el b/lisp/simple.el
index e0b27658df6..9a33049f4ca 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1,6 +1,6 @@
 ;;; simple.el --- basic editing commands for Emacs  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-1987, 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1987, 1993-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
@@ -2087,6 +2087,9 @@ of the prefix argument for `eval-expression' and
                 ((= num -1) most-positive-fixnum)
                 (t eval-expression-print-maximum-character)))))
 
+(defun eval-expression--debug (err)
+  (funcall debugger 'error err :backtrace-base #'eval-expression--debug))
+
 ;; We define this, rather than making `eval' interactive,
 ;; for the sake of completion of names like eval-region, eval-buffer.
 (defun eval-expression (exp &optional insert-value no-truncate 
char-print-limit)
@@ -2120,23 +2123,17 @@ this command arranges for all errors to enter the 
debugger."
    (cons (read--expression "Eval: ")
          (eval-expression-get-print-arguments current-prefix-arg)))
 
-  (let (result)
+  (let* (result
+         (runfun
+          (lambda ()
+            (setq result
+                  (values--store-value
+                   (eval (let ((lexical-binding t)) (macroexpand-all exp))
+                         t))))))
     (if (null eval-expression-debug-on-error)
-        (setq result
-              (values--store-value
-               (eval (let ((lexical-binding t)) (macroexpand-all exp)) t)))
-      (let ((old-value (make-symbol "t")) new-value)
-        ;; Bind debug-on-error to something unique so that we can
-        ;; detect when evalled code changes it.
-        (let ((debug-on-error old-value))
-          (setq result
-               (values--store-value
-                 (eval (let ((lexical-binding t)) (macroexpand-all exp)) t)))
-         (setq new-value debug-on-error))
-        ;; If evalled code has changed the value of debug-on-error,
-        ;; propagate that change to the global binding.
-        (unless (eq old-value new-value)
-         (setq debug-on-error new-value))))
+        (funcall runfun)
+      (handler-bind ((error #'eval-expression--debug))
+        (funcall runfun)))
 
     (let ((print-length (unless no-truncate eval-expression-print-length))
           (print-level  (unless no-truncate eval-expression-print-level))
@@ -6422,7 +6419,7 @@ PROMPT is a string to prompt with."
                      0 (length s)
                      '(
                        keymap local-map action mouse-action
-                       button category help-args)
+                       read-only button category help-args)
                      s)
                     s)
                   kill-ring))
@@ -8756,7 +8753,7 @@ node `(elisp) Word Motion' for details."
 
 (defun mark-word (&optional arg allow-extend)
   "Set mark ARG words from point or move mark one word.
-When called from Lisp with ALLOW-EXTEND ommitted or nil, mark is
+When called from Lisp with ALLOW-EXTEND omitted or nil, mark is
 set ARG words from point.
 With ARG and ALLOW-EXTEND both non-nil (interactively, with prefix
 argument), the place to which mark goes is the same place \\[forward-word]
@@ -9943,6 +9940,20 @@ Also see the `completion-auto-wrap' variable."
   (interactive "p")
   (next-completion (- n)))
 
+(defun completion--move-to-candidate-start ()
+  "If in a completion candidate, move point to its start."
+  (when (and (get-text-property (point) 'mouse-face)
+             (not (bobp))
+             (get-text-property (1- (point)) 'mouse-face))
+    (goto-char (previous-single-property-change (point) 'mouse-face))))
+
+(defun completion--move-to-candidate-end ()
+  "If in a completion candidate, move point to its end."
+  (when (and (get-text-property (point) 'mouse-face)
+             (not (eobp))
+             (get-text-property (1+ (point)) 'mouse-face))
+    (goto-char (or (next-single-property-change (point) 'mouse-face) 
(point-max)))))
+
 (defun next-completion (n)
   "Move to the next item in the completions buffer.
 With prefix argument N, move N items (negative N means move
@@ -10032,9 +10043,7 @@ Also see the `completion-auto-wrap' variable."
 
     (if (get-text-property (point) 'mouse-face)
         ;; If in a completion, move to the start of it.
-        (when (and (not (bobp))
-                   (get-text-property (1- (point)) 'mouse-face))
-          (goto-char (previous-single-property-change (point) 'mouse-face)))
+        (completion--move-to-candidate-start)
       ;; Try to move to the previous completion.
       (setq pos (previous-single-property-change (point) 'mouse-face))
       (if pos
@@ -10049,10 +10058,11 @@ Also see the `completion-auto-wrap' variable."
 
     (while (> n 0)
       (setq found nil pos nil column (current-column) line 
(line-number-at-pos))
+      (completion--move-to-candidate-end)
       (while (and (not found)
                   (eq (forward-line 1) 0)
                   (not (eobp))
-                  (eq (move-to-column column) column))
+                  (move-to-column column))
         (when (get-text-property (point) 'mouse-face)
           (setq found t)))
       (when (not found)
@@ -10073,9 +10083,10 @@ Also see the `completion-auto-wrap' variable."
 
     (while (< n 0)
       (setq found nil pos nil column (current-column) line 
(line-number-at-pos))
+      (completion--move-to-candidate-start)
       (while (and (not found)
                   (eq (forward-line -1) 0)
-                  (eq (move-to-column column) column))
+                  (move-to-column column))
         (when (get-text-property (point) 'mouse-face)
           (setq found t)))
       (when (not found)
@@ -10324,13 +10335,27 @@ Called from `temp-buffer-show-hook'."
       ;; Maybe insert help string.
       (when completion-show-help
        (goto-char (point-min))
-        (insert (substitute-command-keys
-                (if (display-mouse-p)
-                    "Click or type \\[minibuffer-choose-completion] on a 
completion to select it.\n"
-                   "Type \\[minibuffer-choose-completion] on a completion to 
select it.\n")))
-        (insert (substitute-command-keys
-                "Type \\[minibuffer-next-completion] or 
\\[minibuffer-previous-completion] \
-to move point between completions.\n\n"))))))
+        (if minibuffer-visible-completions
+            (let ((helps
+                   (with-current-buffer (window-buffer 
(active-minibuffer-window))
+                     (list
+                      (substitute-command-keys
+                      (if (display-mouse-p)
+                          "Click or type 
\\[minibuffer-choose-completion-or-exit] on a completion to select it.\n"
+                         "Type \\[minibuffer-choose-completion-or-exit] on a 
completion to select it.\n"))
+                      (substitute-command-keys
+                      "Type \\[minibuffer-next-completion], 
\\[minibuffer-previous-completion], \
+\\[minibuffer-next-line-completion], \\[minibuffer-previous-line-completion] \
+to move point between completions.\n\n")))))
+              (dolist (help helps)
+                (insert help)))
+          (insert (substitute-command-keys
+                  (if (display-mouse-p)
+                      "Click or type \\[minibuffer-choose-completion] on a 
completion to select it.\n"
+                     "Type \\[minibuffer-choose-completion] on a completion to 
select it.\n")))
+          (insert (substitute-command-keys
+                  "Type \\[minibuffer-next-completion] or 
\\[minibuffer-previous-completion] \
+to move point between completions.\n\n")))))))
 
 (add-hook 'completion-setup-hook #'completion-setup-function)
 
@@ -11178,10 +11203,10 @@ For each insertion:
     enabled.
 
   - Look for the deletion of a single electric pair character,
-    and delete the adjascent pair if
+    and delete the adjacent pair if
     `electric-pair-delete-adjacent-pairs'.
 
-  - Run `post-self-insert-functions' for the last character of
+  - Run `post-self-insert-hook' for the last character of
     any inserted text so that modes such as `electric-pair-mode'
     can work.
 
diff --git a/lisp/skeleton.el b/lisp/skeleton.el
index dbb8fd0a763..2a20fc6d321 100644
--- a/lisp/skeleton.el
+++ b/lisp/skeleton.el
@@ -1,6 +1,6 @@
 ;;; skeleton.el --- Lisp language extension for writing statement skeletons  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/so-long.el b/lisp/so-long.el
index d91002e873a..0208f3fddef 100644
--- a/lisp/so-long.el
+++ b/lisp/so-long.el
@@ -1,6 +1,6 @@
 ;;; so-long.el --- Say farewell to performance problems with minified code.  
-*- lexical-binding:t -*-
 ;;
-;; Copyright (C) 2015-2016, 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2016, 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Phil Sainty <psainty@orcon.net.nz>
 ;; Maintainer: Phil Sainty <psainty@orcon.net.nz>
diff --git a/lisp/sort.el b/lisp/sort.el
index 6b008b6644e..4f0d759ef8a 100644
--- a/lisp/sort.el
+++ b/lisp/sort.el
@@ -1,6 +1,6 @@
 ;;; sort.el --- commands to sort text in an Emacs buffer -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 1986-1987, 1994-1995, 2001-2023 Free Software
+;; Copyright (C) 1986-1987, 1994-1995, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Howie Kaye
@@ -478,6 +478,27 @@ sRegexp specifying key within record: \nr")
                          ;; if there was no such register
                          (error (throw 'key nil))))))))))
 
+;;;###autoload
+(defun sort-on (sequence predicate accessor)
+  "Sort SEQUENCE by calling PREDICATE on sort keys produced by ACCESSOR.
+SEQUENCE should be the input sequence to sort.
+Elements of SEQUENCE are sorted by keys which are obtained by
+calling ACCESSOR on each element.  ACCESSOR should be a function of
+one argument, an element of SEQUENCE, and should return the key
+value to be compared by PREDICATE for sorting the element.
+PREDICATE is the function for comparing keys; it is called with two
+arguments, the keys to compare, and should return non-nil if the
+first key should sort before the second key.
+The return value is always a new list.
+This function has the performance advantage of evaluating
+ACCESSOR only once for each element in the input SEQUENCE, and is
+therefore appropriate when computing the key by ACCESSOR is an
+expensive operation.  This is known as the \"decorate-sort-undecorate\"
+paradigm, or the Schwartzian transform."
+  (mapcar #'car
+          (sort (mapcar #'(lambda (x) (cons x (funcall accessor x))) sequence)
+                #'(lambda (x y) (funcall predicate (cdr x) (cdr y))))))
+
 
 (defvar sort-columns-subprocess t)
 
diff --git a/lisp/soundex.el b/lisp/soundex.el
index 2cffec18d8e..b2988997ee2 100644
--- a/lisp/soundex.el
+++ b/lisp/soundex.el
@@ -1,6 +1,6 @@
 ;;; soundex.el --- implement Soundex algorithm -*- lexical-binding: t -*-
 
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Christian Plaunt <chris@bliss.berkeley.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/speedbar.el b/lisp/speedbar.el
index 51c5962cb66..1cb72dc23e6 100644
--- a/lisp/speedbar.el
+++ b/lisp/speedbar.el
@@ -1,6 +1,6 @@
 ;;; speedbar.el --- quick access to files and tags in a frame  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: file, tags, tools
diff --git a/lisp/sqlite-mode.el b/lisp/sqlite-mode.el
index 120967a725f..7b1a9ce2e88 100644
--- a/lisp/sqlite-mode.el
+++ b/lisp/sqlite-mode.el
@@ -1,6 +1,6 @@
 ;;; sqlite-mode.el --- Mode for examining sqlite3 database files  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/sqlite.el b/lisp/sqlite.el
index 22a0355d3cd..46e35ac18d8 100644
--- a/lisp/sqlite.el
+++ b/lisp/sqlite.el
@@ -1,6 +1,6 @@
 ;;; sqlite.el --- Functions for interacting with sqlite3 databases  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/startup.el b/lisp/startup.el
index e40c316a8e8..773765a4b97 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -1,6 +1,6 @@
 ;;; startup.el --- process Emacs shell arguments  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-1986, 1992, 1994-2023 Free Software Foundation,
+;; Copyright (C) 1985-1986, 1992, 1994-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -393,7 +393,7 @@ If this is nil, Emacs uses `system-name'."
   "The email address of the current user.
 This defaults to either: the value of EMAIL environment variable; or
 user@host, using `user-login-name' and `mail-host-address' (or `system-name')."
-  :initialize 'custom-initialize-delay
+  :initialize #'custom-initialize-delay
   :set-after '(mail-host-address)
   :type 'string
   :group 'mail)
@@ -492,7 +492,7 @@ DIRS are relative."
       (setq tail (cdr tail)))
     ;;Splice the new section in.
     (when tail
-      (setcdr tail (append (mapcar 'expand-file-name dirs) (cdr tail))))))
+      (setcdr tail (append (mapcar #'expand-file-name dirs) (cdr tail))))))
 
 ;; The default location for XDG-convention Emacs init files.
 (defconst startup--xdg-config-default "~/.config/emacs/")
@@ -641,7 +641,24 @@ It is the default value of the variable `top-level'."
       (setq eol-mnemonic-dos  "(DOS)"
            eol-mnemonic-mac  "(Mac)")))
 
-    (set-locale-environment nil)
+    (if (and (featurep 'android)
+             (eq system-type 'android)
+             (fboundp 'android-locale-for-system-language)
+             initial-window-system)
+        ;; If Android windowing is enabled, derive a proper locale
+        ;; from the system's language preferences.  On Android, LANG
+        ;; and LC_* must be set to one of the two locales the C
+        ;; library supports, but, by contrast with other systems, the
+        ;; C library locale does not reflect the configured system
+        ;; language.
+        ;;
+        ;; For this reason, the locale from which Emacs derives a
+        ;; default language environment is computed from such
+        ;; preferences, rather than environment variables that the C
+        ;; library refers to.
+        (set-locale-environment
+         (funcall 'android-locale-for-system-language))
+      (set-locale-environment nil))
     ;; Decode all default-directory's (probably, only *scratch* exists
     ;; at this point).  default-directory of *scratch* is the basis
     ;; for many other file-name variables and directory lists, so it
@@ -1002,6 +1019,9 @@ If STYLE is nil, display appropriately for the terminal."
           (when standard-display-table
             (aset standard-display-table char nil)))))))
 
+(defun startup--debug (err)
+  (funcall debugger 'error err :backtrace-base #'startup--debug))
+
 (defun startup--load-user-init-file
     (filename-function &optional alternate-filename-function load-defaults)
   "Load a user init-file.
@@ -1015,88 +1035,79 @@ is non-nil.
 
 This function sets `user-init-file' to the name of the loaded
 init-file, or to a default value if loading is not possible."
-  (let ((debug-on-error-from-init-file nil)
-        (debug-on-error-should-be-set nil)
-        (debug-on-error-initial
-         (if (eq init-file-debug t)
-             'startup--witness  ;Dummy but recognizable non-nil value.
-           init-file-debug))
-        (d-i-e-from-init-file nil)
-        (d-i-e-initial
-         ;; Use (startup--witness) instead of nil, so we can detect when the
-         ;; init files set `debug-ignored-errors' to nil.
-         (if init-file-debug '(startup--witness) debug-ignored-errors))
-        (d-i-e-standard debug-ignored-errors)
-        ;; The init file might contain byte-code with embedded NULs,
-        ;; which can cause problems when read back, so disable nul
-        ;; byte detection.  (Bug#52554)
-        (inhibit-null-byte-detection t))
-    (let ((debug-on-error debug-on-error-initial)
-          ;; If they specified --debug-init, enter the debugger
-          ;; on any error whatsoever.
-          (debug-ignored-errors d-i-e-initial))
+  ;; The init file might contain byte-code with embedded NULs,
+  ;; which can cause problems when read back, so disable nul
+  ;; byte detection.  (Bug#52554)
+  (let ((inhibit-null-byte-detection t)
+        (body
+         (lambda ()
+           (when init-file-user
+             (let ((init-file-name (funcall filename-function)))
+
+               ;; If `user-init-file' is t, then `load' will store
+               ;; the name of the file that it loads into
+               ;; `user-init-file'.
+               (setq user-init-file t)
+              (when init-file-name
+                (load (if (equal (file-name-extension init-file-name)
+                                 "el")
+                          (file-name-sans-extension init-file-name)
+                        init-file-name)
+                      'noerror 'nomessage))
+
+               (when (and (eq user-init-file t) alternate-filename-function)
+                 (let ((alt-file (funcall alternate-filename-function)))
+                  (unless init-file-name
+                    (setq init-file-name alt-file))
+                  (and (equal (file-name-extension alt-file) "el")
+                       (setq alt-file (file-name-sans-extension alt-file)))
+                  (load alt-file 'noerror 'nomessage)))
+
+               ;; If we did not find the user's init file, set
+               ;; user-init-file conclusively.  Don't let it be
+               ;; set from default.el.
+               (when (eq user-init-file t)
+                 (setq user-init-file init-file-name)))
+
+             ;; If we loaded a compiled file, set `user-init-file' to
+             ;; the source version if that exists.
+             (if (equal (file-name-extension user-init-file) "elc")
+                 (let* ((source (file-name-sans-extension user-init-file))
+                        (alt (concat source ".el")))
+                   (setq source (cond ((file-exists-p alt) alt)
+                                      ((file-exists-p source) source)
+                                      (t nil)))
+                   (when source
+                     (when (file-newer-than-file-p source user-init-file)
+                       (message "Warning: %s is newer than %s"
+                                source user-init-file)
+                       (sit-for 1))
+                     (setq user-init-file source)))
+               ;; Else, perhaps the user init file was compiled
+               (when (and (equal (file-name-extension user-init-file) "eln")
+                          ;; The next test is for builds without native
+                          ;; compilation support or builds with unexec.
+                          (boundp 'comp-eln-to-el-h))
+                 (if-let (source (gethash (file-name-nondirectory
+                                           user-init-file)
+                                          comp-eln-to-el-h))
+                     ;; source exists or the .eln file would not load
+                     (setq user-init-file source)
+                   (message "Warning: unknown source file for init file %S"
+                            user-init-file)
+                   (sit-for 1))))
+
+             (when (and load-defaults
+                        (not inhibit-default-init))
+               ;; Prevent default.el from changing the value of
+               ;; `inhibit-startup-screen'.
+               (let ((inhibit-startup-screen nil))
+                 (load "default" 'noerror 'nomessage)))))))
+    (if (eq init-file-debug t)
+        (handler-bind ((error #'startup--debug))
+          (funcall body))
       (condition-case-unless-debug error
-          (when init-file-user
-            (let ((init-file-name (funcall filename-function)))
-
-              ;; If `user-init-file' is t, then `load' will store
-              ;; the name of the file that it loads into
-              ;; `user-init-file'.
-              (setq user-init-file t)
-             (when init-file-name
-               (load (if (equal (file-name-extension init-file-name)
-                                "el")
-                         (file-name-sans-extension init-file-name)
-                       init-file-name)
-                     'noerror 'nomessage))
-
-              (when (and (eq user-init-file t) alternate-filename-function)
-                (let ((alt-file (funcall alternate-filename-function)))
-                 (unless init-file-name
-                   (setq init-file-name alt-file))
-                  (and (equal (file-name-extension alt-file) "el")
-                       (setq alt-file (file-name-sans-extension alt-file)))
-                  (load alt-file 'noerror 'nomessage)))
-
-              ;; If we did not find the user's init file, set
-              ;; user-init-file conclusively.  Don't let it be
-              ;; set from default.el.
-              (when (eq user-init-file t)
-                (setq user-init-file init-file-name)))
-
-            ;; If we loaded a compiled file, set `user-init-file' to
-            ;; the source version if that exists.
-            (if (equal (file-name-extension user-init-file) "elc")
-                (let* ((source (file-name-sans-extension user-init-file))
-                       (alt (concat source ".el")))
-                  (setq source (cond ((file-exists-p alt) alt)
-                                     ((file-exists-p source) source)
-                                     (t nil)))
-                  (when source
-                    (when (file-newer-than-file-p source user-init-file)
-                      (message "Warning: %s is newer than %s"
-                               source user-init-file)
-                      (sit-for 1))
-                    (setq user-init-file source)))
-              ;; Else, perhaps the user init file was compiled
-              (when (and (equal (file-name-extension user-init-file) "eln")
-                         ;; The next test is for builds without native
-                         ;; compilation support or builds with unexec.
-                         (boundp 'comp-eln-to-el-h))
-                (if-let (source (gethash (file-name-nondirectory 
user-init-file)
-                                         comp-eln-to-el-h))
-                    ;; source exists or the .eln file would not load
-                    (setq user-init-file source)
-                  (message "Warning: unknown source file for init file %S"
-                           user-init-file)
-                  (sit-for 1))))
-
-            (when (and load-defaults
-                       (not inhibit-default-init))
-              ;; Prevent default.el from changing the value of
-              ;; `inhibit-startup-screen'.
-              (let ((inhibit-startup-screen nil))
-                (load "default" 'noerror 'nomessage))))
+          (funcall body)
         (error
          (display-warning
           'initialization
@@ -1111,28 +1122,7 @@ the `--debug-init' option to view a complete error 
backtrace."
                           (mapconcat (lambda (s) (prin1-to-string s t))
                                      (cdr error) ", "))
           :warning)
-         (setq init-file-had-error t)))
-
-      ;; If we can tell that the init file altered debug-on-error,
-      ;; arrange to preserve the value that it set up.
-      (unless (eq debug-ignored-errors d-i-e-initial)
-        (if (memq 'startup--witness debug-ignored-errors)
-            ;; The init file wants to add errors to the standard
-            ;; value, so we need to emulate that.
-            (setq d-i-e-from-init-file
-                  (list (append d-i-e-standard
-                                (remq 'startup--witness
-                                      debug-ignored-errors))))
-          ;; The init file _replaces_ the standard value.
-          (setq d-i-e-from-init-file (list debug-ignored-errors))))
-      (or (eq debug-on-error debug-on-error-initial)
-          (setq debug-on-error-should-be-set t
-                debug-on-error-from-init-file debug-on-error)))
-
-    (when d-i-e-from-init-file
-      (setq debug-ignored-errors (car d-i-e-from-init-file)))
-    (when debug-on-error-should-be-set
-      (setq debug-on-error debug-on-error-from-init-file))))
+         (setq init-file-had-error t))))))
 
 (defvar lisp-directory nil
   "Directory where Emacs's own *.el and *.elc Lisp files are installed.")
@@ -1428,7 +1418,7 @@ please check its value")
     (error
      (princ
       (if (eq (car error) 'error)
-         (apply 'concat (cdr error))
+         (apply #'concat (cdr error))
        (if (memq 'file-error (get (car error) 'error-conditions))
            (format "%s: %s"
                     (nth 1 error)
@@ -1768,7 +1758,7 @@ If this is nil, no message will be displayed."
      "\n"))
   "A list of texts to show in the middle part of splash screens.
 Each element in the list should be a list of strings or pairs
-`:face FACE', like `fancy-splash-insert' accepts them.")
+`:KEYWORD VALUE', like what `fancy-splash-insert' accepts.")
 
 (defconst fancy-about-text
   `((:face (variable-pitch font-lock-comment-face)
@@ -1861,7 +1851,7 @@ Each element in the list should be a list of strings or 
pairs
      "\tDisplay the Emacs manual in Info mode"))
   "A list of texts to show in the middle part of the About screen.
 Each element in the list should be a list of strings or pairs
-`:face FACE', like `fancy-splash-insert' accepts them.")
+`:KEYWORD VALUE', like what `fancy-splash-insert' accepts.")
 
 
 (defgroup fancy-splash-screen ()
@@ -1880,10 +1870,10 @@ Each element in the list should be a list of strings or 
pairs
   (let ((map (make-sparse-keymap)))
     (suppress-keymap map)
     (set-keymap-parent map button-buffer-map)
-    (define-key map "\C-?" 'scroll-down-command)
-    (define-key map [?\S-\ ] 'scroll-down-command)
-    (define-key map " " 'scroll-up-command)
-    (define-key map "q" 'exit-splash-screen)
+    (define-key map "\C-?" #'scroll-down-command)
+    (define-key map [?\S-\ ] #'scroll-down-command)
+    (define-key map " " #'scroll-up-command)
+    (define-key map "q" #'exit-splash-screen)
     map)
   "Keymap for splash screen buffer.")
 
@@ -2321,7 +2311,7 @@ To quit a partially entered command, type Control-g.\n")
                       ;; If C-h can't be invoked, temporarily disable its
                       ;; binding, so where-is uses alternative bindings.
                       (let ((map (make-sparse-keymap)))
-                        (define-key map [?\C-h] 'undefined)
+                        (define-key map [?\C-h] #'undefined)
                         map))
                 minor-mode-overriding-map-alist)))
 
@@ -2513,8 +2503,8 @@ A fancy display is used on graphic displays, normal 
otherwise."
       (fancy-about-screen)
     (normal-splash-screen nil)))
 
-(defalias 'about-emacs 'display-about-screen)
-(defalias 'display-splash-screen 'display-startup-screen)
+(defalias 'about-emacs #'display-about-screen)
+(defalias 'display-splash-screen #'display-startup-screen)
 
 ;; This avoids byte-compiler warning in the unexec build.
 (declare-function pdumper-stats "pdumper.c" ())
diff --git a/lisp/strokes.el b/lisp/strokes.el
index 5bfcab5f9e2..50920229d9d 100644
--- a/lisp/strokes.el
+++ b/lisp/strokes.el
@@ -1,6 +1,6 @@
 ;;; strokes.el --- control Emacs through mouse strokes  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: David Bakhash <cadet@alum.mit.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/subr.el b/lisp/subr.el
index eb7383207bb..a9b30a1aa6a 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -1,6 +1,6 @@
 ;;; subr.el --- basic lisp subroutines for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2023 Free Software
+;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -2023,6 +2023,8 @@ instead; it will indirectly limit the specpdl stack size 
as well.")
 
 (defvaralias 'native-comp-deferred-compilation 'native-comp-jit-compilation)
 
+(define-obsolete-function-alias 'fetch-bytecode #'ignore "30.1")
+
 
 ;;;; Alternate names for functions - these are not being phased out.
 
@@ -2737,6 +2739,8 @@ By default we choose the head of the first list."
 
 (defun derived-mode-all-parents (mode &optional known-children)
   "Return all the parents of MODE, starting with MODE.
+This includes the parents set by `define-derived-mode' and additional
+ones set by `derived-mode-add-parents'.
 The returned list is not fresh, don't modify it.
 \n(fn MODE)"               ;`known-children' is for internal use only.
   ;; Can't use `with-memoization' :-(
@@ -2785,7 +2789,9 @@ The returned list is not fresh, don't modify it.
 (defun provided-mode-derived-p (mode &optional modes &rest old-modes)
   "Non-nil if MODE is derived from a mode that is a member of the list MODES.
 MODES can also be a single mode instead of a list.
-If you just want to check `major-mode', use `derived-mode-p'.
+This examines the parent modes set by `define-derived-mode' and also
+additional ones set by `derived-mode-add-parents'.
+If you just want to check the current `major-mode', use `derived-mode-p'.
 We also still support the deprecated calling convention:
 \(provided-mode-derived-p MODE &rest MODES)."
   (declare (side-effect-free t)
@@ -2799,12 +2805,18 @@ We also still support the deprecated calling convention:
     (car modes)))
 
 (defun derived-mode-p (&optional modes &rest old-modes)
- "Non-nil if the current major mode is derived from one of MODES.
+ "Return non-nil if the current major mode is derived from one of MODES.
 MODES should be a list of symbols or a single mode symbol instead of a list.
+This examines the parent modes set by `define-derived-mode' and also
+additional ones set by `derived-mode-add-parents'.
 We also still support the deprecated calling convention:
 \(derived-mode-p &rest MODES)."
  (declare (side-effect-free t)
-          (advertised-calling-convention (modes) "30.1"))
+          ;; FIXME: It's cumbersome for external packages to write code which
+          ;; accommodates both the old and the new calling conventions *and*
+          ;; doesn't cause spurious warnings.  So let's be more lenient
+          ;; for now and maybe remove `deprecated-args' for Emacs-31.
+          (advertised-calling-convention (modes &rest deprecated-args) "30.1"))
  (provided-mode-derived-p major-mode (if old-modes (cons modes old-modes)
                                        modes)))
 
@@ -2816,7 +2828,8 @@ We also still support the deprecated calling convention:
 (defun derived-mode-add-parents (mode extra-parents)
   "Add EXTRA-PARENTS to the parents of MODE.
 Declares the parents of MODE to be its main parent (as defined
-in `define-derived-mode') plus EXTRA-PARENTS."
+in `define-derived-mode') plus EXTRA-PARENTS, which should be a list
+of symbols."
   (put mode 'derived-mode-extra-parents extra-parents)
   (derived-mode--flush mode))
 
@@ -3091,7 +3104,7 @@ instead."
 LIBRARY should be a relative file name of the library, a string.
 It can omit the suffix (a.k.a. file-name extension) if NOSUFFIX is
 nil (which is the default, see below).
-This command searches the directories in `load-path' like `\\[load-library]'
+This command searches the directories in `load-path' like \\[load-library]
 to find the file that `\\[load-library] RET LIBRARY RET' would load.
 Optional second arg NOSUFFIX non-nil means don't add suffixes `load-suffixes'
 to the specified name LIBRARY.
@@ -6380,13 +6393,14 @@ If non-nil, BASE should be a function, and frames 
before its
 nearest activation frame are discarded."
   (let ((frames nil))
     (mapbacktrace (lambda (&rest frame) (push frame frames))
-                  (or base 'backtrace-frames))
+                  (or base #'backtrace-frames))
     (nreverse frames)))
 
 (defun backtrace-frame (nframes &optional base)
   "Return the function and arguments NFRAMES up from current execution point.
 If non-nil, BASE should be a function, and NFRAMES counts from its
-nearest activation frame.
+nearest activation frame.  BASE can also be of the form (OFFSET . FUNCTION)
+in which case OFFSET will be added to NFRAMES.
 If the frame has not evaluated the arguments yet (or is a special form),
 the value is (nil FUNCTION ARG-FORMS...).
 If the frame has evaluated its arguments and called its function already,
@@ -6397,7 +6411,7 @@ or a lambda expression for macro calls.
 If NFRAMES is more than the number of frames, the value is nil."
   (backtrace-frame--internal
    (lambda (evald func args _) `(,evald ,func ,@args))
-   nframes (or base 'backtrace-frame)))
+   nframes (or base #'backtrace-frame)))
 
 
 (defvar called-interactively-p-functions nil
@@ -7492,6 +7506,28 @@ predicate conditions in CONDITION."
         (push buf bufs)))
     bufs))
 
+(defmacro handler-bind (handlers &rest body)
+  "Setup error HANDLERS around execution of BODY.
+HANDLERS is a list of (CONDITIONS HANDLER) where
+CONDITIONS should be a list of condition names (symbols) or
+a single condition name, and HANDLER is a form whose evaluation
+returns a function.
+When an error is signaled during execution of BODY, if that
+error matches CONDITIONS, then the associated HANDLER
+function is called with the error object as argument.
+HANDLERs can either transfer the control via a non-local exit,
+or return normally.  If a handler returns normally, the search for an
+error handler continues from where it left off."
+  ;; FIXME: Completion support as in `condition-case'?
+  (declare (indent 1) (debug ((&rest (sexp form)) body)))
+  (let ((args '()))
+    (dolist (cond+handler handlers)
+      (let ((handler (car (cdr cond+handler)))
+            (conds (car cond+handler)))
+        (push `',(ensure-list conds) args)
+        (push handler args)))
+    `(handler-bind-1 (lambda () ,@body) ,@(nreverse args))))
+
 (defmacro with-memoization (place &rest code)
   "Return the value of CODE and stash it in PLACE.
 If PLACE's value is non-nil, then don't bother evaluating CODE
diff --git a/lisp/svg.el b/lisp/svg.el
index dc8b4feb51f..f2eb2ec66dd 100644
--- a/lisp/svg.el
+++ b/lisp/svg.el
@@ -1,6 +1,6 @@
 ;;; svg.el --- SVG image creation functions -*- lexical-binding: t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;;         Felix E. Klee <felix.klee@inka.de>
diff --git a/lisp/t-mouse.el b/lisp/t-mouse.el
index c461743b0f1..6bd3168ab7c 100644
--- a/lisp/t-mouse.el
+++ b/lisp/t-mouse.el
@@ -4,7 +4,7 @@
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: mouse gpm linux
 
-;; Copyright (C) 1994-1995, 1998, 2006-2023 Free Software Foundation,
+;; Copyright (C) 1994-1995, 1998, 2006-2024 Free Software Foundation,
 ;; Inc.
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index e21367255a0..3e1d8278b04 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -1,6 +1,6 @@
 ;;; tab-bar.el --- frame-local tabs with named persistent window 
configurations -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Juri Linkov <juri@linkov.net>
 ;; Keywords: frames tabs
@@ -416,6 +416,8 @@ Beep, then throw to `context-menu' and return."
   (beep)
   (throw 'context-menu 'context-menu))
 
+(defvar touch-screen-delay)
+
 (defun tab-bar-touchscreen-begin (event)
   "Handle a touchscreen begin EVENT on the tab bar.
 
@@ -1300,7 +1302,7 @@ tab bar might wrap to the second line when it shouldn't.")
       (ws . ,(window-state-get
               (frame-root-window (or frame (selected-frame))) 'writable))
       (wc . ,(current-window-configuration))
-      (wc-point . ,(point-marker))
+      (wc-point . ,(copy-marker (window-point) window-point-insertion-type))
       (wc-bl . ,bl)
       (wc-bbl . ,bbl)
       ,@(when tab-bar-history-mode
@@ -1453,13 +1455,7 @@ Negative TAB-NUMBER counts tabs from the end of the tab 
bar."
             ;; set-window-configuration does not restore the value of
             ;; point in the current buffer, so restore it separately.
             (when (and (markerp wc-point)
-                       (marker-buffer wc-point)
-                       ;; FIXME: After dired-revert, marker relocates to 1.
-                       ;; window-configuration restores point to global point
-                       ;; in this dired buffer, not to its window point,
-                       ;; but this is slightly better than 1.
-                       ;; Maybe better to save dired-filename in each window?
-                       (not (eq 1 (marker-position wc-point))))
+                       (marker-buffer wc-point))
               (goto-char wc-point))
 
             (when wc-bl  (set-frame-parameter nil 'buffer-list wc-bl))
diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 4637dafcd90..cc60f94c9c5 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -1,6 +1,6 @@
 ;;; tab-line.el --- window-local tabs with window buffers -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Juri Linkov <juri@linkov.net>
 ;; Keywords: windows tabs
@@ -958,6 +958,8 @@ sight of the tab line."
 
 ;;; Touch screen support.
 
+(defvar touch-screen-delay)
+
 (defun tab-line-track-tap (event &optional function)
   "Track a tap starting from EVENT.
 If EVENT is not a `touchscreen-begin' event, return t.
diff --git a/lisp/tabify.el b/lisp/tabify.el
index 019c83cf7df..37a3ec65c4b 100644
--- a/lisp/tabify.el
+++ b/lisp/tabify.el
@@ -1,6 +1,6 @@
 ;;; tabify.el --- tab conversion commands for Emacs  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985, 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Package: emacs
diff --git a/lisp/talk.el b/lisp/talk.el
index 46c36c0b6e5..b19b1f46378 100644
--- a/lisp/talk.el
+++ b/lisp/talk.el
@@ -1,6 +1,6 @@
 ;;; talk.el --- allow several users to talk to each other through Emacs  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: comm, frames
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
index 2b6329fecc3..375191a8167 100644
--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -1,6 +1,6 @@
 ;;; tar-mode.el --- simple editing of tar files from GNU Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1990-1991, 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1991, 1993-2024 Free Software Foundation, Inc.
 
 ;; Author: Jamie Zawinski <jwz@lucid.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/tempo.el b/lisp/tempo.el
index 45dc24dcc97..b7ad680c2a9 100644
--- a/lisp/tempo.el
+++ b/lisp/tempo.el
@@ -1,6 +1,6 @@
 ;;; tempo.el --- Flexible template insertion -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1994-1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: David Kågedal <davidk@lysator.liu.se>
 ;; Created: 16 Feb 1994
@@ -164,7 +164,7 @@ documentation for the function `tempo-complete-tag' for 
more info.
   "Indicates if the tag collection needs to be rebuilt.")
 
 (defvar-local tempo-marks nil
-  "A list of marks to jump to with `\\[tempo-forward-mark]' and 
`\\[tempo-backward-mark]'.")
+  "A list of marks to jump to with \\[tempo-forward-mark] and 
\\[tempo-backward-mark].")
 
 (defvar-local tempo-match-finder "\\b\\([[:word:]]+\\)\\="
   "The regexp or function used to find the string to match against tags.
@@ -198,6 +198,10 @@ This is an abnormal hook where the functions are called 
with one argument
 (defvar-local tempo-region-start (make-marker)
   "Region start when inserting around the region.")
 
+;; Insertion by the template at the region start position should move
+;; the marker to preserve the original region contents.
+(set-marker-insertion-type tempo-region-start t)
+
 (defvar-local tempo-region-stop (make-marker)
   "Region stop when inserting around the region.")
 
@@ -333,7 +337,8 @@ possible."
     (`(r> . ,rest) (if on-region
                        (progn
                          (goto-char tempo-region-stop)
-                         (indent-region (mark) (point) nil))
+                         (indent-region tempo-region-start
+                                        tempo-region-stop))
                        (tempo-insert-prompt-compat rest)))
     (`(s ,name) (tempo-insert-named name))
     (`(l . ,rest) (dolist (elt rest) (tempo-insert elt on-region)))
@@ -344,7 +349,7 @@ possible."
     ('r> (if on-region
             (progn
               (goto-char tempo-region-stop)
-              (indent-region (mark) (point) nil))
+              (indent-region tempo-region-start tempo-region-stop))
           (tempo-insert-mark (point-marker))))
     ('> (indent-according-to-mode))
     ('& (if (not (or (= (current-column) 0)
@@ -577,7 +582,7 @@ TAG-LIST is a symbol whose variable value is a tag list 
created with
 `tempo-add-tag'.
 
 COMPLETION-FUNCTION is an obsolete option for specifying an optional
-function or string that is used by `\\[tempo-complete-tag]' to find a
+function or string that is used by \\[tempo-complete-tag] to find a
 string to match the tag against.  It has the same definition as the
 variable `tempo-match-finder'.  In this version, supplying a
 COMPLETION-FUNCTION just sets `tempo-match-finder' locally."
diff --git a/lisp/term.el b/lisp/term.el
index b2875e4a17f..2ce0c2b5e79 100644
--- a/lisp/term.el
+++ b/lisp/term.el
@@ -1,6 +1,6 @@
 ;;; term.el --- general command interpreter in a window stuff -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1988, 1990, 1992, 1994-1995, 2001-2023 Free Software
+;; Copyright (C) 1988, 1990, 1992, 1994-1995, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Per Bothner <per@bothner.com>
@@ -1085,6 +1085,8 @@ underlying shell."
   (setq term-ansi-current-invisible nil)
   (setq term-ansi-current-bg-color 0))
 
+(defvar touch-screen-display-keyboard)
+
 (define-derived-mode term-mode fundamental-mode "Term"
   "Major mode for interacting with an inferior interpreter.
 The interpreter name is same as buffer name, sans the asterisks.
@@ -1107,7 +1109,7 @@ variable `term-input-autoexpand', and addition is 
controlled by the
 variable `term-input-ignoredups'.
 
 Input to, and output from, the subprocess can cause the window to scroll to
-the end of the buffer.  See variables `term-scroll-to-bottom-on-input',
+the end of the buffer.  See variables `term-scroll-snap-to-bottom',
 and `term-scroll-to-bottom-on-output'.
 
 If you accidentally suspend your process, use \\[term-continue-subjob]
@@ -1391,10 +1393,15 @@ Entry to this mode runs the hooks on `term-mode-hook'."
   (interactive)
    (term-send-raw-string (current-kill 0)))
 
-(defun term--xterm-paste ()
+(defun term--xterm-paste (event)
   "Insert the text pasted in an XTerm bracketed paste operation."
-  (interactive)
-  (term-send-raw-string (xterm--pasted-text)))
+  (interactive "e")
+  (unless (eq (car-safe event) 'xterm-paste)
+    (error "term--xterm-paste must be found to xterm-paste event"))
+  (let ((str (nth 1 event)))
+    (unless (stringp str)
+      (error "term--xterm-paste provided event does not contain paste text"))
+    (term-send-raw-string str)))
 
 (declare-function xterm--pasted-text "term/xterm" ())
 
diff --git a/lisp/term/AT386.el b/lisp/term/AT386.el
index 541b7c5aad0..6592fd3da45 100644
--- a/lisp/term/AT386.el
+++ b/lisp/term/AT386.el
@@ -1,6 +1,6 @@
 ;;; AT386.el --- terminal support package for IBM AT keyboards  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric S. Raymond <esr@thyrsus.com>
 ;; Keywords: terminals
diff --git a/lisp/term/README b/lisp/term/README
index 6940e30c002..32aab4af00d 100644
--- a/lisp/term/README
+++ b/lisp/term/README
@@ -1,4 +1,4 @@
-Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/lisp/term/android-win.el b/lisp/term/android-win.el
index 36470097b40..e0d252f17e0 100644
--- a/lisp/term/android-win.el
+++ b/lisp/term/android-win.el
@@ -1,6 +1,6 @@
 ;;; android-win.el --- terminal set up for Android  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF
 ;; Keywords: terminals, i18n, android
@@ -340,7 +340,7 @@ the `stop-selecting-text' editing key."
 
 
 ;; Splash screen notice.  Users are frequently left scratching their
-;; heads when they overlook the Android appendex in the Emacs manual
+;; heads when they overlook the Android appendix in the Emacs manual
 ;; and discover that external storage is not accessible; worse yet,
 ;; Android 11 and later veil the settings panel controlling such
 ;; permissions behind layer upon layer of largely immaterial settings
@@ -406,7 +406,7 @@ to grant such permissions.
 
 FANCY-P non-nil means the notice will be displayed with faces, in
 the style appropriate for its incorporation within the fancy splash
-screen display; see `francy-splash-insert'."
+screen display; see `fancy-splash-insert'."
   (unless (android-external-storage-available-p)
     (if fancy-p
         (fancy-splash-insert
@@ -417,7 +417,7 @@ been denied.  Click "
          :link '("here" android-display-storage-permission-popup)
          " to grant them.")
       (insert
-       "Permissions necessary to access external storage directories have been
+       "\nPermissions necessary to access external storage directories have 
been
 denied.  ")
       (insert-button "Click here to grant them."
                      'action #'android-display-storage-permission-popup
@@ -425,5 +425,60 @@ denied.  ")
       (newline))))
 
 
+;;; Locale preferences.
+
+(defvar android-os-language)
+
+(defun android-locale-for-system-language ()
+  "Return a locale representing the system language.
+This locale reflects the system's language preferences in its
+language name and country variant fields, and always specifies
+the UTF-8 coding system."
+  ;; android-os-language is a list comprising four elements LANGUAGE,
+  ;; COUNTRY, SCRIPT, and VARIANT.
+  ;;
+  ;; LANGUAGE and COUNTRY are ISO language and country codes identical
+  ;; to those stored within POSIX locales.
+  ;;
+  ;; SCRIPT is an ISO 15924 script tag, representing the script used
+  ;; if available, or if required to disambiguate between distinct
+  ;; writing systems for the same combination of language and country.
+  ;;
+  ;; VARIANT is an arbitrary string representing the variant of the
+  ;; LANGUAGE or SCRIPT represented.
+  ;;
+  ;; Each of these fields might be empty, but the locale is invalid if
+  ;; LANGUAGE is empty, which if true "en_US.UTF-8" is returned as a
+  ;; placeholder.
+  (let ((language (or (nth 0 android-os-language) ""))
+        (country (or (nth 1 android-os-language) ""))
+        (script (or (nth 2 android-os-language) ""))
+        (variant (or (nth 3 android-os-language) ""))
+        locale-base locale-modifier)
+    (if (string-empty-p language)
+        (setq locale-base "en_US.UTF-8")
+      (if (string-empty-p country)
+          (setq locale-base (concat language ".UTF-8"))
+        (setq locale-base (concat language "_" country
+                                  ".UTF-8"))))
+    ;; No straightforward relation between Java script and variant
+    ;; combinations exist: Java permits both a script and a variant to
+    ;; be supplied at once, whereas POSIX's closest analog "modifiers"
+    ;; permit only either an alternative script or a variant to be
+    ;; supplied.
+    ;;
+    ;; Emacs disregards variants besides "EURO" and scripts besides
+    ;; "Cyrl", for these two never coexist in existing locales, and
+    ;; their POSIX equivalents are the sole modifiers recognized by
+    ;; Emacs.
+    (if (string-equal script "Cyrl")
+        (setq locale-modifier "@cyrillic")
+      (if (string-equal variant "EURO")
+          (setq locale-modifier "@euro")
+        (setq locale-modifier "")))
+    ;; Return the concatenation of both these values.
+    (concat locale-base locale-modifier)))
+
+
 (provide 'android-win)
 ;; android-win.el ends here.
diff --git a/lisp/term/common-win.el b/lisp/term/common-win.el
index 38b3c580625..181dcc8e6d9 100644
--- a/lisp/term/common-win.el
+++ b/lisp/term/common-win.el
@@ -1,6 +1,6 @@
 ;;; common-win.el --- common part of handling window systems  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: terminals
diff --git a/lisp/term/fbterm.el b/lisp/term/fbterm.el
index d9981778dbe..834a45dac66 100644
--- a/lisp/term/fbterm.el
+++ b/lisp/term/fbterm.el
@@ -1,6 +1,6 @@
 ;;; fbterm.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Note that, in some versions of fbterm, the TERM environment
 ;; variable is set to "linux".  When that's the case, the code below
diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el
index f53cf7939b9..efc0a129062 100644
--- a/lisp/term/haiku-win.el
+++ b/lisp/term/haiku-win.el
@@ -1,6 +1,6 @@
 ;;; haiku-win.el --- set up windowing on Haiku -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/term/internal.el b/lisp/term/internal.el
index 14ebb0f6609..8c0e50e20b3 100644
--- a/lisp/term/internal.el
+++ b/lisp/term/internal.el
@@ -1,6 +1,6 @@
 ;;; internal.el --- support for PC internal terminal  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1993-1994, 1998-1999, 2001-2023 Free Software
+;; Copyright (C) 1993-1994, 1998-1999, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Morten Welinder <terra@diku.dk>
diff --git a/lisp/term/iris-ansi.el b/lisp/term/iris-ansi.el
index abe7282f823..a07927000e7 100644
--- a/lisp/term/iris-ansi.el
+++ b/lisp/term/iris-ansi.el
@@ -1,6 +1,6 @@
 ;;; iris-ansi.el --- configure Emacs for SGI xwsh and winterm apps  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Dan Nicolaescu <dann@ics.uci.edu>
 
diff --git a/lisp/term/konsole.el b/lisp/term/konsole.el
index 7db3695f5d0..1aff9df29ea 100644
--- a/lisp/term/konsole.el
+++ b/lisp/term/konsole.el
@@ -1,5 +1,5 @@
 ;;; konsole.el --- terminal initialization for konsole  -*- lexical-binding:t 
-*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 (require 'term/xterm)
 
diff --git a/lisp/term/linux.el b/lisp/term/linux.el
index f24af3f1344..491649a053d 100644
--- a/lisp/term/linux.el
+++ b/lisp/term/linux.el
@@ -13,9 +13,13 @@
   ;; Compositions confuse cursor movement.
   (setq-default auto-composition-mode "linux")
 
+  ;; Ensure additional terminal setup is done when `gpm-mouse-mode' is
+  ;; enabled.
+  (ignore-errors (when gpm-mouse-mode (gpm-mouse-mode 1)))
+
   ;; Don't translate ESC TAB to backtab as directed by ncurses-6.3.
   (define-key input-decode-map "\e\t" nil)
-  
+
   ;; Make Latin-1 input characters work, too.
   ;; Meta will continue to work, because the kernel turns that into Escape.
 
diff --git a/lisp/term/news.el b/lisp/term/news.el
index f2fd814d438..dfcfd8ac04b 100644
--- a/lisp/term/news.el
+++ b/lisp/term/news.el
@@ -1,6 +1,6 @@
 ;;; news.el --- keypad and function key bindings for the Sony NEWS keyboard  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1989, 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF
 ;; Keywords: terminals
diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el
index e40a0ce3e96..2a29457133e 100644
--- a/lisp/term/ns-win.el
+++ b/lisp/term/ns-win.el
@@ -1,6 +1,6 @@
 ;;; ns-win.el --- lisp side of interface with NeXT/Open/GNUstep/macOS window 
system  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1993-1994, 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2005-2024 Free Software Foundation, Inc.
 
 ;; Authors: Carl Edman
 ;;     Christian Limpach
diff --git a/lisp/term/pc-win.el b/lisp/term/pc-win.el
index 589a2dc85e0..92d65c75816 100644
--- a/lisp/term/pc-win.el
+++ b/lisp/term/pc-win.el
@@ -1,6 +1,6 @@
 ;;; pc-win.el --- setup support for `PC windows' (whatever that is)  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1994, 1996-1997, 1999, 2001-2023 Free Software
+;; Copyright (C) 1994, 1996-1997, 1999, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Morten Welinder <terra@diku.dk>
@@ -47,7 +47,7 @@
 
 ;; This was copied from etc/rgb.txt, except that some values were changed
 ;; a bit to make them consistent with DOS console colors, and the RGB
-;; values were scaled up to 16 bits, as `tty-define-color' requires.
+;; values were scaled up to 16 bits, as `tty-color-define' requires.
 ;;;
 ;; The mapping between the 16 standard EGA/VGA colors and X color names
 ;; was done by running a Unix version of Emacs inside an X client and a
diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el
index ef854a28278..7999d348082 100644
--- a/lisp/term/pgtk-win.el
+++ b/lisp/term/pgtk-win.el
@@ -1,6 +1,6 @@
 ;;; pgtk-win.el --- parse relevant switches and set up for Pure-GTK  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1995, 2001-2020, 2022-2023 Free Software Foundation,
+;; Copyright (C) 1995, 2001-2020, 2022-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: FSF
diff --git a/lisp/term/rxvt.el b/lisp/term/rxvt.el
index af1ea36ff7d..b16cf5ec189 100644
--- a/lisp/term/rxvt.el
+++ b/lisp/term/rxvt.el
@@ -1,6 +1,6 @@
 ;;; rxvt.el --- define function key sequences and standard colors for rxvt  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Eli Zaretskii
 ;; Keywords: terminals
diff --git a/lisp/term/screen.el b/lisp/term/screen.el
index 912664f2bae..8ca0755d545 100644
--- a/lisp/term/screen.el
+++ b/lisp/term/screen.el
@@ -1,5 +1,5 @@
 ;;; screen.el --- terminal initialization for screen and tmux  -*- 
lexical-binding: t -*-
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 (require 'term/xterm)
 
diff --git a/lisp/term/st.el b/lisp/term/st.el
index 334acdba560..ba10134289f 100644
--- a/lisp/term/st.el
+++ b/lisp/term/st.el
@@ -1,6 +1,6 @@
 ;;; st.el --- terminal initialization for st  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;;; Commentary:
 
diff --git a/lisp/term/sun.el b/lisp/term/sun.el
index 2189c394bfc..f9dc0ba5dd1 100644
--- a/lisp/term/sun.el
+++ b/lisp/term/sun.el
@@ -1,6 +1,6 @@
 ;;; sun.el --- keybinding for standard default sunterm keys  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1987, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Jeff Peck <peck@sun.com>
 ;; Keywords: terminals
diff --git a/lisp/term/tmux.el b/lisp/term/tmux.el
index 5dba3aa4ebe..3776367b7ae 100644
--- a/lisp/term/tmux.el
+++ b/lisp/term/tmux.el
@@ -1,5 +1,5 @@
 ;;; tmux.el --- terminal initialization for tmux  -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 (require 'term/xterm)
 
diff --git a/lisp/term/tty-colors.el b/lisp/term/tty-colors.el
index cb7ff385ce7..0ffd06f9099 100644
--- a/lisp/term/tty-colors.el
+++ b/lisp/term/tty-colors.el
@@ -1,6 +1,6 @@
 ;;; tty-colors.el --- color support for character terminals  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Eli Zaretskii
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/term/tvi970.el b/lisp/term/tvi970.el
index 5f6e1a20f85..63598c20f9f 100644
--- a/lisp/term/tvi970.el
+++ b/lisp/term/tvi970.el
@@ -1,6 +1,6 @@
 ;;; tvi970.el --- terminal support for the Televideo 970  -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Jim Blandy <jimb@occs.cs.oberlin.edu>
 ;; Keywords: terminals
diff --git a/lisp/term/vt100.el b/lisp/term/vt100.el
index 1275556b9cb..e8c7a03844d 100644
--- a/lisp/term/vt100.el
+++ b/lisp/term/vt100.el
@@ -1,6 +1,6 @@
 ;;; vt100.el --- define VT100 function key sequences in function-key-map  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1989, 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF
 ;; Keywords: terminals
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el
index 4f1fd475392..9b696475c34 100644
--- a/lisp/term/w32-win.el
+++ b/lisp/term/w32-win.el
@@ -1,6 +1,6 @@
 ;;; w32-win.el --- parse switches controlling interface with W32 window system 
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Kevin Gallo
 ;; Keywords: terminals
diff --git a/lisp/term/w32console.el b/lisp/term/w32console.el
index 396d80040ed..129452e5439 100644
--- a/lisp/term/w32console.el
+++ b/lisp/term/w32console.el
@@ -1,6 +1,6 @@
 ;;; w32console.el --- Setup w32 console keys and colors.  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF
 ;; Keywords: terminals
diff --git a/lisp/term/wyse50.el b/lisp/term/wyse50.el
index 5fe3e7fce31..a0b403e4044 100644
--- a/lisp/term/wyse50.el
+++ b/lisp/term/wyse50.el
@@ -1,6 +1,6 @@
 ;;; wyse50.el --- terminal support code for Wyse 50  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1989, 1993-1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1989, 1993-1994, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>,
diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el
index a9af6bd6d1c..98dd576fea2 100644
--- a/lisp/term/x-win.el
+++ b/lisp/term/x-win.el
@@ -1,6 +1,6 @@
 ;;; x-win.el --- parse relevant switches and set up for X  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF
 ;; Keywords: terminals, i18n
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el
index 5ed4e46e0a5..82f9a60b53b 100644
--- a/lisp/term/xterm.el
+++ b/lisp/term/xterm.el
@@ -1,6 +1,6 @@
 ;;; xterm.el --- define function key sequences and standard colors for xterm  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF
 ;; Keywords: terminals
diff --git a/lisp/textmodes/artist.el b/lisp/textmodes/artist.el
index 08613db600c..b6029dc1ffd 100644
--- a/lisp/textmodes/artist.el
+++ b/lisp/textmodes/artist.el
@@ -1,6 +1,6 @@
 ;;; artist.el --- draw ascii graphics with your mouse -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author:       Tomas Abrahamsson <tab@lysator.liu.se>
 ;; Keywords:     mouse
diff --git a/lisp/textmodes/bib-mode.el b/lisp/textmodes/bib-mode.el
index 7037cabffc5..ea5e02b25f6 100644
--- a/lisp/textmodes/bib-mode.el
+++ b/lisp/textmodes/bib-mode.el
@@ -1,6 +1,6 @@
 ;;; bib-mode.el --- major mode for editing bib files  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1989, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Henry Kautz
 ;; (according to authors.el)
diff --git a/lisp/textmodes/bibtex-style.el b/lisp/textmodes/bibtex-style.el
index 649f1831558..78c53bfc37d 100644
--- a/lisp/textmodes/bibtex-style.el
+++ b/lisp/textmodes/bibtex-style.el
@@ -1,6 +1,6 @@
 ;;; bibtex-style.el --- Major mode for BibTeX Style files -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: tex
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el
index 32d2786b86c..a8e2f03bd70 100644
--- a/lisp/textmodes/bibtex.el
+++ b/lisp/textmodes/bibtex.el
@@ -1,6 +1,6 @@
 ;;; bibtex.el --- BibTeX mode for GNU Emacs -*- lexical-binding: t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Schoef <schoef@offis.uni-oldenburg.de>
 ;;      Bengt Martensson <bengt@mathematik.uni-Bremen.de>
@@ -1837,7 +1837,7 @@ Initialized by `bibtex-set-dialect'.")
     (bibtex-font-lock-url) (bibtex-font-lock-crossref)
     ;; cite
     ,@(mapcar (lambda (matcher)
-                `((lambda (bound) (bibtex-font-lock-cite ',matcher bound))))
+                `(,(lambda (bound) (bibtex-font-lock-cite matcher bound))))
               bibtex-cite-matcher-alist))
   "Default expressions to highlight in BibTeX mode.")
 
@@ -2760,7 +2760,7 @@ Formats current entry according to variable 
`bibtex-entry-format'."
                           (setq error-field-name
                                  (car (last (aref alt-fields idx))))
                           (user-error "Alternative mandatory fields `%s' are 
missing"
-                                       (mapconcat 'identity
+                                       (mapconcat #'identity
                                                   (reverse
                                                    (aref alt-expect idx))
                                                   ", ")))
@@ -2768,7 +2768,7 @@ Formats current entry according to variable 
`bibtex-entry-format'."
                           (setq error-field-name
                                  (car (last (aref alt-fields idx))))
                           (user-error "Fields `%s' are alternatives"
-                                       (mapconcat 'identity
+                                       (mapconcat #'identity
                                                   (reverse
                                                    (aref alt-fields idx))
                                                   ", ")))))))
@@ -3624,7 +3624,7 @@ if that value is non-nil.
   (unless bibtex-parse-idle-timer
     (setq bibtex-parse-idle-timer (run-with-idle-timer
                                    bibtex-parse-keys-timeout t
-                                   'bibtex-parse-buffers-stealthily)))
+                                   #'bibtex-parse-buffers-stealthily)))
   (setq-local paragraph-start "[ \f\n\t]*$")
   (setq-local comment-column 0)
   (setq-local defun-prompt-regexp "^[ \t]*@[[:alnum:]]+[ \t]*")
@@ -3829,7 +3829,7 @@ for the templates of `bibtex-entry', whereas entry 
validation performed by
       (if (and (nth 3 elt)
                (<= 0 (nth 3 elt)))
           (push (nth 3 elt) alt-list)))
-    (setq alt-list (sort alt-list '<))
+    (setq alt-list (sort alt-list #'<))
     ;; Skip aliases.  If ELT is marked as "proper alternative", but all
     ;; alternatives for field ELT are aliases, we do not label ELT
     ;; as an alternative either.
@@ -4641,7 +4641,7 @@ Return t if test was successful, nil otherwise."
         (let ((file (file-name-nondirectory (buffer-file-name)))
               (dir default-directory)
               (err-buf "*BibTeX validation errors*"))
-          (setq error-list (sort error-list 'car-less-than-car))
+          (setq error-list (sort error-list #'car-less-than-car))
           (with-current-buffer (get-buffer-create err-buf)
             (setq default-directory dir)
             (unless (eq major-mode 'compilation-mode) (compilation-mode))
@@ -4714,7 +4714,7 @@ Return t if test was successful, nil otherwise."
               (delete-region (point-min) (point-max))
               (insert (substitute-command-keys
                       "BibTeX mode command `bibtex-validate-globally'\n\n"))
-              (dolist (err (sort error-list 'string-lessp)) (insert err))
+              (dolist (err (sort error-list #'string-lessp)) (insert err))
               (set-buffer-modified-p nil))
             (goto-char (point-min))
             (forward-line 2)) ; first error message
diff --git a/lisp/textmodes/conf-mode.el b/lisp/textmodes/conf-mode.el
index 4d0dde7752b..5e1636033f6 100644
--- a/lisp/textmodes/conf-mode.el
+++ b/lisp/textmodes/conf-mode.el
@@ -1,6 +1,6 @@
 ;;; conf-mode.el --- Simple major mode for editing conf/ini/properties files  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
 ;; Keywords: conf ini windows java
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index f51edfb4c80..425f3ec8a30 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -1,6 +1,6 @@
 ;;; css-mode.el --- Major mode to edit CSS files  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Maintainer: Simen Heggestøyl <simenheg@gmail.com>
diff --git a/lisp/textmodes/dns-mode.el b/lisp/textmodes/dns-mode.el
index bc3fa8d8e3a..c801010d768 100644
--- a/lisp/textmodes/dns-mode.el
+++ b/lisp/textmodes/dns-mode.el
@@ -1,6 +1,6 @@
 ;;; dns-mode.el --- a mode for viewing/editing Domain Name System master files 
 -*- lexical-binding: t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <simon@josefsson.org>
 ;; Keywords: DNS master zone file SOA comm
diff --git a/lisp/textmodes/emacs-authors-mode.el 
b/lisp/textmodes/emacs-authors-mode.el
index 248234b1db1..4609f93869f 100644
--- a/lisp/textmodes/emacs-authors-mode.el
+++ b/lisp/textmodes/emacs-authors-mode.el
@@ -1,6 +1,6 @@
 ;;; emacs-authors-mode.el --- font-locking for etc/AUTHORS  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 ;; Keywords: internal
diff --git a/lisp/textmodes/emacs-news-mode.el 
b/lisp/textmodes/emacs-news-mode.el
index 773b07764aa..1dd017abb01 100644
--- a/lisp/textmodes/emacs-news-mode.el
+++ b/lisp/textmodes/emacs-news-mode.el
@@ -1,6 +1,6 @@
 ;;; emacs-news-mode.el --- major mode to edit and view the NEWS file -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Keywords: tools
 
diff --git a/lisp/textmodes/enriched.el b/lisp/textmodes/enriched.el
index 004b844a3e7..385674f5b1a 100644
--- a/lisp/textmodes/enriched.el
+++ b/lisp/textmodes/enriched.el
@@ -1,9 +1,9 @@
 ;;; enriched.el --- read and save files in text/enriched format  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1994-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Boris Goldowsky <boris@gnu.org>
-;; Keywords: wp, faces
+;; Keywords: text, faces
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el
index 4d6c73bfdd6..29c56f8feaf 100644
--- a/lisp/textmodes/fill.el
+++ b/lisp/textmodes/fill.el
@@ -1,10 +1,10 @@
 ;;; fill.el --- fill commands for Emacs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1985-1986, 1992, 1994-1997, 1999, 2001-2023 Free
+;; Copyright (C) 1985-1986, 1992, 1994-1997, 1999, 2001-2024 Free
 ;; Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
-;; Keywords: wp
+;; Keywords: text
 ;; Package: emacs
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/textmodes/flyspell.el b/lisp/textmodes/flyspell.el
index 1ca508e14ef..de59294e9f0 100644
--- a/lisp/textmodes/flyspell.el
+++ b/lisp/textmodes/flyspell.el
@@ -1,6 +1,6 @@
 ;;; flyspell.el --- On-the-fly spell checker  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Manuel Serrano <Manuel.Serrano@sophia.inria.fr>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/glyphless-mode.el b/lisp/textmodes/glyphless-mode.el
index eb4447f3048..6f8363a3b67 100644
--- a/lisp/textmodes/glyphless-mode.el
+++ b/lisp/textmodes/glyphless-mode.el
@@ -1,6 +1,6 @@
 ;;; glyphless-mode.el --- minor mode for displaying glyphless characters  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 
diff --git a/lisp/textmodes/html-ts-mode.el b/lisp/textmodes/html-ts-mode.el
index d08d899c815..301f3e8791c 100644
--- a/lisp/textmodes/html-ts-mode.el
+++ b/lisp/textmodes/html-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; html-ts-mode.el --- tree-sitter support for HTML  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author     : Theodor Thornhill <theo@thornhill.no>
 ;; Maintainer : Theodor Thornhill <theo@thornhill.no>
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index 4c3b22281bd..17af1f1d926 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -1,6 +1,6 @@
 ;;; ispell.el --- interface to spell checkers  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1994-1995, 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1995, 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Ken Stevens <k.stevens@ieee.org>
 
@@ -522,7 +522,12 @@ re-start Emacs."
      
"[^A-Za-z\345\344\366\351\340\374\350\346\370\347\305\304\326\311\300\334\310\306\330\307]"
      "[']" nil ("-C") "~list" iso-8859-1)
     ("hebrew" 
"[\340\341\342\343\344\345\346\347\350\351\353\352\354\356\355\360\357\361\362\364\363\367\366\365\370\371\372]"
 
"[^\340\341\342\343\344\345\346\347\350\351\353\352\354\356\355\360\357\361\362\364\363\367\366\365\370\371\372]"
 "" nil ("-B") nil cp1255))
-  "Base value for `ispell-dictionary-alist'.")
+  "Base value for `ispell-dictionary-alist'.
+
+Note that when the speller program is \"aspell\" or \"hunspell\",
+some parts of the database, notably OTHERCHARS, will be overridden
+by parsing the dictionary data files, see `ispell-aspell-find-dictionary'
+and `ispell-parse-hunspell-affix-file'.")
 
 (defvar ispell-dictionary-alist nil
   "An alist of dictionaries and their associated parameters.
@@ -577,7 +582,11 @@ when the language uses non-ASCII characters.
 Note that with \"ispell\" as the speller, the CASECHARS and
 OTHERCHARS slots of the alist should contain the same character
 set as casechars and otherchars in the LANGUAGE.aff file \(e.g.,
-english.aff).  Aspell and Hunspell don't have this limitation.")
+english.aff).  Aspell and Hunspell don't have this limitation.
+Also, when the speller program is \"aspell\" or \"hunspell\",
+some parts of the database, notably OTHERCHARS, will be determined
+by parsing the dictionary data files, see `ispell-aspell-find-dictionary'
+and `ispell-parse-hunspell-affix-file'.")
 
 (defvar ispell-really-aspell nil
   "Non-nil if we can use Aspell extensions.")
@@ -3699,7 +3708,6 @@ If APPEND is non-nil, don't erase previous debugging 
output."
              (setcdr cur (cddr cur)))
            (setq cur (cdr cur)))
          (list beg end (cdr all)
-               :annotation-function (lambda (_) " Dictionary word")
                :exclusive 'no))))))
 
 
diff --git a/lisp/textmodes/less-css-mode.el b/lisp/textmodes/less-css-mode.el
index 2e4d71fb631..198f067f1d8 100644
--- a/lisp/textmodes/less-css-mode.el
+++ b/lisp/textmodes/less-css-mode.el
@@ -1,6 +1,6 @@
 ;;; less-css-mode.el --- Major mode for editing Less CSS files  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Steve Purcell <steve@sanityinc.com>
 ;; Maintainer: Simen Heggestøyl <simenheg@gmail.com>
diff --git a/lisp/textmodes/makeinfo.el b/lisp/textmodes/makeinfo.el
index 16821944145..7e08111fddd 100644
--- a/lisp/textmodes/makeinfo.el
+++ b/lisp/textmodes/makeinfo.el
@@ -1,6 +1,6 @@
 ;;; makeinfo.el --- run makeinfo conveniently  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1991, 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 1993, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Robert J. Chassell
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/mhtml-mode.el b/lisp/textmodes/mhtml-mode.el
index ebb55ec279c..0b5c6756ab9 100644
--- a/lisp/textmodes/mhtml-mode.el
+++ b/lisp/textmodes/mhtml-mode.el
@@ -1,8 +1,8 @@
 ;;; mhtml-mode.el --- HTML editing mode that handles CSS and JS -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
-;; Keywords: wp, hypermedia, comm, languages
+;; Keywords: text, hypermedia, comm, languages
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/textmodes/nroff-mode.el b/lisp/textmodes/nroff-mode.el
index 7374fa63bec..026d37f1b74 100644
--- a/lisp/textmodes/nroff-mode.el
+++ b/lisp/textmodes/nroff-mode.el
@@ -1,9 +1,9 @@
 ;;; nroff-mode.el --- GNU Emacs major mode for editing nroff source  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
-;; Keywords: wp
+;; Keywords: text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/textmodes/page-ext.el b/lisp/textmodes/page-ext.el
index 446112bce27..f5f59adb0cf 100644
--- a/lisp/textmodes/page-ext.el
+++ b/lisp/textmodes/page-ext.el
@@ -1,10 +1,10 @@
 ;;; page-ext.el --- extended page handling commands  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1990-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-2024 Free Software Foundation, Inc.
 
 ;; Author: Robert J. Chassell <bob@gnu.org>
 ;; (according to ack.texi)
-;; Keywords: wp data
+;; Keywords: text data
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/textmodes/page.el b/lisp/textmodes/page.el
index 86a2762b0ee..a5de354fc0a 100644
--- a/lisp/textmodes/page.el
+++ b/lisp/textmodes/page.el
@@ -1,9 +1,9 @@
 ;;; page.el --- page motion commands for Emacs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
-;; Keywords: wp convenience
+;; Keywords: text convenience
 ;; Package: emacs
 
 ;; This file is part of GNU Emacs.
@@ -159,21 +159,23 @@ point, respectively."
              total before after)))
 
 (defun page--what-page ()
-  "Return a list of the page and line number of point."
+  "Return a list of the page and line number of point.
+The line number is relative to the start of the page."
   (save-restriction
     (widen)
     (save-excursion
       (let ((count 1)
+            (adjust (if (or (bolp) (looking-back page-delimiter nil)) 1 0))
             (opoint (point)))
         (goto-char (point-min))
         (while (re-search-forward page-delimiter opoint t)
           (when (= (match-beginning 0) (match-end 0))
             (forward-char))
           (setq count (1+ count)))
-        (list count (line-number-at-pos opoint))))))
+        (list count (+ adjust (count-lines (point) opoint)))))))
 
 (defun what-page ()
-  "Print page and line number of point."
+  "Display the page number, and the line number within that page."
   (interactive)
   (apply #'message (cons "Page %d, line %d" (page--what-page))))
 
diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el
index fd28bfe8016..af99a96e045 100644
--- a/lisp/textmodes/paragraphs.el
+++ b/lisp/textmodes/paragraphs.el
@@ -1,10 +1,10 @@
 ;;; paragraphs.el --- paragraph and sentence parsing  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1985-1987, 1991, 1994-1997, 1999-2023 Free Software
+;; Copyright (C) 1985-1987, 1991, 1994-1997, 1999-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
-;; Keywords: wp
+;; Keywords: text
 ;; Package: emacs
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/textmodes/picture.el b/lisp/textmodes/picture.el
index f98c3963b6f..adb06cb6a29 100644
--- a/lisp/textmodes/picture.el
+++ b/lisp/textmodes/picture.el
@@ -1,10 +1,10 @@
 ;;; picture.el --- "Picture mode" -- editing using quarter-plane screen model 
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Author: K. Shane Hartman
 ;; Maintainer: emacs-devel@gnu.org
-;; Keywords: convenience wp
+;; Keywords: convenience text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/textmodes/pixel-fill.el b/lisp/textmodes/pixel-fill.el
index 9fd62d98fd6..d26eaec2111 100644
--- a/lisp/textmodes/pixel-fill.el
+++ b/lisp/textmodes/pixel-fill.el
@@ -1,6 +1,6 @@
 ;;; pixel-fill.el --- variable pitch filling functions  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: filling
@@ -73,39 +73,41 @@ lines that are visually wider than PIXEL-WIDTH.
 If START isn't at the start of a line, the horizontal position of
 START, converted to pixel units, will be used as the indentation
 prefix on subsequent lines."
-  (save-excursion
-    (goto-char start)
-    (let ((indentation
-           (car (window-text-pixel-size nil (line-beginning-position)
-                                        (point))))
-          (newline-end nil))
-      (when (> indentation pixel-width)
-        (error "The indentation (%s) is wider than the fill width (%s)"
-               indentation pixel-width))
-      (save-restriction
-        (narrow-to-region start end)
-        (goto-char (point-max))
-        (when (looking-back "\n[ \t]*" (point-min))
-          (setq newline-end t))
-        (goto-char (point-min))
-        ;; First replace all whitespace with space.
-        (while (re-search-forward "[ \t\n]+" nil t)
-          (cond
-           ((or (= (match-beginning 0) start)
-                (= (match-end 0) end))
-            (delete-region (match-beginning 0) (match-end 0)))
-           ;; If there's just a single space here, don't replace.
-           ((not (and (= (- (match-end 0) (match-beginning 0)) 1)
-                      (= (char-after (match-beginning 0)) ?\s)))
-            (replace-match
-             ;; We need to use a space that has an appropriate width.
-             (propertize " " 'face
-                         (get-text-property (match-beginning 0) 'face))))))
-        (goto-char start)
-        (pixel-fill--fill-line pixel-width indentation)
-        (goto-char (point-max))
-        (when newline-end
-          (insert "\n"))))))
+  (save-window-excursion
+    (set-window-buffer nil (current-buffer))
+    (save-excursion
+      (goto-char start)
+      (let ((indentation
+             (car (window-text-pixel-size nil (line-beginning-position)
+                                          (point))))
+            (newline-end nil))
+        (when (> indentation pixel-width)
+          (error "The indentation (%s) is wider than the fill width (%s)"
+                 indentation pixel-width))
+        (save-restriction
+          (narrow-to-region start end)
+          (goto-char (point-max))
+          (when (looking-back "\n[ \t]*" (point-min))
+            (setq newline-end t))
+          (goto-char (point-min))
+          ;; First replace all whitespace with space.
+          (while (re-search-forward "[ \t\n]+" nil t)
+            (cond
+             ((or (= (match-beginning 0) start)
+                  (= (match-end 0) end))
+              (delete-region (match-beginning 0) (match-end 0)))
+             ;; If there's just a single space here, don't replace.
+             ((not (and (= (- (match-end 0) (match-beginning 0)) 1)
+                        (= (char-after (match-beginning 0)) ?\s)))
+              (replace-match
+               ;; We need to use a space that has an appropriate width.
+               (propertize " " 'face
+                           (get-text-property (match-beginning 0) 'face))))))
+          (goto-char start)
+          (pixel-fill--fill-line pixel-width indentation)
+          (goto-char (point-max))
+          (when newline-end
+            (insert "\n")))))))
 
 (defun pixel-fill--goto-pixel (width)
   (vertical-motion (cons (/ width (frame-char-width)) 0)))
diff --git a/lisp/textmodes/po.el b/lisp/textmodes/po.el
index f9d2198b7fc..a1ac5005bc0 100644
--- a/lisp/textmodes/po.el
+++ b/lisp/textmodes/po.el
@@ -1,6 +1,6 @@
 ;;; po.el --- basic support of PO translation files  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1995-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Authors: François Pinard <pinard@iro.umontreal.ca>,
 ;;          Greg McGary <gkm@magilla.cichlid.com>,
diff --git a/lisp/textmodes/refbib.el b/lisp/textmodes/refbib.el
index 8f187e745c8..dd548e00d9b 100644
--- a/lisp/textmodes/refbib.el
+++ b/lisp/textmodes/refbib.el
@@ -1,6 +1,6 @@
 ;;; refbib.el --- convert refer-style references to ones usable by Latex bib  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1989, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Henry Kautz <kautz@research.att.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/refer.el b/lisp/textmodes/refer.el
index 9200c401226..0fbe4a30b11 100644
--- a/lisp/textmodes/refer.el
+++ b/lisp/textmodes/refer.el
@@ -1,6 +1,6 @@
 ;;; refer.el --- look up references in bibliography files  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1992, 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1996, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Ashwin Ram <ashwin@cc.gatech.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/refill.el b/lisp/textmodes/refill.el
index bd8e7cd7435..63789e887e2 100644
--- a/lisp/textmodes/refill.el
+++ b/lisp/textmodes/refill.el
@@ -1,10 +1,10 @@
 ;;; refill.el --- `auto-fill' by refilling paragraphs on changes  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Maintainer: Miles Bader <miles@gnu.org>
-;; Keywords: wp
+;; Keywords: text
 
 ;; This file is part of GNU Emacs.
 
@@ -106,10 +106,10 @@ This is used to optimize refilling.")
     ;; FIXME: forward-paragraph seems to disregard `use-hard-newlines',
     ;; leading to excessive refilling and wrong choice of fill-prefix.
     ;; might be a bug in my paragraphs.el.
-    (forward-paragraph)
+    (fill-forward-paragraph 1)
     (skip-syntax-backward "-")
     (let ((end (point))
-         (beg (progn (backward-paragraph) (point)))
+         (beg (progn (fill-forward-paragraph -1) (point)))
          (obeg (overlay-start refill-ignorable-overlay))
          (oend (overlay-end refill-ignorable-overlay)))
       (unless (> beg pos)      ;Don't fill if point is outside the paragraph.
diff --git a/lisp/textmodes/reftex-auc.el b/lisp/textmodes/reftex-auc.el
index 680d9d28df9..1c8be18a06d 100644
--- a/lisp/textmodes/reftex-auc.el
+++ b/lisp/textmodes/reftex-auc.el
@@ -1,6 +1,6 @@
 ;;; reftex-auc.el --- RefTeX's interface to AUCTeX  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@science.uva.nl>
 ;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-cite.el b/lisp/textmodes/reftex-cite.el
index eaa03c96fe9..f7b155874de 100644
--- a/lisp/textmodes/reftex-cite.el
+++ b/lisp/textmodes/reftex-cite.el
@@ -1,6 +1,6 @@
 ;;; reftex-cite.el --- creating citations with RefTeX  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@science.uva.nl>
 ;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-dcr.el b/lisp/textmodes/reftex-dcr.el
index c3ecea3acda..2c5e5cb7ce6 100644
--- a/lisp/textmodes/reftex-dcr.el
+++ b/lisp/textmodes/reftex-dcr.el
@@ -1,6 +1,6 @@
 ;;; reftex-dcr.el --- viewing cross references and citations with RefTeX  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@science.uva.nl>
 ;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-global.el b/lisp/textmodes/reftex-global.el
index b8b0ae6a061..0eaffec3b54 100644
--- a/lisp/textmodes/reftex-global.el
+++ b/lisp/textmodes/reftex-global.el
@@ -1,6 +1,6 @@
 ;;; reftex-global.el --- operations on entire documents with RefTeX  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@science.uva.nl>
 ;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-index.el b/lisp/textmodes/reftex-index.el
index 7cb15c7e99a..a93afd63855 100644
--- a/lisp/textmodes/reftex-index.el
+++ b/lisp/textmodes/reftex-index.el
@@ -1,6 +1,6 @@
 ;;; reftex-index.el --- index support with RefTeX  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@science.uva.nl>
 ;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-parse.el b/lisp/textmodes/reftex-parse.el
index e2b9a0d983e..9694a1364d3 100644
--- a/lisp/textmodes/reftex-parse.el
+++ b/lisp/textmodes/reftex-parse.el
@@ -1,6 +1,6 @@
 ;;; reftex-parse.el --- parser functions for RefTeX  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@science.uva.nl>
 ;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-ref.el b/lisp/textmodes/reftex-ref.el
index 64cf3fa4bbb..8dab7e6c48f 100644
--- a/lisp/textmodes/reftex-ref.el
+++ b/lisp/textmodes/reftex-ref.el
@@ -1,6 +1,6 @@
 ;;; reftex-ref.el --- code to create labels and references with RefTeX  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@science.uva.nl>
 ;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-sel.el b/lisp/textmodes/reftex-sel.el
index 61baf9408c2..fa36543daf4 100644
--- a/lisp/textmodes/reftex-sel.el
+++ b/lisp/textmodes/reftex-sel.el
@@ -1,6 +1,6 @@
 ;;; reftex-sel.el --- the selection modes for RefTeX  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@science.uva.nl>
 ;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-toc.el b/lisp/textmodes/reftex-toc.el
index 312ccb0f2be..1cc6e27e780 100644
--- a/lisp/textmodes/reftex-toc.el
+++ b/lisp/textmodes/reftex-toc.el
@@ -1,6 +1,6 @@
 ;;; reftex-toc.el --- RefTeX's table of contents mode  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2000, 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@science.uva.nl>
 ;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-vars.el b/lisp/textmodes/reftex-vars.el
index a153bfb3ec3..a0bc5c11ece 100644
--- a/lisp/textmodes/reftex-vars.el
+++ b/lisp/textmodes/reftex-vars.el
@@ -1,6 +1,6 @@
 ;;; reftex-vars.el --- configuration variables for RefTeX  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1997-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1999, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@science.uva.nl>
 ;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex.el b/lisp/textmodes/reftex.el
index 0a1fa8580d0..6974a4be4a7 100644
--- a/lisp/textmodes/reftex.el
+++ b/lisp/textmodes/reftex.el
@@ -1,6 +1,6 @@
 ;;; reftex.el --- minor mode for doing \label, \ref, \cite, \index in LaTeX  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2000, 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <dominik@science.uva.nl>
 ;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/remember.el b/lisp/textmodes/remember.el
index 84a0185f7b5..c75a9b758e7 100644
--- a/lisp/textmodes/remember.el
+++ b/lisp/textmodes/remember.el
@@ -1,6 +1,6 @@
 ;;; remember.el --- a mode for quickly jotting down things to remember  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1999-2001, 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2001, 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
@@ -185,7 +185,7 @@
 (defcustom remember-mode-hook nil
   "Functions run upon entering `remember-mode'."
   :type 'hook
-  :options '(flyspell-mode turn-on-auto-fill org-remember-apply-template))
+  :options '(flyspell-mode turn-on-auto-fill))
 
 (defcustom remember-in-new-frame nil
   "Non-nil means use a separate frame for capturing remember data."
@@ -210,8 +210,7 @@ recorded somewhere by that function."
   :options '(remember-store-in-mailbox
              remember-append-to-file
              remember-store-in-files
-             remember-diary-extract-entries
-             org-remember-handler))
+             remember-diary-extract-entries))
 
 (defcustom remember-all-handler-functions nil
   "If non-nil every function in `remember-handler-functions' is called."
@@ -235,7 +234,7 @@ recorded somewhere by that function."
 (defcustom remember-annotation-functions '(buffer-file-name)
   "Hook that returns an annotation to be inserted into the remember buffer."
   :type 'hook
-  :options '(org-remember-annotation buffer-file-name))
+  :options '(buffer-file-name))
 
 (defvar remember-annotation nil
   "Current annotation.")
diff --git a/lisp/textmodes/rst.el b/lisp/textmodes/rst.el
index d2661a44734..2cd78943883 100644
--- a/lisp/textmodes/rst.el
+++ b/lisp/textmodes/rst.el
@@ -1,6 +1,6 @@
 ;;; rst.el --- Mode for viewing and editing reStructuredText-documents  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: Stefan Merten <stefan at merten-home dot de>
 ;; Author: Stefan Merten <stefan at merten-home dot de>,
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el
index 5c53716c3ac..0e15f7e6062 100644
--- a/lisp/textmodes/sgml-mode.el
+++ b/lisp/textmodes/sgml-mode.el
@@ -1,13 +1,13 @@
 ;;; sgml-mode.el --- SGML- and HTML-editing modes -*- lexical-binding:t -*-
 
-;; Copyright (C) 1992, 1995-1996, 1998, 2001-2023 Free Software
+;; Copyright (C) 1992, 1995-1996, 1998, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: James Clark <jjc@jclark.com>
 ;; Maintainer: emacs-devel@gnu.org
 ;; Adapted-By: ESR, Daniel Pfeiffer <occitan@esperanto.org>,
 ;;             F.Potorti@cnuce.cnr.it
-;; Keywords: wp, hypermedia, comm, languages
+;; Keywords: text, hypermedia, comm, languages
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/textmodes/string-edit.el b/lisp/textmodes/string-edit.el
index c366611f26e..03be426ac25 100644
--- a/lisp/textmodes/string-edit.el
+++ b/lisp/textmodes/string-edit.el
@@ -1,6 +1,6 @@
 ;;; string-edit.el --- editing long strings  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 
diff --git a/lisp/textmodes/table.el b/lisp/textmodes/table.el
index 50c3f461bcc..19c6a8d7c4f 100644
--- a/lisp/textmodes/table.el
+++ b/lisp/textmodes/table.el
@@ -1,8 +1,8 @@
 ;;; table.el --- create and edit WYSIWYG text based embedded tables  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
-;; Keywords: wp, convenience
+;; Keywords: text, convenience
 ;; Author: Takaaki Ota <Takaaki.Ota@am.sony.com>
 ;; Created: Sat Jul 08 2000 13:28:45 (PST)
 
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
index d1644b5613e..8968d8ec23b 100644
--- a/lisp/textmodes/tex-mode.el
+++ b/lisp/textmodes/tex-mode.el
@@ -1,6 +1,7 @@
 ;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1989, 1992, 1994-1999, 2001-2024 Free
+;; Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: tex
diff --git a/lisp/textmodes/texinfmt.el b/lisp/textmodes/texinfmt.el
index c8c493f5e31..e144a9c34a0 100644
--- a/lisp/textmodes/texinfmt.el
+++ b/lisp/textmodes/texinfmt.el
@@ -1,6 +1,6 @@
 ;;; texinfmt.el --- format Texinfo files into Info files  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1985-1986, 1988, 1990-1998, 2000-2023 Free Software
+;; Copyright (C) 1985-1986, 1988, 1990-1998, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/texinfo.el b/lisp/textmodes/texinfo.el
index bedf9ec92a5..bd371514df0 100644
--- a/lisp/textmodes/texinfo.el
+++ b/lisp/textmodes/texinfo.el
@@ -1,6 +1,6 @@
 ;;; texinfo.el --- major mode for editing Texinfo files  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 1985, 1988-1993, 1996-1997, 2000-2023 Free Software
+;; Copyright (C) 1985, 1988-1993, 1996-1997, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Robert J. Chassell
diff --git a/lisp/textmodes/texnfo-upd.el b/lisp/textmodes/texnfo-upd.el
index 5961f5960bd..f4815c37181 100644
--- a/lisp/textmodes/texnfo-upd.el
+++ b/lisp/textmodes/texnfo-upd.el
@@ -1,6 +1,6 @@
 ;;; texnfo-upd.el --- utilities for updating nodes and menus in Texinfo files  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 1989-1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989-1992, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Robert J. Chassell
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/text-mode.el b/lisp/textmodes/text-mode.el
index 7f38a1c463d..87f6668cecb 100644
--- a/lisp/textmodes/text-mode.el
+++ b/lisp/textmodes/text-mode.el
@@ -1,10 +1,10 @@
 ;;; text-mode.el --- text mode, and its idiosyncratic commands  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985, 1992, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985, 1992, 1994, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
-;; Keywords: wp
+;; Keywords: text
 ;; Package: emacs
 
 ;; This file is part of GNU Emacs.
@@ -75,8 +75,15 @@
 Many other modes, such as `mail-mode' and `outline-mode', inherit
 all the commands defined in this map.")
 
-(defcustom text-mode-meta-tab-ispell-complete-word nil
-  "Whether M-TAB invokes `ispell-complete-word' in Text mode.
+(defcustom text-mode-ispell-word-completion 'completion-at-point
+  "How Text mode provides Ispell word completion.
+
+By default, this option is set to `completion-at-point', which
+means that Text mode adds an Ispell word completion function to
+`completion-at-point-functions'.  Any other non-nil value says to
+bind M-TAB directly to `ispell-complete-word' instead.  If this
+is nil, Text mode neither binds M-TAB to `ispell-complete-word'
+nor does it extend `completion-at-point-functions'.
 
 This user option only takes effect when you customize it in
 Custom or with `setopt', not with `setq'."
@@ -84,8 +91,9 @@ Custom or with `setopt', not with `setq'."
   :type 'boolean
   :version "30.1"
   :set (lambda (sym val)
-         (if (set sym val)
-            (keymap-set text-mode-map "C-M-i" #'ispell-complete-word)
+         (if (and (set sym val)
+                  (not (eq val 'completion-at-point)))
+             (keymap-set text-mode-map "C-M-i" #'ispell-complete-word)
            (keymap-unset text-mode-map "C-M-i" t))))
 
 (easy-menu-define text-mode-menu text-mode-map
@@ -144,7 +152,8 @@ Turning on Text mode runs the normal hook `text-mode-hook'."
   ;; Enable text conversion in this buffer.
   (setq-local text-conversion-style t)
   (add-hook 'context-menu-functions 'text-mode-context-menu 10 t)
-  (add-hook 'completion-at-point-functions #'ispell-completion-at-point 10 t))
+  (when (eq text-mode-ispell-word-completion 'completion-at-point)
+    (add-hook 'completion-at-point-functions #'ispell-completion-at-point 10 
t)))
 
 (define-derived-mode paragraph-indent-text-mode text-mode "Parindent"
   "Major mode for editing text, with leading spaces starting a paragraph.
diff --git a/lisp/textmodes/tildify.el b/lisp/textmodes/tildify.el
index 18ba83e86e8..8bdb41a07b1 100644
--- a/lisp/textmodes/tildify.el
+++ b/lisp/textmodes/tildify.el
@@ -1,11 +1,11 @@
 ;;; tildify.el --- adding hard spaces into texts -*- lexical-binding: t -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author:     Milan Zamazal <pdm@zamazal.org>
 ;;             Michal Nazarewicz <mina86@mina86.com>
 ;; Version:    4.6.1
-;; Keywords:   text, TeX, SGML, wp
+;; Keywords:   text, TeX, SGML
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/textmodes/toml-ts-mode.el b/lisp/textmodes/toml-ts-mode.el
index 193c83f9aec..1ba410045f5 100644
--- a/lisp/textmodes/toml-ts-mode.el
+++ b/lisp/textmodes/toml-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; toml-ts-mode.el --- tree-sitter support for TOML  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author     : Jostein Kjønigsen <jostein@kjonigsen.net>
 ;; Maintainer : Jostein Kjønigsen <jostein@kjonigsen.net>
diff --git a/lisp/textmodes/two-column.el b/lisp/textmodes/two-column.el
index 23dcc7e5945..806d6c5e709 100644
--- a/lisp/textmodes/two-column.el
+++ b/lisp/textmodes/two-column.el
@@ -1,10 +1,10 @@
 ;;; two-column.el --- minor mode for editing of two-column text  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1992-1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1995, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
 ;; Adapted-By: ESR, Daniel Pfeiffer
-;; Keywords: wp
+;; Keywords: text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/textmodes/underline.el b/lisp/textmodes/underline.el
index b22652b6824..b1157febc24 100644
--- a/lisp/textmodes/underline.el
+++ b/lisp/textmodes/underline.el
@@ -1,9 +1,9 @@
 ;;; underline.el --- insert/remove underlining (done by overstriking) in Emacs 
 -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
-;; Keywords: wp
+;; Keywords: text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/textmodes/word-wrap-mode.el b/lisp/textmodes/word-wrap-mode.el
index 28bca7e27ea..86724a193db 100644
--- a/lisp/textmodes/word-wrap-mode.el
+++ b/lisp/textmodes/word-wrap-mode.el
@@ -1,6 +1,6 @@
 ;;; word-wrap-mode.el --- minor mode for `word-wrap' tweaks  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 
diff --git a/lisp/textmodes/yaml-ts-mode.el b/lisp/textmodes/yaml-ts-mode.el
index dfa8d22fb34..a8cb504ef03 100644
--- a/lisp/textmodes/yaml-ts-mode.el
+++ b/lisp/textmodes/yaml-ts-mode.el
@@ -1,6 +1,6 @@
 ;;; yaml-ts-mode.el --- tree-sitter support for YAML  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author     : Randy Taylor <dev@rjt.dev>
 ;; Maintainer : Randy Taylor <dev@rjt.dev>
@@ -30,6 +30,9 @@
 (require 'treesit)
 
 (declare-function treesit-parser-create "treesit.c")
+(declare-function treesit-node-start "treesit.c")
+(declare-function treesit-node-end "treesit.c")
+(declare-function treesit-node-type "treesit.c")
 
 (defvar yaml-ts-mode--syntax-table
   (let ((table (make-syntax-table)))
@@ -117,6 +120,27 @@
    '((ERROR) @font-lock-warning-face))
   "Tree-sitter font-lock settings for `yaml-ts-mode'.")
 
+(defun yaml-ts-mode--fill-paragraph (&optional justify)
+  "Fill paragraph.
+Behaves like `fill-paragraph', but respects block node
+boundaries.  JUSTIFY is passed to `fill-paragraph'."
+  (interactive "*P")
+  (save-restriction
+    (widen)
+    (let ((node (treesit-node-at (point))))
+      (if (member (treesit-node-type node) '("block_scalar" "comment"))
+        (let* ((start (treesit-node-start node))
+               (end (treesit-node-end node))
+               (start-marker (point-marker))
+               (fill-paragraph-function nil))
+          (save-excursion
+            (goto-char start)
+            (forward-line)
+            (move-marker start-marker (point))
+            (narrow-to-region (point) end))
+          (fill-region start-marker end justify))
+        t))))
+
 ;;;###autoload
 (define-derived-mode yaml-ts-mode text-mode "YAML"
   "Major mode for editing YAML, powered by tree-sitter."
@@ -141,6 +165,8 @@
                   (constant escape-sequence number property)
                   (bracket delimiter error misc-punctuation)))
 
+    (setq-local fill-paragraph-function #'yaml-ts-mode--fill-paragraph)
+
     (treesit-major-mode-setup)))
 
 (if (treesit-ready-p 'yaml)
diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el
index 88efbf73beb..323d3d1cf6c 100644
--- a/lisp/thingatpt.el
+++ b/lisp/thingatpt.el
@@ -1,6 +1,6 @@
 ;;; thingatpt.el --- get the `thing' at point  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1991-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Mike Williams <mikew@gopher.dosli.govt.nz>
 ;; Maintainer: emacs-devel@gnu.org
@@ -652,7 +652,7 @@ back from point."
 
 ;;   Email addresses
 (defvar thing-at-point-email-regexp
-  "<?[-+_~a-zA-Z0-9][-+_.~:a-zA-Z0-9]*@[-a-zA-Z0-9]+[-.a-zA-Z0-9]*>?"
+  "<?[-+_~a-zA-Z0-9/][-+_.~:a-zA-Z0-9/]*@[-a-zA-Z0-9]+[-.a-zA-Z0-9]*>?"
   "A regular expression probably matching an email address.
 This does not match the real name portion, only the address, optionally
 with angle brackets.")
diff --git a/lisp/thread.el b/lisp/thread.el
index 7363e9a06c8..4c428f30f71 100644
--- a/lisp/thread.el
+++ b/lisp/thread.el
@@ -1,6 +1,6 @@
 ;;; thread.el --- Thread support in Emacs Lisp -*- lexical-binding: t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Gemini Lasswell <gazally@runbox.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el
index 1447b6b4368..8c28920d219 100644
--- a/lisp/time-stamp.el
+++ b/lisp/time-stamp.el
@@ -1,6 +1,6 @@
 ;;; time-stamp.el --- Maintain last change time stamps in files edited by 
Emacs  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1989, 1993-1995, 1997, 2000-2023 Free Software
+;; Copyright (C) 1989, 1993-1995, 1997, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/time.el b/lisp/time.el
index 3f10deff5fd..9b932e945ba 100644
--- a/lisp/time.el
+++ b/lisp/time.el
@@ -1,6 +1,6 @@
 ;;; time.el --- display time, load and mail indicator in mode line of Emacs  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-1987, 1993-1994, 1996, 2000-2023 Free Software
+;; Copyright (C) 1985-1987, 1993-1994, 1996, 2000-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
@@ -589,7 +589,7 @@ See `world-clock'."
 (defun world-clock ()
   "Display a world clock buffer with times in various time zones.
 The variable `world-clock-list' specifies which time zones to use.
-To turn off the world time display, go to the window and type 
`\\[quit-window]'."
+To turn off the world time display, go to the window and type \\[quit-window]."
   (interactive)
   (if-let ((buffer (get-buffer world-clock-buffer-name)))
       (pop-to-buffer buffer)
diff --git a/lisp/timezone.el b/lisp/timezone.el
index 9a199f0939e..515bf87480b 100644
--- a/lisp/timezone.el
+++ b/lisp/timezone.el
@@ -1,6 +1,6 @@
 ;;; timezone.el --- time zone package for GNU Emacs  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1990-1993, 1996, 1999, 2001-2023 Free Software
+;; Copyright (C) 1990-1993, 1996, 1999, 2001-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Masanobu Umeda <umerin@mse.kyutech.ac.jp>
diff --git a/lisp/tmm.el b/lisp/tmm.el
index b587b416a35..f52afb7e162 100644
--- a/lisp/tmm.el
+++ b/lisp/tmm.el
@@ -1,6 +1,6 @@
 ;;; tmm.el --- text mode access to menu-bar  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1994-1996, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1996, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Ilya Zakharevich <ilya@math.mps.ohio-state.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/tool-bar.el b/lisp/tool-bar.el
index ab81a21211d..96b61c7b229 100644
--- a/lisp/tool-bar.el
+++ b/lisp/tool-bar.el
@@ -1,6 +1,6 @@
 ;;; tool-bar.el --- setting up the tool bar  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;; Keywords: mouse frames
@@ -165,6 +165,8 @@ color capability and based on the available image 
libraries."
             base-keymap)
       base-keymap)))
 
+;; This function should return binds even if images can not be
+;; displayed so the tool bar can still be displayed on terminals.
 (defun tool-bar-make-keymap-1 (&optional map)
   "Generate an actual keymap from `tool-bar-map', without caching.
 MAP is either a keymap to use as a source for menu items, or nil,
@@ -180,15 +182,14 @@ in which case the value of `tool-bar-map' is used 
instead."
                         (consp image-exp)
                         (not (eq (car image-exp) 'image))
                         (fboundp (car image-exp)))
-               (if (not (display-images-p))
-                   (setq bind nil)
-                 (let ((image (eval image-exp)))
-                   (unless (and image (image-mask-p image))
-                     (setq image (append image '(:mask heuristic))))
-                   (setq bind (copy-sequence bind)
-                         plist (nthcdr (if (consp (nth 4 bind)) 5 4)
-                                       bind))
-                   (plist-put plist :image image))))
+               (let ((image (and (display-images-p)
+                                  (eval image-exp))))
+                 (unless (and image (image-mask-p image))
+                   (setq image (append image '(:mask heuristic))))
+                 (setq bind (copy-sequence bind)
+                       plist (nthcdr (if (consp (nth 4 bind)) 5 4)
+                                     bind))
+                 (plist-put plist :image image)))
              bind))
          (or map tool-bar-map)))
 
diff --git a/lisp/tooltip.el b/lisp/tooltip.el
index 6f8a489e60c..4537fdf8087 100644
--- a/lisp/tooltip.el
+++ b/lisp/tooltip.el
@@ -1,6 +1,6 @@
 ;;; tooltip.el --- show tooltip windows  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1997, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Gerd Moellmann <gerd@acm.org>
 ;; Keywords: help c mouse tools
diff --git a/lisp/touch-screen.el b/lisp/touch-screen.el
index 56adb75cefc..a1ec4bca89f 100644
--- a/lisp/touch-screen.el
+++ b/lisp/touch-screen.el
@@ -1,6 +1,6 @@
 ;;; touch-screen.el --- touch screen support for X and Android  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Package: emacs
@@ -57,7 +57,7 @@ touch point being tracked, the window where the touch began, a
 cons holding the initial position of the touch point, and the
 last known position of the touch point, all in the same format as
 in `touch-screen-current-tool', the distance in pixels between
-the current tool and the aformentioned initial position, the
+the current tool and the aforementioned initial position, the
 center of the line formed between those two points, the ratio
 between the present distance between both tools and the aforesaid
 initial distance when a pinch gesture was last sent, and three
@@ -320,6 +320,7 @@ the event."
 
 ;;; Drag-to-select gesture.
 
+;;;###autoload
 (defun touch-screen-hold (event)
   "Handle a long press EVENT.
 Ding and select the window at EVENT, then activate the mark.  If
@@ -1026,7 +1027,7 @@ POINT was initially placed upon, and pixel deltas 
describing how
 much point has moved relative to its previous position in the X
 and Y axes.
 
-If the fourth element of `touchscreen-current-tool' is `scroll',
+If the fourth element of `touch-screen-current-tool' is `scroll',
 then generate a `touchscreen-scroll' event with the window that
 POINT was initially placed upon, and pixel deltas describing how
 much point has moved relative to its previous position in the X
@@ -1913,6 +1914,7 @@ if POSN is on a link or a button, or `mouse-1' otherwise."
 
 ;; Exports.  These functions are intended for use externally.
 
+;;;###autoload
 (defun touch-screen-track-tap (event &optional update data threshold)
   "Track a single tap starting from EVENT.
 EVENT should be a `touchscreen-begin' event.
@@ -1925,7 +1927,7 @@ with that event and DATA.
 
 If THRESHOLD is non-nil, enforce a threshold of movement that is
 either itself or 10 pixels when it is not a number.  If the
-aformentioned touch point moves beyond that threshold on any
+aforementioned touch point moves beyond that threshold on any
 axis, return nil immediately, and further resume mouse event
 translation for the touch point at hand.
 
@@ -1970,6 +1972,7 @@ otherwise, return t once the `touchscreen-end' event 
arrives."
                    (eq (caadr event) (caadr new-event))))
            (t (throw 'finish nil))))))))
 
+;;;###autoload
 (defun touch-screen-track-drag (event update &optional data)
   "Track a single drag starting from EVENT.
 EVENT should be a `touchscreen-begin' event.
@@ -2017,6 +2020,7 @@ touch point in EVENT did not move significantly, and t 
otherwise."
 ;;; Event handling exports.  These functions are intended for use by
 ;;; Lisp commands bound to touch screen gesture events.
 
+;;;###autoload
 (defun touch-screen-inhibit-drag ()
   "Inhibit subsequent `touchscreen-drag' events from being sent.
 Prevent `touchscreen-drag' and translated mouse events from being
diff --git a/lisp/transient.el b/lisp/transient.el
index 455e18bbf26..06d0b95bd82 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -1,13 +1,11 @@
 ;;; transient.el --- Transient commands  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Jonas Bernoulli <jonas@bernoul.li>
 ;; URL: https://github.com/magit/transient
 ;; Keywords: extensions
-
-;; Package-Version: 0.4.3
-;; Package-Requires: ((emacs "26.1"))
+;; Version: 0.5.2
 
 ;; SPDX-License-Identifier: GPL-3.0-or-later
 
@@ -28,27 +26,9 @@
 
 ;;; Commentary:
 
-;; Taking inspiration from prefix keys and prefix arguments, Transient
-;; implements a similar abstraction involving a prefix command, infix
-;; arguments and suffix commands.  We could call this abstraction a
-;; "transient command", but because it always involves at least two
-;; commands (a prefix and a suffix) we prefer to call it just a
-;; "transient".
-
-;; When the user calls a transient prefix command, then a transient
-;; (temporary) keymap is activated, which binds the transient's infix
-;; and suffix commands, and functions that control the transient state
-;; are added to `pre-command-hook' and `post-command-hook'.  The
-;; available suffix and infix commands and their state are shown in
-;; the echo area until the transient is exited by invoking a suffix
-;; command.
-
-;; Calling an infix command causes its value to be changed, possibly
-;; by 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 state.
+;; Transient is the library used to implement the keyboard-driven menus
+;; in Magit.  It is distributed as a separate package, so that it can be
+;; used to implement similar menus in other packages.
 
 ;;; Code:
 
@@ -56,7 +36,41 @@
 (require 'eieio)
 (require 'edmacro)
 (require 'format-spec)
+
+(eval-and-compile
+  (when (and (featurep' seq)
+             (not (fboundp 'seq-keep)))
+    (unload-feature 'seq 'force)))
 (require 'seq)
+(unless (fboundp 'seq-keep)
+  (display-warning 'transient (substitute-command-keys "\
+Transient requires `seq' >= 2.24,
+but due to bad defaults, Emacs' package manager, refuses to
+upgrade this and other built-in packages to higher releases
+from GNU Elpa, when a package specifies that this is needed.
+
+To fix this, you have to add this to your init file:
+
+  (setq package-install-upgrade-built-in t)
+
+Then evaluate that expression by placing the cursor after it
+and typing \\[eval-last-sexp].
+
+Once you have done that, you have to explicitly upgrade `seq':
+
+  \\[package-upgrade] seq \\`RET'
+
+Then you also must make sure the updated version is loaded,
+by evaluating this form:
+
+  (progn (unload-feature 'seq t) (require 'seq))
+
+Until you do this, you will get random errors about `seq-keep'
+being undefined while using Transient.
+
+If you don't use the `package' package manager but still get
+this warning, then your chosen package manager likely has a
+similar defect.") :emergency))
 
 (eval-when-compile (require 'subr-x))
 
@@ -65,10 +79,20 @@
 (declare-function Man-next-section "man" (n))
 (declare-function Man-getpage-in-background "man" (topic))
 
-(defvar display-line-numbers) ; since Emacs 26.1
 (defvar Man-notify-method)
 (defvar pp-default-function) ; since Emacs 29.1
 
+(defmacro static-if (condition then-form &rest else-forms)
+  "A conditional compilation macro.
+Evaluate CONDITION at macro-expansion time.  If it is non-nil,
+expand the macro to THEN-FORM.  Otherwise expand it to ELSE-FORMS
+enclosed in a `progn' form.  ELSE-FORMS may be empty."
+  (declare (indent 2)
+           (debug (sexp sexp &rest sexp)))
+  (if (eval condition lexical-binding)
+      then-form
+    (cons 'progn else-forms)))
+
 (defmacro transient--with-emergency-exit (&rest body)
   (declare (indent defun))
   `(condition-case err
@@ -198,21 +222,30 @@ If nil, then the buffer has no mode-line.  If the buffer 
is not
 displayed right above the echo area, then this probably is not
 a good value.
 
-If `line' (the default), then the buffer also has no mode-line,
-but a thin line is drawn instead, using the background color of
-the face `transient-separator'.  Termcap frames cannot display
-thin lines and therefore fallback to treating `line' like nil.
+If `line' (the default) or a natural number, then the buffer
+has no mode-line, but a line is drawn is drawn in its place.
+If a number is used, that specifies the thickness of the line.
+On termcap frames we cannot draw lines, so there `line' and
+numbers are synonyms for nil.
+
+The color of the line is used to indicate if non-suffixes are
+allowed and whether they exit the transient.  The foreground
+color of `transient-key-noop' (if non-suffix are disallowed),
+`transient-key-stay' (if allowed and transient stays active), or
+`transient-key-exit' (if allowed and they exit the transient) is
+used to draw the line.
 
 Otherwise this can be any mode-line format.
 See `mode-line-format' for details."
   :package-version '(transient . "0.2.0")
   :group 'transient
-  :type '(choice (const :tag "hide mode-line" nil)
-                 (const :tag "substitute thin line" line)
-                 (const :tag "name of prefix command"
-                        ("%e" mode-line-front-space
-                         mode-line-buffer-identification))
-                 (sexp  :tag "custom mode-line format")))
+  :type '(choice (const  :tag "hide mode-line" nil)
+                 (const  :tag "substitute thin line" line)
+                 (number :tag "substitute line with thickness")
+                 (const  :tag "name of prefix command"
+                         ("%e" mode-line-front-space
+                          mode-line-buffer-identification))
+                 (sexp   :tag "custom mode-line format")))
 
 (defcustom transient-show-common-commands nil
   "Whether to show common transient suffixes in the popup buffer.
@@ -236,7 +269,7 @@ of this variable use \"C-x t\" when a transient is active."
 This only affects infix arguments that represent command-line
 arguments.  When this option is non-nil, then the key binding
 for infix argument are highlighted when only a long argument
-\(e.g. \"--verbose\") is specified but no shor-thand (e.g \"-v\").
+\(e.g., \"--verbose\") is specified but no shorthand (e.g., \"-v\").
 In the rare case that a short-hand is specified but does not
 match the key binding, then it is highlighted differently.
 
@@ -285,19 +318,14 @@ using a layout optimized for Lisp.
   :group 'transient
   :type '(choice (const :tag "Transform no keys (nil)" nil) function))
 
-(defcustom transient-semantic-coloring nil
-  "Whether to color prefixes and suffixes in Hydra-like fashion.
-This feature is experimental.
+(defcustom transient-semantic-coloring t
+  "Whether to use colors to indicate transient behavior.
 
 If non-nil, then the key binding of each suffix is colorized to
-indicate whether it exits the transient state or not.  The color
-of the prefix is indicated using the line that is drawn when the
-value of `transient-mode-line-format' is `line'.
-
-For more information about how Hydra uses colors see
-https://github.com/abo-abo/hydra#color and
-https://oremacs.com/2015/02/19/hydra-colors-reloaded.";
-  :package-version '(transient . "0.3.0")
+indicate whether it exits the transient state or not, and the
+line that is drawn below the transient popup buffer is used to
+indicate the behavior of non-suffix commands."
+  :package-version '(transient . "0.5.0")
   :group 'transient
   :type 'boolean)
 
@@ -356,8 +384,8 @@ text and might otherwise have to scroll in two dimensions."
   :group 'transient
   :type 'boolean)
 
+(defconst transient--max-level 7)
 (defconst transient--default-child-level 1)
-
 (defconst transient--default-prefix-level 4)
 
 (defcustom transient-default-level transient--default-prefix-level
@@ -436,22 +464,18 @@ give you as many additional suffixes as you hoped.)"
   "Face used for headings."
   :group 'transient-faces)
 
-(defface transient-key '((t :inherit font-lock-builtin-face))
-  "Face used for keys."
-  :group 'transient-faces)
-
-(defface transient-argument '((t :inherit font-lock-warning-face))
+(defface transient-argument '((t :inherit font-lock-string-face :weight bold))
   "Face used for enabled arguments."
   :group 'transient-faces)
 
-(defface transient-value '((t :inherit font-lock-string-face))
-  "Face used for values."
-  :group 'transient-faces)
-
 (defface transient-inactive-argument '((t :inherit shadow))
   "Face used for inactive arguments."
   :group 'transient-faces)
 
+(defface transient-value '((t :inherit font-lock-string-face :weight bold))
+  "Face used for values."
+  :group 'transient-faces)
+
 (defface transient-inactive-value '((t :inherit shadow))
   "Face used for inactive values."
   :group 'transient-faces)
@@ -460,28 +484,14 @@ give you as many additional suffixes as you hoped.)"
   "Face used for suffixes unreachable from the current prefix sequence."
   :group 'transient-faces)
 
-(defface transient-active-infix '((t :inherit secondary-selection))
-  "Face used for the infix for which the value is being read."
-  :group 'transient-faces)
-
-(defface transient-unreachable-key '((t :inherit (transient-key shadow)))
-  "Face used for keys unreachable from the current prefix sequence."
-  :group 'transient-faces)
-
-(defface transient-nonstandard-key '((t :underline t))
-  "Face optionally used to highlight keys conflicting with short-argument.
-Also see option `transient-highlight-mismatched-keys'."
-  :group 'transient-faces)
-
-(defface transient-mismatched-key '((t :underline t))
-  "Face optionally used to highlight keys without a short-argument.
-Also see option `transient-highlight-mismatched-keys'."
-  :group 'transient-faces)
-
 (defface transient-inapt-suffix '((t :inherit shadow :italic t))
   "Face used for suffixes that are inapt at this time."
   :group 'transient-faces)
 
+(defface transient-active-infix '((t :inherit highlight))
+  "Face used for the infix for which the value is being read."
+  :group 'transient-faces)
+
 (defface transient-enabled-suffix
   '((t :background "green" :foreground "black" :weight bold))
   "Face used for enabled levels while editing suffix levels.
@@ -494,63 +504,83 @@ See info node `(transient)Enabling and Disabling 
Suffixes'."
 See info node `(transient)Enabling and Disabling Suffixes'."
   :group 'transient-faces)
 
-(defface transient-higher-level '((t :underline t))
+(defface transient-higher-level
+  `((t :box ( :line-width ,(if (>= emacs-major-version 28) (cons -1 -1) -1)
+              :color ,(let ((color (face-attribute 'shadow :foreground nil t)))
+                        (or (and (not (eq color 'unspecified)) color)
+                            "grey60")))))
   "Face optionally used to highlight suffixes on higher levels.
 Also see option `transient-highlight-higher-levels'."
   :group 'transient-faces)
 
-(defface transient-separator
-  `((((class color) (background light))
-     ,@(and (>= emacs-major-version 27) '(:extend t))
-     :background "grey80")
-    (((class color) (background  dark))
-     ,@(and (>= emacs-major-version 27) '(:extend t))
-     :background "grey30"))
-  "Face used to draw line below transient popup window.
-This is only used if `transient-mode-line-format' is `line'.
-Only the background color is significant."
+(defface transient-delimiter '((t :inherit shadow))
+  "Face used for delimiters and separators.
+This includes the parentheses around values and the pipe
+character used to separate possible values from each other."
   :group 'transient-faces)
 
-(defgroup transient-color-faces
-  '((transient-semantic-coloring custom-variable))
-  "Faces used by Transient for Hydra-like command coloring.
-These faces are only used if `transient-semantic-coloring'
-\(which see) is non-nil."
+(defface transient-key '((t :inherit font-lock-builtin-face))
+  "Face used for keys."
   :group 'transient-faces)
 
-(defface transient-red
-  '((t :inherit transient-key :foreground "red"))
-  "Face used for red prefixes and suffixes."
-  :group 'transient-color-faces)
+(defface transient-key-stay
+  `((((class color) (background light))
+     :inherit transient-key
+     :foreground "#22aa22")
+    (((class color) (background dark))
+     :inherit transient-key
+     :foreground "#ddffdd"))
+  "Face used for keys of suffixes that don't exit transient state."
+  :group 'transient-faces)
 
-(defface transient-blue
-  '((t :inherit transient-key :foreground "blue"))
-  "Face used for blue prefixes and suffixes."
-  :group 'transient-color-faces)
+(defface transient-key-noop
+  `((((class color) (background light))
+     :inherit transient-key
+     :foreground "grey80")
+    (((class color) (background dark))
+     :inherit transient-key
+     :foreground "grey30"))
+  "Face used for keys of suffixes that currently cannot be invoked."
+  :group 'transient-faces)
 
-(defface transient-amaranth
-  '((t :inherit transient-key :foreground "#E52B50"))
-  "Face used for amaranth prefixes."
-  :group 'transient-color-faces)
+(defface transient-key-return
+  `((((class color) (background light))
+     :inherit transient-key
+     :foreground "#aaaa11")
+    (((class color) (background dark))
+     :inherit transient-key
+     :foreground "#ffffcc"))
+  "Face used for keys of suffixes that return to the parent transient."
+  :group 'transient-faces)
 
-(defface transient-pink
-  '((t :inherit transient-key :foreground "#FF6EB4"))
-  "Face used for pink prefixes."
-  :group 'transient-color-faces)
+(defface transient-key-exit
+  `((((class color) (background light))
+     :inherit transient-key
+     :foreground "#aa2222")
+    (((class color) (background dark))
+     :inherit transient-key
+     :foreground "#ffdddd"))
+  "Face used for keys of suffixes that exit transient state."
+  :group 'transient-faces)
 
-(defface transient-teal
-  '((t :inherit transient-key :foreground "#367588"))
-  "Face used for teal prefixes."
-  :group 'transient-color-faces)
+(defface transient-unreachable-key
+  '((t :inherit (shadow transient-key) :weight normal))
+  "Face used for keys unreachable from the current prefix sequence."
+  :group 'transient-faces)
 
-(defface transient-purple
-  '((t :inherit transient-key :foreground "#a020f0"))
-  "Face used for purple prefixes.
+(defface transient-nonstandard-key
+  `((t :box ( :line-width ,(if (>= emacs-major-version 28) (cons -1 -1) -1)
+              :color "cyan")))
+  "Face optionally used to highlight keys conflicting with short-argument.
+Also see option `transient-highlight-mismatched-keys'."
+  :group 'transient-faces)
 
-This is an addition to the colors supported by Hydra.  It is
-used by suffixes that quit the current prefix but return to
-the previous prefix."
-  :group 'transient-color-faces)
+(defface transient-mismatched-key
+  `((t :box ( :line-width ,(if (>= emacs-major-version 28) (cons -1 -1) -1)
+              :color "magenta")))
+  "Face optionally used to highlight keys without a short-argument.
+Also see option `transient-highlight-mismatched-keys'."
+  :group 'transient-faces)
 
 ;;; Persistence
 
@@ -633,6 +663,8 @@ If `transient-save-history' is nil, then do nothing."
    (man-page    :initarg :man-page    :initform nil)
    (transient-suffix     :initarg :transient-suffix     :initform nil)
    (transient-non-suffix :initarg :transient-non-suffix :initform nil)
+   (transient-switch-frame :initarg :transient-switch-frame)
+   (refresh-suffixes     :initarg :refresh-suffixes     :initform nil)
    (incompatible         :initarg :incompatible         :initform nil)
    (suffix-description   :initarg :suffix-description)
    (variable-pitch       :initarg :variable-pitch       :initform nil)
@@ -698,7 +730,9 @@ slot is non-nil."
    (transient   :initarg :transient)
    (format      :initarg :format      :initform " %k %d")
    (description :initarg :description :initform nil)
+   (face        :initarg :face        :initform nil)
    (show-help   :initarg :show-help   :initform nil)
+   (inapt-face  :initarg :inapt-face  :initform 'transient-inapt-suffix)
    (inapt                             :initform nil)
    (inapt-if
     :initarg :inapt-if
@@ -734,6 +768,12 @@ slot is non-nil."
     :documentation "Inapt if major-mode does not derive from value."))
   "Superclass for suffix command.")
 
+(defclass transient-information (transient-suffix)
+  ((format :initform " %k %d")
+   (key    :initform " "))
+  "Display-only information.
+A suffix object with no associated command.")
+
 (defclass transient-infix (transient-suffix)
   ((transient                         :initform t)
    (argument    :initarg :argument)
@@ -788,8 +828,8 @@ They become the value of this argument.")
   ((suffixes       :initarg :suffixes       :initform nil)
    (hide           :initarg :hide           :initform nil)
    (description    :initarg :description    :initform nil)
-   (setup-children :initarg :setup-children)
-   (pad-keys       :initarg :pad-keys))
+   (pad-keys       :initarg :pad-keys       :initform nil)
+   (setup-children :initarg :setup-children))
   "Abstract superclass of all group classes."
   :abstract t)
 
@@ -934,11 +974,11 @@ explicitly.
 
 The function definitions is always:
 
-   (lambda ()
-     (interactive)
-     (let ((obj (transient-suffix-object)))
-       (transient-infix-set obj (transient-infix-read obj)))
-     (transient--show))
+  (lambda ()
+    (interactive)
+    (let ((obj (transient-suffix-object)))
+      (transient-infix-set obj (transient-infix-read obj)))
+    (transient--show))
 
 `transient-infix-read' and `transient-infix-set' are generic
 functions.  Different infix commands behave differently because
@@ -976,7 +1016,16 @@ example, sets a variable, use `transient-define-infix' 
instead.
 \(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]...)")
 
 (defun transient--default-infix-command ()
-  "Most transient infix commands are but an alias for this command."
+  ;; Most infix commands are but an alias for this command.
+  "Cannot show any documentation for this anonymous infix command.
+
+This infix command was defined anonymously, i.e., it was define
+inside a call to `transient-define-prefix'.
+
+When you request help for such an infix command, then we usually
+show the respective man-page and jump to the location where the
+respective argument is being described.  This isn't possible in
+this case, because the `man-page' slot was not set in this case."
   (interactive)
   (let ((obj (transient-suffix-object)))
     (transient-infix-set obj (transient-infix-read obj)))
@@ -984,30 +1033,31 @@ example, sets a variable, use `transient-define-infix' 
instead.
 (put 'transient--default-infix-command 'interactive-only t)
 (put 'transient--default-infix-command 'command-modes (list 'not-a-mode))
 
-(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)))
-    (while (keywordp (car args))
-      (let ((k (pop args))
-            (v (pop args)))
-        (if (eq k :class)
-            (setq class v)
-          (push k keys)
-          (push v keys))))
-    (while (let ((arg (car args)))
-             (or (vectorp arg)
-                 (and arg (symbolp arg))))
-      (push (pop args) suffixes))
-    (list (if (eq (car-safe class) 'quote)
-              (cadr class)
-            class)
-          (nreverse keys)
-          (nreverse suffixes)
-          docstr
-          args)))
+(eval-and-compile
+  (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)))
+      (while (keywordp (car args))
+        (let ((k (pop args))
+              (v (pop args)))
+          (if (eq k :class)
+              (setq class v)
+            (push k keys)
+            (push v keys))))
+      (while (let ((arg (car args)))
+               (or (vectorp arg)
+                   (and arg (symbolp arg))))
+        (push (pop args) suffixes))
+      (list (if (eq (car-safe class) 'quote)
+                (cadr class)
+              class)
+            (nreverse keys)
+            (nreverse suffixes)
+            docstr
+            args))))
 
 (defun transient--parse-child (prefix spec)
   (cl-etypecase spec
@@ -1072,8 +1122,9 @@ example, sets a variable, use `transient-define-infix' 
instead.
              (commandp (cadr spec)))
         (setq args (plist-put args :description (macroexp-quote pop)))))
       (cond
+       ((eq car :info))
        ((keywordp car)
-        (error "Need command, got `%s'" car))
+        (error "Need command or `:info', got `%s'" car))
        ((symbolp car)
         (setq args (plist-put args :command (macroexp-quote pop))))
        ((and (commandp car)
@@ -1091,7 +1142,10 @@ example, sets a variable, use `transient-define-infix' 
instead.
                       `(prog1 ',sym
                          (put ',sym 'interactive-only t)
                          (put ',sym 'command-modes (list 'not-a-mode))
-                         (defalias ',sym ,(macroexp-quote cmd)))))))
+                         (defalias ',sym
+                           ,(if (eq (car-safe cmd) 'lambda)
+                                cmd
+                              (macroexp-quote cmd))))))))
        ((or (stringp car)
             (and car (listp car)))
         (let ((arg pop)
@@ -1126,6 +1180,9 @@ example, sets a variable, use `transient-define-infix' 
instead.
               (val pop))
           (cond ((eq key :class) (setq class val))
                 ((eq key :level) (setq level val))
+                ((eq key :info)
+                 (setq class 'transient-information)
+                 (setq args (plist-put args :description val)))
                 ((eq (car-safe val) '\,)
                  (setq args (plist-put args key (cadr val))))
                 ((or (symbolp val)
@@ -1194,11 +1251,11 @@ Intended for use in a group's `:setup-children' 
function."
                         (equal (transient--suffix-predicate suf)
                                (transient--suffix-predicate conflict)))))
         (transient-remove-suffix prefix key))
-      (cl-ecase action
-        (insert  (setcdr mem (cons elt (cdr mem)))
-                 (setcar mem suf))
-        (append  (setcdr mem (cons suf (cdr mem))))
-        (replace (setcar mem suf)))))))
+      (pcase-exhaustive action
+        ('insert  (setcdr mem (cons elt (cdr mem)))
+                  (setcar mem suf))
+        ('append  (setcdr mem (cons suf (cdr mem))))
+        ('replace (setcar mem suf)))))))
 
 ;;;###autoload
 (defun transient-insert-suffix (prefix loc suffix &optional keep-other)
@@ -1309,7 +1366,7 @@ See info node `(transient)Modifying Existing Transients'."
                (delq (car (transient--group-member loc layout))
                      (aref layout 3)))
          nil)
-        (t (transient--group-member loc layout))))
+        ((transient--group-member loc layout))))
 
 (defun transient--group-member (loc group)
   (cl-member-if (lambda (suffix)
@@ -1338,7 +1395,7 @@ See info node `(transient)Modifying Existing Transients'."
          (plist-get plist :command)))))
 
 (defun transient--command-key (cmd)
-  (and-let* ((obj (get cmd 'transient--suffix)))
+  (and-let* ((obj (transient--suffix-prototype cmd)))
     (cond ((slot-boundp obj 'key)
            (oref obj key))
           ((slot-exists-p obj 'shortarg)
@@ -1379,11 +1436,15 @@ variable instead.")
 (defconst transient--exit nil "Do exit the transient.")
 
 (defvar transient--exitp nil "Whether to exit the transient.")
-(defvar transient--showp nil "Whether the transient is show in a popup 
buffer.")
+(defvar transient--showp nil "Whether to show the transient popup buffer.")
 (defvar transient--helpp nil "Whether help-mode is active.")
 (defvar transient--editp nil "Whether edit-mode is active.")
 
-(defvar transient--active-infix nil "The active infix awaiting user input.")
+(defvar transient--refreshp nil
+  "Whether to refresh the transient completely.")
+
+(defvar transient--all-levels-p nil
+  "Whether temporary display of suffixes on all levels is active.")
 
 (defvar transient--timer nil)
 
@@ -1395,7 +1456,7 @@ variable instead.")
   "Name of the transient buffer.")
 
 (defvar transient--window nil
-  "The window used to display the transient popup.")
+  "The window used to display the transient popup buffer.")
 
 (defvar transient--original-window nil
   "The window that was selected before the transient was invoked.
@@ -1405,7 +1466,24 @@ Usually it remains selected while the transient is 
active.")
   "The buffer that was current before the transient was invoked.
 Usually it remains current while the transient is active.")
 
-(defvar transient--debug nil "Whether put debug information into *Messages*.")
+(defvar transient--restore-winconf nil
+  "Window configuration to restore after exiting help.")
+
+(defvar transient--shadowed-buffer nil
+  "The buffer that is temporarily shadowed by the transient buffer.
+This is bound while the suffix predicate is being evaluated and while
+drawing in the transient buffer.")
+
+(defvar transient--pending-suffix nil
+  "The suffix that is currently being processed.
+This is bound while the suffix predicate is being evaluated.")
+
+(defvar transient--pending-group nil
+  "The group that is currently being processed.
+This is bound while the suffixes are drawn in the transient buffer.")
+
+(defvar transient--debug nil
+  "Whether to put debug information into *Messages*.")
 
 (defvar transient--history nil)
 
@@ -1417,6 +1495,31 @@ Usually it remains current while the transient is 
active.")
 
 ;;; Identities
 
+(defun transient-prefix-object ()
+  "Return the current prefix as an object.
+
+While a transient is being setup or refreshed (which involves
+preparing its suffixes) the variable `transient--prefix' can be
+used to access the prefix object.  Thus this is what has to be
+used in suffix methods such as `transient-format-description',
+and in object-specific functions that are stored in suffix slots
+such as `description'.
+
+When a suffix command is invoked (i.e., in its `interactive' form
+and function body) then the variable `transient-current-prefix'
+has to be used instead.
+
+Two distinct variables are needed, because any prefix may itself
+be used as a suffix of another prefix, and such sub-prefixes have
+to be able to tell themselves apart from the prefix they were
+invoked from.
+
+Regular suffix commands, which are not prefixes, do not have to
+concern themselves with this distinction, so they can use this
+function instead.  In the context of a plain suffix, it always
+returns the value of the appropriate variable."
+  (or transient--prefix transient-current-prefix))
+
 (defun transient-suffix-object (&optional command)
   "Return the object associated with the current suffix command.
 
@@ -1428,11 +1531,11 @@ This function is intended to be called by infix 
commands, which
 are usually aliases of `transient--default-infix-command', which
 is defined like this:
 
-   (defun transient--default-infix-command ()
-     (interactive)
-     (let ((obj (transient-suffix-object)))
-       (transient-infix-set obj (transient-infix-read obj)))
-     (transient--show))
+  (defun transient--default-infix-command ()
+    (interactive)
+    (let ((obj (transient-suffix-object)))
+      (transient-infix-set obj (transient-infix-read obj)))
+    (transient--show))
 
 \(User input is read outside of `interactive' to prevent the
 command from being added to `command-history'.  See #23.)
@@ -1477,12 +1580,17 @@ probably use this instead:
                            (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.
-      (transient-init-scope obj)
-      (transient-init-value obj)
-      obj)))
+    (and-let* ((obj (transient--suffix-prototype (or command this-command)))
+               (obj (clone obj)))
+      (progn ; work around debbugs#31840
+        (transient-init-scope obj)
+        (transient-init-value obj)
+        obj))))
+
+(defun transient--suffix-prototype (command)
+  (or (get command 'transient--suffix)
+      (seq-some (lambda (cmd) (get cmd 'transient--suffix))
+                (function-alias-p command))))
 
 ;;; Keymaps
 
@@ -1573,7 +1681,8 @@ to `transient-predicate-map'.  Also see 
`transient-base-map'."
                        (if transient-show-common-commands
                            "Hide common commands"
                          "Show common permanently")))
-               (list "C-x l" "Show/hide suffixes" #'transient-set-level))))))))
+               (list "C-x l" "Show/hide suffixes" #'transient-set-level)
+               (list "C-x a" #'transient-toggle-level-limit))))))))
 
 (defvar-keymap transient-popup-navigation-map
   :doc "One of the keymaps used when popup navigation is enabled.
@@ -1591,6 +1700,16 @@ See `transient-enable-popup-navigation'."
   "<mouse-1>" #'transient-push-button
   "<mouse-2>" #'transient-push-button)
 
+(defvar-keymap transient-resume-mode-map
+  :doc "Keymap for `transient-resume-mode'.
+
+This keymap remaps every command that would usually just quit the
+documentation buffer to `transient-resume', which additionally
+resumes the suspended transient."
+  "<remap> <Man-quit>"    #'transient-resume
+  "<remap> <Info-exit>"   #'transient-resume
+  "<remap> <quit-window>" #'transient-resume)
+
 (defvar-keymap transient-predicate-map
   :doc "Base keymap used to map common commands to their transient behavior.
 
@@ -1626,7 +1745,9 @@ of the corresponding object."
   "<transient-update>"            #'transient--do-stay
   "<transient-toggle-common>"     #'transient--do-stay
   "<transient-set>"               #'transient--do-call
+  "<transient-set-and-exit>"      #'transient--do-exit
   "<transient-save>"              #'transient--do-call
+  "<transient-save-and-exit>"     #'transient--do-exit
   "<transient-reset>"             #'transient--do-call
   "<describe-key-briefly>"        #'transient--do-stay
   "<describe-key>"                #'transient--do-stay
@@ -1702,50 +1823,66 @@ of the corresponding object."
     map))
 
 (defun transient--make-predicate-map ()
-  (let ((map (make-sparse-keymap)))
+  (let* ((default (transient--resolve-pre-command
+                   (oref transient--prefix transient-suffix)))
+         (return (and transient-current-prefix (eq default t)))
+         (map (make-sparse-keymap)))
     (set-keymap-parent map transient-predicate-map)
-    (when (memq (oref transient--prefix transient-non-suffix)
-                '(nil transient--do-warn transient--do-noop))
-      (keymap-set map "<handle-switch-frame>" #'transient--do-suspend))
+    (when (or (and (slot-boundp transient--prefix 'transient-switch-frame)
+                   (transient--resolve-pre-command
+                    (not (oref transient--prefix transient-switch-frame))))
+              (memq (transient--resolve-pre-command
+                     (oref transient--prefix transient-non-suffix))
+                    '(nil transient--do-warn transient--do-noop)))
+      (define-key map [handle-switch-frame] #'transient--do-suspend))
     (dolist (obj transient--suffixes)
       (let* ((cmd (oref obj command))
-             (sub-prefix (and (symbolp cmd) (get cmd 'transient--prefix) t)))
+             (kind (cond ((get cmd 'transient--prefix)    'prefix)
+                         ((cl-typep obj 'transient-infix) 'infix)
+                         (t                               'suffix))))
         (cond
          ((oref obj inapt)
           (define-key map (vector cmd) #'transient--do-warn-inapt))
          ((slot-boundp obj 'transient)
           (define-key map (vector cmd)
-            (let ((do (oref obj transient)))
-              (pcase (list do sub-prefix)
-                ('(t     t) #'transient--do-recurse)
-                ('(t   nil) (if (cl-typep obj 'transient-infix)
-                                #'transient--do-stay
-                              #'transient--do-call))
-                ('(nil   t) #'transient--do-replace)
-                ('(nil nil) #'transient--do-exit)
-                (_          do)))))
+            (pcase (list kind
+                         (transient--resolve-pre-command (oref obj transient))
+                         return)
+              (`(prefix   t ,_) #'transient--do-recurse)
+              (`(prefix nil ,_) #'transient--do-stack)
+              (`(infix    t ,_) #'transient--do-stay)
+              (`(suffix   t ,_) #'transient--do-call)
+              ('(suffix nil  t) #'transient--do-return)
+              (`(,_     nil ,_) #'transient--do-exit)
+              (`(,_     ,do ,_) do))))
          ((not (lookup-key transient-predicate-map (vector cmd)))
           (define-key map (vector cmd)
-            (if sub-prefix
-                #'transient--do-replace
-              (or (oref transient--prefix transient-suffix)
-                  #'transient--do-exit)))))))
+            (pcase (list kind default return)
+              (`(prefix ,(or 'transient--do-stay 'transient--do-call) ,_)
+               #'transient--do-recurse)
+              (`(prefix   t ,_) #'transient--do-recurse)
+              (`(prefix  ,_ ,_) #'transient--do-stack)
+              (`(infix   ,_ ,_) #'transient--do-stay)
+              (`(suffix   t ,_) #'transient--do-call)
+              ('(suffix nil  t) #'transient--do-return)
+              (`(suffix nil ,_) #'transient--do-exit)
+              (`(suffix ,do ,_) do)))))))
     map))
 
 (defun transient--make-redisplay-map ()
   (setq transient--redisplay-key
-        (cl-case this-command
-          (transient-update
+        (pcase this-command
+          ('transient-update
            (setq transient--showp t)
            (setq unread-command-events
                  (listify-key-sequence (this-single-command-raw-keys))))
-          (transient-quit-seq
+          ('transient-quit-seq
            (setq unread-command-events
                  (butlast (listify-key-sequence
                            (this-single-command-raw-keys))
                           2))
            (butlast transient--redisplay-key))
-          (t nil)))
+          (_ nil)))
   (let ((topmap (make-sparse-keymap))
         (submap (make-sparse-keymap)))
     (when transient--redisplay-key
@@ -1789,7 +1926,7 @@ EDIT may be non-nil."
       (setq params (list :scope (oref transient--prefix scope))))
      (transient--prefix
       ;; Invoked as a ":transient-non-suffix 'transient--do-{stay,call}"
-      ;; of an outer prefix.  Unlike the usual `transient--do-replace',
+      ;; of an outer prefix.  Unlike the usual `transient--do-stack',
       ;; these predicates fail to clean up after the outer prefix.
       (transient--pop-keymap 'transient--transient-map)
       (transient--pop-keymap 'transient--redisplay-map))
@@ -1800,10 +1937,8 @@ EDIT may be non-nil."
       ;; Returning from help to edit.
       (setq transient--editp t)))
     (transient--init-objects name layout params)
+    (transient--init-keymaps)
     (transient--history-init transient--prefix)
-    (setq transient--predicate-map (transient--make-predicate-map))
-    (setq transient--transient-map (transient--make-transient-map))
-    (setq transient--redisplay-map (transient--make-redisplay-map))
     (setq transient--original-window (selected-window))
     (setq transient--original-buffer (current-buffer))
     (setq transient--minibuffer-depth (minibuffer-depth))
@@ -1820,8 +1955,16 @@ value.  Otherwise return CHILDREN as is."
       (funcall (oref group setup-children) children)
     children))
 
-(defun transient--init-objects (name layout params)
-  (setq transient--prefix (transient--init-prefix name params))
+(defun transient--init-keymaps ()
+  (setq transient--predicate-map (transient--make-predicate-map))
+  (setq transient--transient-map (transient--make-transient-map))
+  (setq transient--redisplay-map (transient--make-redisplay-map)))
+
+(defun transient--init-objects (&optional name layout params)
+  (if name
+      (setq transient--prefix (transient--init-prefix name params))
+    (setq name (oref transient--prefix command)))
+  (setq transient--refreshp (oref transient--prefix refresh-suffixes))
   (setq transient--layout (or layout (transient--init-suffixes name)))
   (setq transient--suffixes (transient--flatten-suffixes transient--layout)))
 
@@ -1848,10 +1991,11 @@ value.  Otherwise return CHILDREN as is."
   (cl-labels ((s (def)
                 (cond
                  ((stringp def) nil)
+                 ((cl-typep def 'transient-information) nil)
                  ((listp def) (cl-mapcan #'s def))
-                 ((transient-group--eieio-childp def)
+                 ((cl-typep def 'transient-group)
                   (cl-mapcan #'s (oref def suffixes)))
-                 ((transient-suffix--eieio-childp def)
+                 ((cl-typep def 'transient-suffix)
                   (list def)))))
     (cl-mapcan #'s layout)))
 
@@ -1863,31 +2007,37 @@ value.  Otherwise return CHILDREN as is."
 
 (defun transient--init-group (levels spec)
   (pcase-let ((`(,level ,class ,args ,children) (append spec nil)))
-    (when-let* ((- (transient--use-level-p level))
-                (obj (apply class :level level args))
-                (- (transient--use-suffix-p obj))
-                (suffixes (cl-mapcan (lambda (c) (transient--init-child levels 
c))
-                                     (transient-setup-children obj children))))
-      ;; Cannot use and-let* because of debbugs#31840.
-      (oset obj suffixes suffixes)
-      (list obj))))
+    (and-let* ((- (transient--use-level-p level))
+               (obj (apply class :level level args))
+               (- (transient--use-suffix-p obj))
+               (suffixes (cl-mapcan (lambda (c) (transient--init-child levels 
c))
+                                    (transient-setup-children obj children))))
+      (progn ; work around debbugs#31840
+        (oset obj suffixes suffixes)
+        (list obj)))))
 
 (defun transient--init-suffix (levels spec)
   (pcase-let* ((`(,level ,class ,args) spec)
                (cmd (plist-get args :command))
-               (level (or (alist-get cmd levels) level)))
+               (key (transient--kbd (plist-get args :key)))
+               (level (or (alist-get (cons cmd key) levels nil nil #'equal)
+                          (alist-get cmd levels)
+                          level)))
     (let ((fn (and (symbolp cmd)
                    (symbol-function cmd))))
       (when (autoloadp fn)
         (transient--debug "   autoload %s" cmd)
         (autoload-do-load fn)))
     (when (transient--use-level-p level)
-      (unless (and cmd (symbolp cmd))
-        (error "BUG: Non-symbolic suffix command: %s" cmd))
-      (let ((obj (if-let ((proto (get cmd 'transient--suffix)))
-                     (apply #'clone proto :level level args)
-                   (apply class :command cmd :level level args))))
-        (cond ((commandp cmd))
+      (let ((obj (if (child-of-class-p class 'transient-information)
+                     (apply class :level level args)
+                   (unless (and cmd (symbolp cmd))
+                     (error "BUG: Non-symbolic suffix command: %s" cmd))
+                   (if-let ((proto (and cmd (transient--suffix-prototype 
cmd))))
+                       (apply #'clone proto :level level args)
+                     (apply class :command cmd :level level args)))))
+        (cond ((not cmd))
+              ((commandp cmd))
               ((or (cl-typep obj 'transient-switch)
                    (cl-typep obj 'transient-option))
                ;; As a temporary special case, if the package was compiled
@@ -1896,7 +2046,8 @@ value.  Otherwise return CHILDREN as is."
                (defalias cmd #'transient--default-infix-command))
               ((transient--use-suffix-p obj)
                (error "Suffix command %s is not defined or autoloaded" cmd)))
-        (transient--init-suffix-key obj)
+        (unless (cl-typep obj 'transient-information)
+          (transient--init-suffix-key obj))
         (when (transient--use-suffix-p obj)
           (if (transient--inapt-suffix-p obj)
               (oset obj inapt t)
@@ -1920,33 +2071,38 @@ value.  Otherwise return CHILDREN as is."
         (error "No key for %s" (oref obj command))))))
 
 (defun transient--use-level-p (level &optional edit)
-  (or (and transient--editp (not edit))
+  (or transient--all-levels-p
+      (and transient--editp (not edit))
       (and (>= level 1)
            (<= level (oref transient--prefix level)))))
 
 (defun transient--use-suffix-p (obj)
-  (transient--do-suffix-p
-   (oref obj if)
-   (oref obj if-not)
-   (oref obj if-nil)
-   (oref obj if-non-nil)
-   (oref obj if-mode)
-   (oref obj if-not-mode)
-   (oref obj if-derived)
-   (oref obj if-not-derived)
-   t))
+  (let ((transient--shadowed-buffer (current-buffer))
+        (transient--pending-suffix obj))
+    (transient--do-suffix-p
+     (oref obj if)
+     (oref obj if-not)
+     (oref obj if-nil)
+     (oref obj if-non-nil)
+     (oref obj if-mode)
+     (oref obj if-not-mode)
+     (oref obj if-derived)
+     (oref obj if-not-derived)
+     t)))
 
 (defun transient--inapt-suffix-p (obj)
-  (transient--do-suffix-p
-   (oref obj inapt-if)
-   (oref obj inapt-if-not)
-   (oref obj inapt-if-nil)
-   (oref obj inapt-if-non-nil)
-   (oref obj inapt-if-mode)
-   (oref obj inapt-if-not-mode)
-   (oref obj inapt-if-derived)
-   (oref obj inapt-if-not-derived)
-   nil))
+  (let ((transient--shadowed-buffer (current-buffer))
+        (transient--pending-suffix obj))
+    (transient--do-suffix-p
+     (oref obj inapt-if)
+     (oref obj inapt-if-not)
+     (oref obj inapt-if-nil)
+     (oref obj inapt-if-non-nil)
+     (oref obj inapt-if-mode)
+     (oref obj inapt-if-not-mode)
+     (oref obj inapt-if-derived)
+     (oref obj inapt-if-not-derived)
+     nil)))
 
 (defun transient--do-suffix-p
     (if if-not if-nil if-non-nil if-mode if-not-mode if-derived if-not-derived
@@ -1962,14 +2118,15 @@ value.  Otherwise return CHILDREN as is."
    (if-not-mode    (not (if (atom if-not-mode)
                             (eq major-mode if-not-mode)
                           (memq major-mode if-not-mode))))
-   (if-derived          (if (or (atom if-derived) (>= emacs-major-version 30))
+   (if-derived          (if (or (atom if-derived)
+                                (>= emacs-major-version 30))
                             (derived-mode-p if-derived)
                           (apply #'derived-mode-p if-derived)))
    (if-not-derived (not (if (or (atom if-not-derived)
                                 (>= emacs-major-version 30))
                             (derived-mode-p if-not-derived)
                           (apply #'derived-mode-p if-not-derived))))
-   (t default)))
+   (default)))
 
 (defun transient--suffix-predicate (spec)
   (let ((plist (nth 2 spec)))
@@ -2000,6 +2157,17 @@ value.  Otherwise return CHILDREN as is."
     ;; that we just added.
     (setq transient--exitp 'replace)))
 
+(defun transient--refresh-transient ()
+  (transient--debug 'refresh-transient)
+  (transient--pop-keymap 'transient--predicate-map)
+  (transient--pop-keymap 'transient--transient-map)
+  (transient--pop-keymap 'transient--redisplay-map)
+  (transient--init-objects)
+  (transient--init-keymaps)
+  (transient--push-keymap 'transient--transient-map)
+  (transient--push-keymap 'transient--redisplay-map)
+  (transient--redisplay))
+
 (defun transient--pre-command ()
   (transient--debug 'pre-command)
   (transient--with-emergency-exit
@@ -2008,8 +2176,8 @@ value.  Otherwise return CHILDREN as is."
     ;; lead to a suffix being remapped to a non-suffix.  We have to undo
     ;; the remapping in that case.  However, remapping a non-suffix to
     ;; another should remain possible.
-    (when (and (transient--get-predicate-for this-original-command 'suffix)
-               (not (transient--get-predicate-for this-command 'suffix)))
+    (when (and (transient--get-pre-command this-original-command 'suffix)
+               (not (transient--get-pre-command this-command 'suffix)))
       (setq this-command this-original-command))
     (cond
      ((memq this-command '(transient-update transient-quit-seq))
@@ -2033,34 +2201,11 @@ value.  Otherwise return CHILDREN as is."
       (transient--wrap-command))
      (t
       (setq transient--exitp nil)
-      (let ((exitp (eq (transient--do-pre-command) transient--exit)))
+      (let ((exitp (eq (transient--call-pre-command) transient--exit)))
         (transient--wrap-command)
         (when exitp
           (transient--pre-exit)))))))
 
-(defun transient--do-pre-command ()
-  (if-let ((fn (transient--get-predicate-for this-command)))
-      (let ((action (funcall fn)))
-        (when (eq action transient--exit)
-          (setq transient--exitp (or transient--exitp t)))
-        action)
-    (if (let ((keys (this-command-keys-vector)))
-          (eq (aref keys (1- (length keys))) ?\C-g))
-        (setq this-command 'transient-noop)
-      (unless (transient--edebug-command-p)
-        (setq this-command 'transient-undefined)))
-    transient--stay))
-
-(defun transient--get-predicate-for (cmd &optional suffix-only)
-  (or (ignore-errors
-        (lookup-key transient--predicate-map (vector cmd)))
-      (and (not suffix-only)
-           (let ((pred (oref transient--prefix transient-non-suffix)))
-             (pcase pred
-               ('t   #'transient--do-stay)
-               ('nil #'transient--do-warn)
-               (_    pred))))))
-
 (defun transient--pre-exit ()
   (transient--debug 'pre-exit)
   (transient--delete-window)
@@ -2089,8 +2234,9 @@ value.  Otherwise return CHILDREN as is."
            (and (minibuffer-selected-window)
                 (selected-window)))
           (buf (window-buffer transient--window)))
-      ;; Only delete the window if it never showed another buffer.
-      (unless (eq (car (window-parameter transient--window 'quit-restore)) 
'other)
+      ;; Only delete the window if it has never shown another buffer.
+      (unless (eq (car (window-parameter transient--window 'quit-restore))
+                  'other)
         (with-demoted-errors "Error while exiting transient: %S"
           (delete-window transient--window)))
       (kill-buffer buf)
@@ -2166,66 +2312,65 @@ value.  Otherwise return CHILDREN as is."
              (remove-hook 'minibuffer-exit-hook ,exit)))
        ,@body)))
 
-(defun transient--wrap-command ()
-  (if (>= emacs-major-version 30)
-      (transient--wrap-command-30)
-    (transient--wrap-command-29)))
-
-(defun transient--wrap-command-30 ()
-  (letrec
-      ((prefix transient--prefix)
-       (suffix this-command)
-       (advice (lambda (fn &rest args)
-                 (interactive
-                  (lambda (spec)
-                    (let ((abort t))
-                      (unwind-protect
-                         (prog1 (advice-eval-interactive-spec spec)
-                           (setq abort nil))
-                       (when abort
-                          (when-let ((unwind (oref prefix unwind-suffix)))
-                            (transient--debug 'unwind-interactive)
-                            (funcall unwind suffix))
-                          (advice-remove suffix advice)
-                          (oset prefix unwind-suffix nil))))))
-                 (unwind-protect
-                     (apply fn args)
-                   (when-let ((unwind (oref prefix unwind-suffix)))
-                     (transient--debug 'unwind-command)
-                     (funcall unwind suffix))
-                   (advice-remove suffix advice)
-                   (oset prefix unwind-suffix nil)))))
-    (advice-add suffix :around advice '((depth . -99)))))
-
-(defun transient--wrap-command-29 ()
-  (let* ((prefix transient--prefix)
-         (suffix this-command)
-         (advice nil)
-         (advice-interactive
-          (lambda (spec)
-            (let ((abort t))
+(static-if (>= emacs-major-version 30)
+    (defun transient--wrap-command ()
+      (cl-assert
+       (>= emacs-major-version 30) nil
+       "Emacs was downgraded, making it necessary to recompile Transient")
+      (letrec
+          ((prefix transient--prefix)
+           (suffix this-command)
+           (advice (lambda (fn &rest args)
+                     (interactive
+                      (lambda (spec)
+                        (let ((abort t))
+                          (unwind-protect
+                              (prog1 (advice-eval-interactive-spec spec)
+                                (setq abort nil))
+                            (when abort
+                              (when-let ((unwind (oref prefix unwind-suffix)))
+                                (transient--debug 'unwind-interactive)
+                                (funcall unwind suffix))
+                              (advice-remove suffix advice)
+                              (oset prefix unwind-suffix nil))))))
+                     (unwind-protect
+                         (apply fn args)
+                       (when-let ((unwind (oref prefix unwind-suffix)))
+                         (transient--debug 'unwind-command)
+                         (funcall unwind suffix))
+                       (advice-remove suffix advice)
+                       (oset prefix unwind-suffix nil)))))
+        (advice-add suffix :around advice '((depth . -99)))))
+
+  (defun transient--wrap-command ()
+    (let* ((prefix transient--prefix)
+           (suffix this-command)
+           (advice nil)
+           (advice-interactive
+            (lambda (spec)
+              (let ((abort t))
+                (unwind-protect
+                    (prog1 (advice-eval-interactive-spec spec)
+                      (setq abort nil))
+                  (when abort
+                    (when-let ((unwind (oref prefix unwind-suffix)))
+                      (transient--debug 'unwind-interactive)
+                      (funcall unwind suffix))
+                    (advice-remove suffix advice)
+                    (oset prefix unwind-suffix nil))))))
+           (advice-body
+            (lambda (fn &rest args)
               (unwind-protect
-                 (prog1 (advice-eval-interactive-spec spec)
-                   (setq abort nil))
-               (when abort
-                  (when-let ((unwind (oref prefix unwind-suffix)))
-                    (transient--debug 'unwind-interactive)
-                    (funcall unwind suffix))
-                  (advice-remove suffix advice)
-                  (oset prefix unwind-suffix nil))))))
-         (advice-body
-          (lambda (fn &rest args)
-            (unwind-protect
-                (apply fn args)
-              (when-let ((unwind (oref prefix unwind-suffix)))
-                (transient--debug 'unwind-command)
-                (funcall unwind suffix))
-              (advice-remove suffix advice)
-              (oset prefix unwind-suffix nil)))))
-    (setq advice `(lambda (fn &rest args)
-                    (interactive ,advice-interactive)
-                    (apply ',advice-body fn args)))
-    (advice-add suffix :around advice '((depth . -99)))))
+                  (apply fn args)
+                (when-let ((unwind (oref prefix unwind-suffix)))
+                  (transient--debug 'unwind-command)
+                  (funcall unwind suffix))
+                (advice-remove suffix advice)
+                (oset prefix unwind-suffix nil)))))
+      (setq advice `(lambda (fn &rest args)
+                      (interactive ,advice-interactive)
+                      (apply ',advice-body fn args)))
+      (advice-add suffix :around advice '((depth . -99))))))
 
 (defun transient--premature-post-command ()
   (and (equal (this-command-keys-vector) [])
@@ -2246,7 +2391,21 @@ value.  Otherwise return CHILDREN as is."
     (transient--debug 'post-command)
     (transient--with-emergency-exit
       (cond (transient--exitp (transient--post-exit))
-            ((eq this-command (oref transient--prefix command)))
+            ;; If `this-command' is the current transient prefix, then we
+            ;; have already taken care of updating the transient buffer...
+            ((and (eq this-command (oref transient--prefix command))
+                  ;; ... but if `prefix-arg' is non-nil, then the values
+                  ;; of `this-command' and `real-this-command' are untrue
+                  ;; because `prefix-command-preserve-state' changes them.
+                  ;; We cannot use `current-prefix-arg' because it is set
+                  ;; too late (in `command-execute'), and if it were set
+                  ;; earlier, then we likely still would not be able to
+                  ;; rely on it and `prefix-command-preserve-state-hook'
+                  ;; would have to be used to record that a universal
+                  ;; argument is in effect.
+                  (not prefix-arg)))
+            (transient--refreshp
+             (transient--refresh-transient))
             ((let ((old transient--redisplay-map)
                    (new (transient--make-redisplay-map)))
                (unless (equal old new)
@@ -2286,6 +2445,7 @@ value.  Otherwise return CHILDREN as is."
     (setq transient--exitp nil)
     (setq transient--helpp nil)
     (setq transient--editp nil)
+    (setq transient--all-levels-p nil)
     (setq transient--minibuffer-depth 0)
     (run-hooks 'transient-exit-hook)
     (when resume
@@ -2296,6 +2456,7 @@ value.  Otherwise return CHILDREN as is."
   (push (list (oref transient--prefix command)
               transient--layout
               transient--editp
+              :transient-suffix (oref transient--prefix transient-suffix)
               :scope (oref transient--prefix scope))
         transient--stack))
 
@@ -2356,12 +2517,12 @@ value.  Otherwise return CHILDREN as is."
                           (concat ", " (apply #'format args)))
                          (args
                           (concat ", " (apply (car args) (cdr args))))
-                         (t "")))
+                         ("")))
         (apply #'message arg args)))))
 
 (defun transient--emergency-exit ()
   "Exit the current transient command after an error occurred.
-When no transient is active (i.e. when `transient--prefix' is
+When no transient is active (i.e., when `transient--prefix' is
 nil) then do nothing."
   (transient--debug 'emergency-exit)
   (when transient--prefix
@@ -2372,6 +2533,36 @@ nil) then do nothing."
 
 ;;; Pre-Commands
 
+(defun transient--call-pre-command ()
+  (if-let ((fn (transient--get-pre-command this-command)))
+      (let ((action (funcall fn)))
+        (when (eq action transient--exit)
+          (setq transient--exitp (or transient--exitp t)))
+        action)
+    (if (let ((keys (this-command-keys-vector)))
+          (eq (aref keys (1- (length keys))) ?\C-g))
+        (setq this-command 'transient-noop)
+      (unless (transient--edebug-command-p)
+        (setq this-command 'transient-undefined)))
+    transient--stay))
+
+(defun transient--get-pre-command (&optional cmd enforce-type)
+  (or (and (not (eq enforce-type 'non-suffix))
+           (lookup-key transient--predicate-map (vector cmd)))
+      (and (not (eq enforce-type 'suffix))
+           (transient--resolve-pre-command
+            (oref transient--prefix transient-non-suffix)
+            t))))
+
+(defun transient--resolve-pre-command (pre &optional resolve-boolean)
+  (cond ((booleanp pre)
+         (if resolve-boolean
+             (if pre #'transient--do-stay #'transient--do-warn)
+           pre))
+        ((string-match-p "--do-" (symbol-name pre)) pre)
+        ((let ((sym (intern (format "transient--do-%s" pre))))
+           (if (functionp sym) sym pre)))))
+
 (defun transient--do-stay ()
   "Call the command without exporting variables and stay transient."
   transient--stay)
@@ -2412,7 +2603,8 @@ If there is no parent prefix, then behave like 
`transient--do-exit'."
 
 (defun transient--do-leave ()
   "Call the command without exporting variables and exit the transient."
-  transient--stay)
+  (transient--stack-zap)
+  transient--exit)
 
 (defun transient--do-push-button ()
   "Call the command represented by the activated button.
@@ -2427,26 +2619,35 @@ Use that command's pre-command to determine transient 
behavior."
                                    (posn-point (event-start 
last-command-event))
                                  (point))
                                'command)))
-    (transient--do-pre-command)))
+    (transient--call-pre-command)))
 
 (defun transient--do-recurse ()
   "Call the transient prefix command, preparing for return to active transient.
 If there is no parent prefix, then just call the command."
-  (transient--do-replace))
+  (transient--do-stack))
 
 (defun transient--setup-recursion (prefix-obj)
   (when transient--stack
     (let ((command (oref prefix-obj command)))
       (when-let ((suffix-obj (transient-suffix-object command)))
-        (when (and (slot-boundp suffix-obj 'transient)
-                   (memq (oref suffix-obj transient)
-                         (list t #'transient--do-recurse)))
-          (oset prefix-obj transient-suffix 'transient--do-return))))))
+        (when (memq (if (slot-boundp suffix-obj 'transient)
+                        (oref suffix-obj transient)
+                      (oref transient-current-prefix transient-suffix))
+                    (list t #'transient--do-recurse))
+          (oset prefix-obj transient-suffix t))))))
+
+(defun transient--do-stack ()
+  "Call the transient prefix command, stacking the active transient.
+Push the active transient to the transient stack."
+  (transient--export)
+  (transient--stack-push)
+  (setq transient--exitp 'replace)
+  transient--exit)
 
 (defun transient--do-replace ()
-  "Call the transient prefix command, replacing the active transient."
+  "Call the transient prefix command, replacing the active transient.
+Do not push the active transient to the transient stack."
   (transient--export)
-  (transient--stack-push)
   (setq transient--exitp 'replace)
   transient--exit)
 
@@ -2465,7 +2666,9 @@ If there is no parent prefix, then just call the command."
          (setq transient--editp nil)
          (transient-setup)
          transient--stay)
-        (t transient--exit)))
+        (prefix-arg
+         transient--stay)
+        (transient--exit)))
 
 (defun transient--do-quit-all ()
   "Exit all transients without saving the transient stack."
@@ -2477,7 +2680,7 @@ If there is no parent prefix, then just call the command."
 In that case behave like `transient--do-stay', otherwise similar
 to `transient--do-warn'."
   (unless transient-enable-popup-navigation
-    (setq this-command 'transient-popup-navigation-help))
+    (setq this-command 'transient-inhibit-move))
   transient--stay)
 
 (defun transient--do-minus ()
@@ -2488,22 +2691,27 @@ prefix argument and pivot to `transient-update'."
     (setq this-command 'transient-update))
   transient--stay)
 
-(put 'transient--do-stay       'transient-color 'transient-red)
-(put 'transient--do-noop       'transient-color 'transient-red)
-(put 'transient--do-warn       'transient-color 'transient-red)
-(put 'transient--do-warn-inapt 'transient-color 'transient-red)
-(put 'transient--do-call       'transient-color 'transient-red)
-(put 'transient--do-return     'transient-color 'transient-purple)
-(put 'transient--do-exit       'transient-color 'transient-blue)
-(put 'transient--do-recurse    'transient-color 'transient-red)
-(put 'transient--do-replace    'transient-color 'transient-blue)
-(put 'transient--do-suspend    'transient-color 'transient-blue)
-(put 'transient--do-quit-one   'transient-color 'transient-blue)
-(put 'transient--do-quit-all   'transient-color 'transient-blue)
-(put 'transient--do-move       'transient-color 'transient-red)
-(put 'transient--do-minus      'transient-color 'transient-red)
+(put 'transient--do-stay       'transient-face 'transient-key-stay)
+(put 'transient--do-noop       'transient-face 'transient-key-noop)
+(put 'transient--do-warn       'transient-face 'transient-key-noop)
+(put 'transient--do-warn-inapt 'transient-face 'transient-key-noop)
+(put 'transient--do-call       'transient-face 'transient-key-stay)
+(put 'transient--do-return     'transient-face 'transient-key-return)
+(put 'transient--do-exit       'transient-face 'transient-key-exit)
+(put 'transient--do-leave      'transient-face 'transient-key-exit)
+
+(put 'transient--do-recurse    'transient-face 'transient-key-stay)
+(put 'transient--do-stack      'transient-face 'transient-key-stay)
+(put 'transient--do-replace    'transient-face 'transient-key-exit)
+(put 'transient--do-suspend    'transient-face 'transient-key-exit)
+
+(put 'transient--do-quit-one   'transient-face 'transient-key-return)
+(put 'transient--do-quit-all   'transient-face 'transient-key-exit)
+(put 'transient--do-move       'transient-face 'transient-key-stay)
+(put 'transient--do-minus      'transient-face 'transient-key-stay)
 
 ;;; Commands
+;;;; Noop
 
 (defun transient-noop ()
   "Do nothing at all."
@@ -2542,27 +2750,23 @@ prefix argument and pivot to `transient-update'."
     (other-window 1)
     (display-warning 'transient "Inconsistent transient state detected.
 This should never happen.
-Please open an issue and post the shown command log.
-This is a heisenbug, so any additional details might help.
-Thanks!" :error)))
+Please open an issue and post the shown command log." :error)))
 
-(defun transient-toggle-common ()
-  "Toggle whether common commands are always shown."
+(defun transient-inhibit-move ()
+  "Warn the user that popup navigation is disabled."
   (interactive)
-  (setq transient-show-common-commands (not transient-show-common-commands)))
+  (message "To enable use of `%s', please customize `%s'"
+           this-original-command
+           'transient-enable-popup-navigation))
 
-(defun transient-suspend ()
-  "Suspend the current transient.
-It can later be resumed using `transient-resume' while no other
-transient is active."
-  (interactive))
+;;;; Core
 
 (defun transient-quit-all ()
   "Exit all transients without saving the transient stack."
   (interactive))
 
 (defun transient-quit-one ()
-  "Exit the current transients, possibly returning to the previous."
+  "Exit the current transients, returning to outer transient, if any."
   (interactive))
 
 (defun transient-quit-seq ()
@@ -2572,17 +2776,48 @@ transient is active."
 (defun transient-update ()
   "Redraw the transient's state in the popup buffer."
   (interactive)
-  (when (equal this-original-command 'negative-argument)
-    (setq prefix-arg current-prefix-arg)))
+  (setq prefix-arg current-prefix-arg))
 
 (defun transient-show ()
   "Show the transient's state in the popup buffer."
   (interactive)
   (setq transient--showp t))
 
-(defvar-local transient--restore-winconf nil)
+(defun transient-push-button ()
+  "Invoke the suffix command represented by this button."
+  (interactive))
 
-(defvar transient-resume-mode)
+;;;; Suspend
+
+(defun transient-suspend ()
+  "Suspend the current transient.
+It can later be resumed using `transient-resume', while no other
+transient is active."
+  (interactive))
+
+(define-minor-mode transient-resume-mode
+  "Auxiliary minor-mode used to resume a transient after viewing help.")
+
+(defun transient-resume ()
+  "Resume a previously suspended stack of transients."
+  (interactive)
+  (cond (transient--stack
+         (let ((winconf transient--restore-winconf))
+           (kill-local-variable 'transient--restore-winconf)
+           (when transient-resume-mode
+             (transient-resume-mode -1)
+             (quit-window))
+           (when winconf
+             (set-window-configuration winconf)))
+         (transient--stack-pop))
+        (transient-resume-mode
+         (kill-local-variable 'transient--restore-winconf)
+         (transient-resume-mode -1)
+         (quit-window))
+        (t
+         (message "No suspended transient command"))))
+
+;;;; Help
 
 (defun transient-help (&optional interactive)
   "Show help for the active transient or one of its suffixes.\n\n(fn)"
@@ -2599,12 +2834,15 @@ transient is active."
                transient--prefix
              (or (transient-suffix-object)
                  this-original-command)))
-          (setq transient--restore-winconf winconf))
+          (setq-local transient--restore-winconf winconf))
         (fit-window-to-buffer nil (frame-height) (window-height))
         (transient-resume-mode)
-        (message "Type \"q\" to resume transient command.")
+        (message (substitute-command-keys
+                  "Type \\`q' to resume transient command."))
         t))))
 
+;;;; Level
+
 (defun transient-set-level (&optional command level)
   "Set the level of the transient or one of its suffix commands."
   (interactive
@@ -2616,10 +2854,9 @@ transient is active."
           (list command
                 (let ((keys (this-single-command-raw-keys)))
                   (and (lookup-key transient--transient-map keys)
-                       (string-to-number
-                        (let ((transient--active-infix
-                               (transient-suffix-object command)))
-                          (transient--show)
+                       (progn
+                         (transient--show)
+                         (string-to-number
                           (transient--read-number-N
                            (format "Set level for `%s': " command)
                            nil nil (not (eq command prefix)))))))))))
@@ -2630,32 +2867,64 @@ transient is active."
    (level
     (let* ((prefix (oref transient--prefix command))
            (alist (alist-get prefix transient-levels))
-           (sym command))
-      (if (eq command prefix)
-          (progn (oset transient--prefix level level)
-                 (setq sym t))
-        (oset (transient-suffix-object command) level level))
-      (setf (alist-get sym alist) level)
+           (akey command))
+      (cond ((eq command prefix)
+             (oset transient--prefix level level)
+             (setq akey t))
+            (t
+             (oset (transient-suffix-object command) level level)
+             (when (cdr (cl-remove-if-not (lambda (obj)
+                                            (eq (oref obj command) command))
+                                          transient--suffixes))
+               (setq akey (cons command (this-command-keys))))))
+      (setf (alist-get akey alist) level)
       (setf (alist-get prefix transient-levels) alist))
     (transient-save-levels)
     (transient--show))
    (t
     (transient-undefined))))
 
+(transient-define-suffix transient-toggle-level-limit ()
+  "Toggle whether to temporarily displayed suffixes on all levels."
+  :description
+  (lambda ()
+    (cond
+     ((= transient-default-level transient--max-level)
+      "Always displaying all levels")
+     (transient--all-levels-p
+      (format "Hide suffix %s"
+              (propertize
+               (format "levels > %s" (oref (transient-prefix-object) level))
+               'face 'transient-higher-level)))
+     ("Show all suffix levels")))
+  :inapt-if (lambda () (= transient-default-level transient--max-level))
+  :transient t
+  (interactive)
+  (setq transient--all-levels-p (not transient--all-levels-p))
+  (setq transient--refreshp t))
+
+;;;; Value
+
 (defun transient-set ()
-  "Save the value of the active transient for this Emacs session."
+  "Set active transient's value for this Emacs session."
   (interactive)
-  (transient-set-value (or transient--prefix transient-current-prefix)))
+  (transient-set-value (transient-prefix-object)))
+
+(defalias 'transient-set-and-exit 'transient-set
+  "Set active transient's value for this Emacs session and exit.")
 
 (defun transient-save ()
-  "Save the value of the active transient persistenly across Emacs sessions."
+  "Save active transient's value for this and future Emacs sessions."
   (interactive)
-  (transient-save-value (or transient--prefix transient-current-prefix)))
+  (transient-save-value (transient-prefix-object)))
+
+(defalias 'transient-save-and-exit 'transient-save
+  "Save active transient's value for this and future Emacs sessions and exit.")
 
 (defun transient-reset ()
   "Clear the set and saved values of the active transient."
   (interactive)
-  (transient-reset-value (or transient--prefix transient-current-prefix)))
+  (transient-reset-value (transient-prefix-object)))
 
 (defun transient-history-next ()
   "Switch to the next value used for the active transient."
@@ -2682,44 +2951,36 @@ transient is active."
       (oset obj value (nth pos hst))
       (mapc #'transient-init-value transient--suffixes))))
 
-(defun transient-scroll-up (&optional arg)
-  "Scroll text of transient popup window upward ARG lines.
-If ARG is nil scroll near full screen.  This is a wrapper
-around `scroll-up-command' (which see)."
-  (interactive "^P")
-  (with-selected-window transient--window
-    (scroll-up-command arg)))
-
-(defun transient-scroll-down (&optional arg)
-  "Scroll text of transient popup window down ARG lines.
-If ARG is nil scroll near full screen.  This is a wrapper
-around `scroll-down-command' (which see)."
-  (interactive "^P")
-  (with-selected-window transient--window
-    (scroll-down-command arg)))
+;;;; Auxiliary
 
-(defun transient-push-button ()
-  "Invoke the suffix command represented by this button."
-  (interactive))
+(defun transient-toggle-common ()
+  "Toggle whether common commands are permanently shown."
+  (interactive)
+  (setq transient-show-common-commands (not transient-show-common-commands)))
 
-(defun transient-resume ()
-  "Resume a previously suspended stack of transients."
+(defun transient-toggle-debug ()
+  "Toggle debugging statements for transient commands."
   (interactive)
-  (cond (transient--stack
-         (let ((winconf transient--restore-winconf))
-           (kill-local-variable 'transient--restore-winconf)
-           (when transient-resume-mode
-             (transient-resume-mode -1)
-             (quit-window))
-           (when winconf
-             (set-window-configuration winconf)))
-         (transient--stack-pop))
-        (transient-resume-mode
-         (kill-local-variable 'transient--restore-winconf)
-         (transient-resume-mode -1)
-         (quit-window))
-        (t
-         (message "No suspended transient command"))))
+  (setq transient--debug (not transient--debug))
+  (message "Debugging transient %s"
+           (if transient--debug "enabled" "disabled")))
+
+(transient-define-suffix transient-echo-arguments (arguments)
+  "Show the transient's active ARGUMENTS in the echo area.
+Intended for use in prefixes used for demonstration purposes,
+such as when suggesting a new feature or reporting an issue."
+  :transient t
+  :description "Echo arguments"
+  :key "x"
+  (interactive (list (transient-args transient-current-command)))
+  (message "%s: %s"
+           (key-description (this-command-keys))
+           (mapconcat (lambda (arg)
+                        (propertize (if (string-match-p " " arg)
+                                        (format "%S" arg)
+                                      arg)
+                                    'face 'transient-argument))
+                      arguments " ")))
 
 ;;; Value
 ;;;; Init
@@ -2825,28 +3086,18 @@ user using the reader specified by the `reader' slot 
(using the
 `transient-infix' method described below).
 
 For some infix classes the value is changed without reading
-anything in the minibuffer, i.e. the mere act of invoking the
+anything in the minibuffer, i.e., the mere act of invoking the
 infix command determines what the new value should be, based
 on the previous value.")
 
 (cl-defmethod transient-infix-read :around ((obj transient-infix))
-  "Highlight the infix in the popup buffer.
+  "Refresh the transient buffer buffer calling the next method.
 
-This also wraps the call to `cl-call-next-method' with two
-macros.
-
-`transient--with-suspended-override' is necessary to allow
-reading user input using the minibuffer.
-
-`transient--with-emergency-exit' arranges for the transient to
-be exited in case of an error because otherwise Emacs would get
-stuck in an inconsistent state, which might make it necessary to
-kill it from the outside.
-
-If you replace this method, then you must make sure to always use
-the latter macro and most likely also the former."
-  (let ((transient--active-infix obj))
-    (transient--show))
+Also wrap `cl-call-next-method' with two macros:
+- `transient--with-suspended-override' allows use of minibuffer.
+- `transient--with-emergency-exit' arranges for the transient to
+  be exited in case of an error."
+  (transient--show)
   (transient--with-emergency-exit
     (transient--with-suspended-override
      (cl-call-next-method obj))))
@@ -2864,7 +3115,7 @@ the lack of history, for example.
 
 Only for very simple classes that toggle or cycle through a very
 limited number of possible values should you replace this with a
-simple method that does not handle history.  (E.g. for a command
+simple method that does not handle history.  (E.g., for a command
 line switch the only possible values are \"use it\" and \"don't use
 it\", in which case it is pointless to preserve history.)"
   (with-slots (value multi-value always-read allow-empty choices) obj
@@ -2875,6 +3126,7 @@ it\", in which case it is pointless to preserve history.)"
         (oset obj value nil)
       (let* ((enable-recursive-minibuffers t)
              (reader (oref obj reader))
+             (choices (if (functionp choices) (funcall choices) choices))
              (prompt (transient-prompt obj))
              (value (if multi-value (mapconcat #'identity value ",") value))
              (history-key (or (oref obj history-key)
@@ -2897,7 +3149,7 @@ it\", in which case it is pointless to preserve history.)"
                                           initial-input history))
                (choices
                 (completing-read prompt choices nil t initial-input history))
-               (t (read-string prompt initial-input history)))))
+               ((read-string prompt initial-input history)))))
         (cond ((and (equal value "") (not allow-empty))
                (setq value nil))
               ((and (equal value "\"\"") allow-empty)
@@ -2929,7 +3181,7 @@ The last value is \"don't use any of these switches\"."
 Use this if you want to share an infix's history with a regular
 stand-alone command."
   (cl-letf (((symbol-function #'transient--show) #'ignore))
-    (transient-infix-read (get command 'transient--suffix))))
+    (transient-infix-read (transient--suffix-prototype command))))
 
 ;;;; Readers
 
@@ -3020,8 +3272,6 @@ prompt."
 
 ;;;; Set
 
-(defvar transient--unset-incompatible t)
-
 (cl-defgeneric transient-infix-set (obj value)
   "Set the value of infix object OBJ to value.")
 
@@ -3029,29 +3279,32 @@ prompt."
   "Set the value of infix object OBJ to value."
   (oset obj value value))
 
-(cl-defmethod transient-infix-set :around ((obj transient-argument) value)
+(cl-defmethod transient-infix-set :after ((obj transient-argument) value)
   "Unset incompatible infix arguments."
-  (let ((arg (if (slot-boundp obj 'argument)
-                 (oref obj argument)
-               (oref obj argument-regexp))))
-    (if-let ((sic (and value arg transient--unset-incompatible))
-             (spec (oref transient--prefix incompatible))
-             (incomp (cl-mapcan (lambda (rule)
-                                  (and (member arg rule)
-                                       (remove arg rule)))
-                                spec)))
-        (progn
-          (cl-call-next-method obj value)
-          (dolist (arg incomp)
-            (when-let ((obj (cl-find-if
-                             (lambda (obj)
-                               (and (slot-exists-p obj 'argument)
-                                    (slot-boundp obj 'argument)
-                                    (equal (oref obj argument) arg)))
-                             transient--suffixes)))
-              (let ((transient--unset-incompatible nil))
-                (transient-infix-set obj nil)))))
-      (cl-call-next-method obj value))))
+  (when-let* ((--- value)
+              (val (transient-infix-value obj))
+              (arg (if (slot-boundp obj 'argument)
+                       (oref obj argument)
+                     (oref obj argument-format)))
+              (spec (oref transient--prefix incompatible))
+              (filter (lambda (x rule)
+                        (and (member x rule)
+                             (remove x rule))))
+              (incomp (nconc
+                       (cl-mapcan (apply-partially filter arg) spec)
+                       (and (not (equal val arg))
+                            (cl-mapcan (apply-partially filter val) spec)))))
+    (dolist (obj transient--suffixes)
+      (when-let* ((--- (cl-typep obj 'transient-argument))
+                  (val (transient-infix-value obj))
+                  (arg (if (slot-boundp obj 'argument)
+                           (oref obj argument)
+                         (oref obj argument-format)))
+                  (--- (if (equal val arg)
+                           (member arg incomp)
+                         (or (member val incomp)
+                             (member arg incomp)))))
+        (transient-infix-set obj nil)))))
 
 (cl-defgeneric transient-set-value (obj)
   "Set the value of the transient prefix OBJ.")
@@ -3114,11 +3367,11 @@ the set, saved or default value for PREFIX."
 
 (defun transient--get-wrapped-value (obj)
   (and-let* ((value (transient-infix-value obj)))
-    (cl-ecase (and (slot-exists-p obj 'multi-value)
-                   (oref obj multi-value))
-      ((nil)    (list value))
-      ((t rest) (list value))
-      (repeat   value))))
+    (pcase-exhaustive (and (slot-exists-p obj 'multi-value)
+                           (oref obj multi-value))
+      ('nil          (list value))
+      ((or 't 'rest) (list value))
+      ('repeat       value))))
 
 (cl-defgeneric transient-infix-value (obj)
   "Return the value of the suffix object OBJ.
@@ -3153,17 +3406,17 @@ does nothing." nil)
   "Return ARGUMENT and VALUE as a unit or nil if the latter is nil."
   (and-let* ((value (oref obj value)))
     (let ((arg (oref obj argument)))
-      (cl-ecase (oref obj multi-value)
-        ((nil)    (concat arg value))
-        ((t rest) (cons arg value))
-        (repeat   (mapcar (lambda (v) (concat arg v)) value))))))
+      (pcase-exhaustive (oref obj multi-value)
+        ('nil          (concat arg value))
+        ((or 't 'rest) (cons arg value))
+        ('repeat       (mapcar (lambda (v) (concat arg v)) value))))))
 
 (cl-defmethod transient-infix-value ((_   transient-variable))
   "Return nil, which means \"no value\".
 
 Setting the value of a variable is done by, well, setting the
-value of the variable.  I.e. this is a side-effect and does not
-contribute to the value of the transient."
+value of the variable.  I.e., this is a side-effect and does
+not contribute to the value of the transient."
   nil)
 
 ;;;; Utilities
@@ -3245,12 +3498,13 @@ have a history of their own.")
                    (list (propertize (oref suffix key) 'face 
'transient-key)))))
           transient--suffixes)
          #'string<)
-        (propertize "|" 'face 'transient-unreachable-key))))))
+        (propertize "|" 'face 'transient-delimiter))))))
 
 (defun transient--show ()
   (transient--timer-cancel)
   (setq transient--showp t)
-  (let ((buf (get-buffer-create transient--buffer-name))
+  (let ((transient--shadowed-buffer (current-buffer))
+        (buf (get-buffer-create transient--buffer-name))
         (focus nil))
     (with-current-buffer buf
       (when transient-enable-popup-navigation
@@ -3263,9 +3517,11 @@ have a history of their own.")
       (when (bound-and-true-p tab-line-format)
         (setq tab-line-format nil))
       (setq header-line-format nil)
-      (setq mode-line-format (if (eq transient-mode-line-format 'line)
-                                 nil
-                               transient-mode-line-format))
+      (setq mode-line-format
+            (if (or (natnump transient-mode-line-format)
+                    (eq transient-mode-line-format 'line))
+                nil
+              transient-mode-line-format))
       (setq mode-line-buffer-identification
             (symbol-name (oref transient--prefix command)))
       (if transient-enable-popup-navigation
@@ -3276,16 +3532,8 @@ have a history of their own.")
       (transient--insert-groups)
       (when (or transient--helpp transient--editp)
         (transient--insert-help))
-      (when (and (eq transient-mode-line-format 'line)
-                 window-system)
-        (let ((face
-               (if-let ((f (and (transient--semantic-coloring-p)
-                                (transient--prefix-color transient--prefix))))
-                   `(,@(and (>= emacs-major-version 27) '(:extend t))
-                     :background ,(face-foreground f))
-                 'transient-separator)))
-          (insert (propertize "__" 'face face 'display '(space :height (1))))
-          (insert (propertize "\n" 'face face 'line-height t))))
+      (when-let ((line (transient--separator-line)))
+        (insert line))
       (when transient-force-fixed-pitch
         (transient--force-fixed-pitch)))
     (unless (window-live-p transient--window)
@@ -3307,11 +3555,31 @@ have a history of their own.")
         (fit-window-to-buffer window nil (window-height window))
       (fit-window-to-buffer window nil 1))))
 
+(defun transient--separator-line ()
+  (and-let* ((height (cond ((not window-system) nil)
+                           ((natnump transient-mode-line-format)
+                            transient-mode-line-format)
+                           ((eq transient-mode-line-format 'line) 1)))
+             (face `(,@(and (>= emacs-major-version 27) '(:extend t))
+                     :background
+                     ,(or (face-foreground (transient--key-face nil 
'non-suffix)
+                                           nil t)
+                          "#gray60"))))
+    (concat (propertize "__" 'face face 'display `(space :height (,height)))
+            (propertize "\n" 'face face 'line-height t))))
+
+(defmacro transient-with-shadowed-buffer (&rest body)
+  "While in the transient buffer, temporarily make the shadowed buffer 
current."
+  (declare (indent 0) (debug t))
+  `(with-current-buffer (or transient--shadowed-buffer (current-buffer))
+     ,@body))
+
 (defun transient--insert-groups ()
   (let ((groups (cl-mapcan (lambda (group)
                              (let ((hide (oref group hide)))
                                (and (not (and (functionp hide)
-                                              (funcall   hide)))
+                                              (transient-with-shadowed-buffer
+                                                (funcall hide))))
                                     (list group))))
                            transient--layout))
         group)
@@ -3327,23 +3595,25 @@ have a history of their own.")
 
 (cl-defmethod transient--insert-group :around ((group transient-group))
   "Insert GROUP's description, if any."
-  (when-let ((desc (transient-format-description group)))
+  (when-let ((desc (transient-with-shadowed-buffer
+                     (transient-format-description group))))
     (insert desc ?\n))
   (let ((transient--max-group-level
-         (max (oref group level) transient--max-group-level)))
+         (max (oref group level) transient--max-group-level))
+        (transient--pending-group group))
     (cl-call-next-method group)))
 
 (cl-defmethod transient--insert-group ((group transient-row))
   (transient--maybe-pad-keys group)
   (dolist (suffix (oref group suffixes))
-    (insert (transient-format suffix))
+    (insert (transient-with-shadowed-buffer (transient-format suffix)))
     (insert "   "))
   (insert ?\n))
 
 (cl-defmethod transient--insert-group ((group transient-column))
   (transient--maybe-pad-keys group)
   (dolist (suffix (oref group suffixes))
-    (let ((str (transient-format suffix)))
+    (let ((str (transient-with-shadowed-buffer (transient-format suffix))))
       (insert str)
       (unless (string-match-p ".\n\\'" str)
         (insert ?\n)))))
@@ -3353,10 +3623,11 @@ have a history of their own.")
           (mapcar
            (lambda (column)
              (transient--maybe-pad-keys column group)
-             (let ((rows (mapcar #'transient-format (oref column suffixes))))
-               (when-let ((desc (transient-format-description column)))
-                 (push desc rows))
-               (flatten-tree rows)))
+             (transient-with-shadowed-buffer
+               (let ((rows (mapcar #'transient-format (oref column suffixes))))
+                 (when-let ((desc (transient-format-description column)))
+                   (push desc rows))
+                 (flatten-tree rows))))
            (oref group suffixes)))
          (vp (or (oref transient--prefix variable-pitch)
                  transient-align-variable-pitch))
@@ -3396,15 +3667,6 @@ have a history of their own.")
             (when (= c (1- cs))
               (insert ?\n))))))))
 
-(defun transient--pixel-width (string)
-  (save-window-excursion
-    (with-temp-buffer
-      (insert string)
-      (set-window-dedicated-p nil nil)
-      (set-window-buffer nil (current-buffer))
-      (car (window-text-pixel-size
-            nil (line-beginning-position) (point))))))
-
 (cl-defmethod transient--insert-group ((group transient-subgroups))
   (let* ((subgroups (oref group suffixes))
          (n (length subgroups)))
@@ -3435,36 +3697,31 @@ making `transient--original-buffer' current.")
   "Return a string containing just the ARG character."
   (char-to-string arg))
 
-(cl-defmethod transient-format :around ((obj transient-infix))
-  "When reading user input for this infix, then highlight it."
+(cl-defmethod transient-format :around ((obj transient-suffix))
+  "Add additional formatting if appropriate.
+When reading user input for this infix, then highlight it.
+When edit-mode is enabled, then prepend the level information.
+When `transient-enable-popup-navigation' is non-nil then format
+as a button."
   (let ((str (cl-call-next-method obj)))
-    (when (eq obj transient--active-infix)
-      (setq str (concat str "\n"))
-      (add-face-text-property
-       (if (eq this-command 'transient-set-level) 3 0)
-       (length str)
-       'transient-active-infix nil str))
+    (when (and (cl-typep obj 'transient-infix)
+               (eq (oref obj command) this-original-command)
+               (active-minibuffer-window))
+      (setq str (transient--add-face str 'transient-active-infix)))
+    (when transient--editp
+      (setq str (concat (let ((level (oref obj level)))
+                          (propertize (format " %s " level)
+                                      'face (if (transient--use-level-p level 
t)
+                                                'transient-enabled-suffix
+                                              'transient-disabled-suffix)))
+                        str)))
+    (when (and transient-enable-popup-navigation
+               (slot-boundp obj 'command))
+      (setq str (make-text-button str nil
+                                  'type 'transient
+                                  'command (oref obj command))))
     str))
 
-(cl-defmethod transient-format :around ((obj transient-suffix))
-  "When edit-mode is enabled, then prepend the level information.
-Optional support for popup buttons is also implemented here."
-  (let ((str (concat
-              (and transient--editp
-                   (let ((level (oref obj level)))
-                     (propertize (format " %s " level)
-                                 'face (if (transient--use-level-p level t)
-                                           'transient-enabled-suffix
-                                         'transient-disabled-suffix))))
-              (cl-call-next-method obj))))
-    (when (oref obj inapt)
-      (add-face-text-property 0 (length str) 'transient-inapt-suffix nil str))
-    (if transient-enable-popup-navigation
-        (make-text-button str nil
-                          'type 'transient
-                          'command (oref obj command))
-      str)))
-
 (cl-defmethod transient-format ((obj transient-infix))
   "Return a string generated using OBJ's `format'.
 %k is formatted using `transient-format-key'.
@@ -3486,10 +3743,19 @@ Optional support for popup buttons is also implemented 
here."
 (cl-defgeneric transient-format-key (obj)
   "Format OBJ's `key' for display and return the result.")
 
+(cl-defmethod transient-format-key :around ((obj transient-suffix))
+  "Add `transient-inapt-suffix' face if suffix is inapt."
+  (let ((str (cl-call-next-method)))
+    (if (oref obj inapt)
+        (transient--add-face str 'transient-inapt-suffix)
+      str)))
+
 (cl-defmethod transient-format-key ((obj transient-suffix))
   "Format OBJ's `key' for display and return the result."
-  (let ((key (oref obj key))
-        (cmd (oref obj command)))
+  (let ((key (if (slot-boundp obj 'key) (oref obj key) ""))
+        (cmd (and (slot-boundp obj 'command) (oref obj command))))
+    (when-let ((width (oref transient--pending-group pad-keys)))
+      (setq key (truncate-string-to-width key width nil ?\s)))
     (if transient--redisplay-key
         (let ((len (length transient--redisplay-key))
               (seq (cl-coerce (edmacro-parse-keys key t) 'list)))
@@ -3506,7 +3772,7 @@ Optional support for popup buttons is also implemented 
here."
               (setq pre (string-replace "TAB" "C-i" pre))
               (setq suf (string-replace "RET" "C-m" suf))
               (setq suf (string-replace "TAB" "C-i" suf))
-              ;; We use e.g. "-k" instead of the more correct "- k",
+              ;; We use e.g., "-k" instead of the more correct "- k",
               ;; because the former is prettier.  If we did that in
               ;; the definition, then we want to drop the space that
               ;; is reinserted above.  False-positives are possible
@@ -3516,33 +3782,27 @@ Optional support for popup buttons is also implemented 
here."
                 (setq suf (string-replace " " "" suf)))
               (concat (propertize pre 'face 'transient-unreachable-key)
                       (and (string-prefix-p (concat pre " ") key) " ")
-                      (transient--colorize-key suf cmd)
+                      (propertize suf 'face (transient--key-face cmd))
                       (save-excursion
                         (and (string-match " +\\'" key)
                              (propertize (match-string 0 key)
                                          'face 'fixed-pitch))))))
            ((transient--lookup-key transient-sticky-map (kbd key))
-            (transient--colorize-key key cmd))
+            (propertize key 'face (transient--key-face cmd)))
            (t
             (propertize key 'face 'transient-unreachable-key))))
-      (transient--colorize-key key cmd))))
-
-(defun transient--colorize-key (key command)
-  (propertize key 'face
-              (or (and (transient--semantic-coloring-p)
-                       (transient--suffix-color command))
-                  'transient-key)))
+      (propertize key 'face (transient--key-face cmd)))))
 
 (cl-defmethod transient-format-key :around ((obj transient-argument))
+  "Handle `transient-highlight-mismatched-keys'."
   (let ((key (cl-call-next-method obj)))
-    (cond ((not transient-highlight-mismatched-keys))
-          ((not (slot-boundp obj 'shortarg))
-           (add-face-text-property
-            0 (length key) 'transient-nonstandard-key nil key))
-          ((not (string-equal key (oref obj shortarg)))
-           (add-face-text-property
-            0 (length key) 'transient-mismatched-key nil key)))
-    key))
+    (cond
+     ((not transient-highlight-mismatched-keys) key)
+     ((not (slot-boundp obj 'shortarg))
+      (transient--add-face key 'transient-nonstandard-key))
+     ((not (string-equal key (oref obj shortarg)))
+      (transient--add-face key 'transient-mismatched-key))
+     (key))))
 
 (cl-defgeneric transient-format-description (obj)
   "Format OBJ's `description' for display and return the result.")
@@ -3551,10 +3811,14 @@ Optional support for popup buttons is also implemented 
here."
   "The `description' slot may be a function, in which case that is
 called inside the correct buffer (see `transient--insert-group')
 and its value is returned to the caller."
-  (and-let* ((desc (oref obj description)))
-    (if (functionp desc)
-        (with-current-buffer transient--original-buffer
-          (funcall desc))
+  (and-let* ((desc (oref obj description))
+             (desc (if (functionp desc)
+                       (if (= (car (func-arity desc)) 1)
+                           (funcall desc obj)
+                         (funcall desc))
+                     desc)))
+    (if-let* ((face (transient--get-face obj 'face)))
+        (transient--add-face desc face t)
       desc)))
 
 (cl-defmethod transient-format-description ((obj transient-group))
@@ -3576,16 +3840,19 @@ If the OBJ's `key' is currently unreachable, then apply 
the face
                        (funcall (oref transient--prefix suffix-description)
                                 obj))
                   (propertize "(BUG: no description)" 'face 'error))))
-    (cond ((transient--key-unreachable-p obj)
-           (propertize desc 'face 'transient-unreachable))
-          ((and transient-highlight-higher-levels
-                (> (max (oref obj level) transient--max-group-level)
-                   transient--default-prefix-level))
-           (add-face-text-property
-            0 (length desc) 'transient-higher-level nil desc)
-           desc)
-          (t
-           desc))))
+    (when (if transient--all-levels-p
+              (> (oref obj level) transient--default-prefix-level)
+            (and transient-highlight-higher-levels
+                 (> (max (oref obj level) transient--max-group-level)
+                    transient--default-prefix-level)))
+      (setq desc (transient--add-face desc 'transient-higher-level)))
+    (when-let ((inapt-face (and (oref obj inapt)
+                                (transient--get-face obj 'inapt-face))))
+      (setq desc (transient--add-face desc inapt-face)))
+    (when (and (slot-boundp obj 'key)
+               (transient--key-unreachable-p obj))
+      (setq desc (transient--add-face desc 'transient-unreachable)))
+    desc))
 
 (cl-defgeneric transient-format-value (obj)
   "Format OBJ's value for display and return the result.")
@@ -3599,24 +3866,32 @@ If the OBJ's `key' is currently unreachable, then apply 
the face
 (cl-defmethod transient-format-value ((obj transient-option))
   (let ((argument (oref obj argument)))
     (if-let ((value (oref obj value)))
-        (propertize
-         (cl-ecase (oref obj multi-value)
-           ((nil)    (concat argument value))
-           ((t rest) (concat argument
-                             (and (not (string-suffix-p " " argument)) " ")
-                             (mapconcat #'prin1-to-string value " ")))
-           (repeat   (mapconcat (lambda (v) (concat argument v)) value " ")))
-         'face 'transient-value)
-      (propertize argument 'face 'transient-inactive-value))))
+        (pcase-exhaustive (oref obj multi-value)
+          ('nil
+           (concat (propertize argument 'face 'transient-argument)
+                   (propertize value    'face 'transient-value)))
+          ((or 't 'rest)
+           (concat (propertize (if (string-suffix-p " " argument)
+                                   argument
+                                 (concat argument " "))
+                               'face 'transient-argument)
+                   (propertize (mapconcat #'prin1-to-string value " ")
+                               'face 'transient-value)))
+          ('repeat
+           (mapconcat (lambda (value)
+                        (concat (propertize argument 'face 'transient-argument)
+                                (propertize value    'face 'transient-value)))
+                      value " ")))
+      (propertize argument 'face 'transient-inactive-argument))))
 
 (cl-defmethod transient-format-value ((obj transient-switches))
   (with-slots (value argument-format choices) obj
     (format (propertize argument-format
                         'face (if value
-                                  'transient-value
-                                'transient-inactive-value))
-            (concat
-             (propertize "[" 'face 'transient-inactive-value)
+                                  'transient-argument
+                                'transient-inactive-argument))
+            (format
+             (propertize "[%s]" 'face 'transient-delimiter)
              (mapconcat
               (lambda (choice)
                 (propertize choice 'face
@@ -3624,8 +3899,30 @@ If the OBJ's `key' is currently unreachable, then apply 
the face
                                 'transient-value
                               'transient-inactive-value)))
               choices
-              (propertize "|" 'face 'transient-inactive-value))
-             (propertize "]" 'face 'transient-inactive-value)))))
+              (propertize "|" 'face 'transient-delimiter))))))
+
+(defun transient--add-face (string face &optional append beg end)
+  (let ((str (copy-sequence string)))
+    (add-face-text-property (or beg 0) (or end (length str)) face append str)
+    str))
+
+(defun transient--get-face (obj slot)
+  (and-let* ((! (slot-exists-p obj slot))
+             (! (slot-boundp   obj slot))
+             (face (slot-value obj slot)))
+    (if (and (not (facep face))
+             (functionp face))
+        (funcall face)
+      face)))
+
+(defun transient--key-face (&optional cmd enforce-type)
+  (or (and transient-semantic-coloring
+           (not transient--helpp)
+           (not transient--editp)
+           (or (and cmd (get cmd 'transient-face))
+               (get (transient--get-pre-command cmd enforce-type)
+                    'transient-face)))
+      (if cmd 'transient-key 'transient-key-noop)))
 
 (defun transient--key-unreachable-p (obj)
   (and transient--redisplay-key
@@ -3640,19 +3937,24 @@ If the OBJ's `key' is currently unreachable, then apply 
the face
     (and val (not (integerp val)) val)))
 
 (defun transient--maybe-pad-keys (group &optional parent)
-  (when-let ((pad (if (slot-boundp group 'pad-keys)
-                      (oref group pad-keys)
-                    (and parent
-                         (slot-boundp parent 'pad-keys)
-                         (oref parent pad-keys)))))
-    (let ((width (apply #'max
-                        (cons (if (integerp pad) pad 0)
-                              (mapcar (lambda (suffix)
-                                        (length (oref suffix key)))
-                                      (oref group suffixes))))))
-      (dolist (suffix (oref group suffixes))
-        (oset suffix key
-              (truncate-string-to-width (oref suffix key) width nil ?\s))))))
+  (when-let ((pad (or (oref group pad-keys)
+                      (and parent (oref parent pad-keys)))))
+    (oset group pad-keys
+          (apply #'max (cons (if (integerp pad) pad 0)
+                             (seq-keep (lambda (suffix)
+                                         (and (eieio-object-p suffix)
+                                              (slot-boundp suffix 'key)
+                                              (length (oref suffix key))))
+                                       (oref group suffixes)))))))
+
+(defun transient--pixel-width (string)
+  (save-window-excursion
+    (with-temp-buffer
+      (insert string)
+      (set-window-dedicated-p nil nil)
+      (set-window-buffer nil (current-buffer))
+      (car (window-text-pixel-size
+            nil (line-beginning-position) (point))))))
 
 (defun transient-command-summary-or-name (obj)
   "Return the summary or name of the command represented by OBJ.
@@ -3680,7 +3982,7 @@ if non-nil, else show the `man-page' if non-nil, else use
     (cond (show-help (funcall show-help obj))
           (info-manual (transient--show-manual info-manual))
           (man-page (transient--show-manpage man-page))
-          (t (transient--describe-function command)))))
+          ((transient--describe-function command)))))
 
 (cl-defmethod transient-show-help ((obj transient-suffix))
   "Call `show-help' if non-nil, else use `describe-function'.
@@ -3694,9 +3996,9 @@ prefix method."
                        'transient--prefix)))
       (and prefix (not (eq (oref transient--prefix command) this-command))
            (prog1 t (transient-show-help prefix)))))
-   (t (if-let ((show-help (oref obj show-help)))
-          (funcall show-help obj)
-        (transient--describe-function this-command)))))
+   ((if-let ((show-help (oref obj show-help)))
+        (funcall show-help obj)
+      (transient--describe-function this-command)))))
 
 (cl-defmethod transient-show-help ((obj transient-infix))
   "Call `show-help' if non-nil, else show the `man-page'
@@ -3716,7 +4018,7 @@ manpage, then try to jump to the correct location."
   (transient--describe-function cmd))
 
 (defun transient--describe-function (fn)
-  (describe-function (if (symbolp fn) fn 'transient--anonymous-infix-argument))
+  (describe-function fn)
   (unless (derived-mode-p 'help-mode)
     (when-let* ((buf (get-buffer "*Help*"))
                 (win (or (and buf (get-buffer-window buf))
@@ -3726,21 +4028,6 @@ manpage, then try to jump to the correct location."
                                      (window-list)))))
       (select-window win))))
 
-(defun transient--anonymous-infix-argument ()
-  "Cannot show any documentation for this anonymous infix command.
-
-The infix command in question was defined anonymously, i.e.,
-it was define when the prefix command that it belongs to was
-defined, which means that it gets no docstring and also that
-no symbol is bound to it.
-
-When you request help for an infix command, then we usually
-show the respective man-page and jump to the location where
-the respective argument is being described.
-
-Because the containing prefix command does not specify any
-man-page, we cannot do that in this case.  Sorry about that.")
-
 (defun transient--show-manual (manual)
   (info manual))
 
@@ -3833,37 +4120,23 @@ Suffixes on levels %s and %s are unavailable.\n"
                (propertize (format ">=%s" (1+ level))
                            'face 'transient-disabled-suffix))))))
 
-(defvar-keymap transient-resume-mode-map
-  :doc "Keymap for `transient-resume-mode'.
-
-This keymap remaps every command that would usually just quit the
-documentation buffer to `transient-resume', which additionally
-resumes the suspended transient."
-  "<remap> <Man-quit>"    #'transient-resume
-  "<remap> <Info-exit>"   #'transient-resume
-  "<remap> <quit-window>" #'transient-resume)
-
-(define-minor-mode transient-resume-mode
-  "Auxiliary minor-mode used to resume a transient after viewing help.")
-
-(defun transient-toggle-debug ()
-  "Toggle debugging statements for transient commands."
-  (interactive)
-  (setq transient--debug (not transient--debug))
-  (message "Debugging transient %s"
-           (if transient--debug "enabled" "disabled")))
-
 ;;; Popup Navigation
 
-(defun transient-popup-navigation-help ()
-  "Inform the user how to enable popup navigation commands."
-  (interactive)
-  (message "This command is only available if `%s' is non-nil"
-           'transient-enable-popup-navigation))
+(defun transient-scroll-up (&optional arg)
+  "Scroll text of transient popup window upward ARG lines.
+If ARG is nil scroll near full screen.  This is a wrapper
+around `scroll-up-command' (which see)."
+  (interactive "^P")
+  (with-selected-window transient--window
+    (scroll-up-command arg)))
 
-(define-button-type 'transient
-  'face nil
-  'keymap transient-button-map)
+(defun transient-scroll-down (&optional arg)
+  "Scroll text of transient popup window down ARG lines.
+If ARG is nil scroll near full screen.  This is a wrapper
+around `scroll-down-command' (which see)."
+  (interactive "^P")
+  (with-selected-window transient--window
+    (scroll-down-command arg)))
 
 (defun transient-backward-button (n)
   "Move to the previous button in the transient popup buffer.
@@ -3879,6 +4152,10 @@ See `forward-button' for information about N."
   (with-selected-window transient--window
     (forward-button n t)))
 
+(define-button-type 'transient
+  'face nil
+  'keymap transient-button-map)
+
 (defun transient--goto-button (command)
   (cond
    ((stringp command)
@@ -3956,36 +4233,6 @@ search instead."
   (select-window transient--original-window)
   (transient--resume-override))
 
-;;;; Hydra Color Emulation
-
-(defun transient--semantic-coloring-p ()
-  (and transient-semantic-coloring
-       (not transient--helpp)
-       (not transient--editp)))
-
-(defun transient--suffix-color (command)
-  (or (get command 'transient-color)
-      (get (transient--get-predicate-for command) 'transient-color)))
-
-(defun transient--prefix-color (command)
-  (let* ((nonsuf (or (oref command transient-non-suffix)
-                     'transient--do-warn))
-         (nonsuf (if (memq nonsuf '(transient--do-noop transient--do-warn))
-                     'disallow
-                   (get nonsuf 'transient-color)))
-         (suffix (if-let ((pred (oref command transient-suffix)))
-                     (get pred 'transient-color)
-                   (if (eq nonsuf 'transient-red)
-                       'transient-red
-                     'transient-blue))))
-    (pcase (list suffix nonsuf)
-      (`(transient-purple ,_)           'transient-purple)
-      ('(transient-red  disallow)       'transient-amaranth)
-      ('(transient-blue disallow)       'transient-teal)
-      ('(transient-red  transient-red)  'transient-pink)
-      ('(transient-red  transient-blue) 'transient-red)
-      ('(transient-blue transient-blue) 'transient-blue))))
-
 ;;;; Edebug
 
 (defun transient--edebug-command-p ()
@@ -4047,7 +4294,7 @@ we stop there."
   (let ((key (oref obj key)))
     (cond ((string-equal key "q") "Q")
           ((string-equal key "Q") "M-q")
-          (t key))))
+          (key))))
 
 (defun transient--force-fixed-pitch ()
   (require 'face-remap)
@@ -4082,8 +4329,7 @@ we stop there."
                 (regexp-opt (list "transient-define-prefix"
                                   "transient-define-infix"
                                   "transient-define-argument"
-                                  "transient-define-suffix"
-                                  "transient-define-groups")
+                                  "transient-define-suffix")
                             t)
                 "\\_>[ \t'(]*"
                 "\\(\\(?:\\sw\\|\\s_\\)+\\)?")
diff --git a/lisp/tree-widget.el b/lisp/tree-widget.el
index 01091f5493b..9321bff0373 100644
--- a/lisp/tree-widget.el
+++ b/lisp/tree-widget.el
@@ -1,6 +1,6 @@
 ;;; tree-widget.el --- Tree widget  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: David Ponce <david@dponce.com>
 ;; Created: 16 Feb 2001
diff --git a/lisp/treesit.el b/lisp/treesit.el
index da8226f7d8a..fab2ddd88e6 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -1,6 +1,6 @@
 ;;; treesit.el --- tree-sitter utilities -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: 付禹安 (Yuan Fu) <casouri@gmail.com>
 ;; Keywords: treesit, tree-sitter, languages
@@ -595,8 +595,8 @@ that encompasses the region between START and END."
                    (unless (and (consp range-offset)
                                 (numberp (car range-offset))
                                 (numberp (cdr range-offset)))
-                    (signal 'treesit-error (list "Value of :offset option 
should be a pair of numbers" range-offset)))
-                  (setq offset range-offset)))
+                     (signal 'treesit-error (list "Value of :offset option 
should be a pair of numbers" range-offset)))
+                   (setq offset range-offset)))
         (query (if (functionp query)
                    (push (list query nil nil) result)
                  (when (null embed)
@@ -606,7 +606,7 @@ that encompasses the region between START and END."
                  (push (list (treesit-query-compile host query)
                              embed local offset)
                        result))
-               (setq host nil embed nil offset nil))))
+               (setq host nil embed nil offset nil local nil))))
     (nreverse result)))
 
 (defun treesit--merge-ranges (old-ranges new-ranges start end)
@@ -655,42 +655,52 @@ those inside are kept."
            if (<= start (car range) (cdr range) end)
            collect range))
 
-(defun treesit-local-parsers-at (&optional pos language)
+(defun treesit-local-parsers-at (&optional pos language with-host)
   "Return all the local parsers at POS.
 
 POS defaults to point.
 Local parsers are those which only parse a limited region marked
 by an overlay with non-nil `treesit-parser' property.
-If LANGUAGE is non-nil, only return parsers for LANGUAGE."
+If LANGUAGE is non-nil, only return parsers for LANGUAGE.
+
+If WITH-HOST is non-nil, return a list of (PARSER . HOST-PARSER)
+instead.  HOST-PARSER is the host parser which created the local
+PARSER."
   (let ((res nil))
     (dolist (ov (overlays-at (or pos (point))))
-      (when-let ((parser (overlay-get ov 'treesit-parser)))
+      (when-let ((parser (overlay-get ov 'treesit-parser))
+                 (host-parser (overlay-get ov 'treesit-host-parser)))
         (when (or (null language)
                   (eq (treesit-parser-language parser)
                       language))
-          (push parser res))))
+          (push (if with-host (cons parser host-parser) parser) res))))
     (nreverse res)))
 
-(defun treesit-local-parsers-on (&optional beg end language)
+(defun treesit-local-parsers-on (&optional beg end language with-host)
   "Return all the local parsers between BEG END.
 
 BEG and END default to the beginning and end of the buffer's
 accessible portion.
 Local parsers are those which have an `embedded' tag, and only parse
 a limited region marked by an overlay with a non-nil `treesit-parser'
-property.  If LANGUAGE is non-nil, only return parsers for LANGUAGE."
+property.  If LANGUAGE is non-nil, only return parsers for LANGUAGE.
+
+If WITH-HOST is non-nil, return a list of (PARSER . HOST-PARSER)
+instead.  HOST-PARSER is the host parser which created the local
+PARSER."
   (let ((res nil))
     (dolist (ov (overlays-in (or beg (point-min)) (or end (point-max))))
-      (when-let ((parser (overlay-get ov 'treesit-parser)))
+      (when-let ((parser (overlay-get ov 'treesit-parser))
+                 (host-parser (overlay-get ov 'treesit-host-parser)))
         (when (or (null language)
                   (eq (treesit-parser-language parser)
                       language))
-          (push parser res))))
+          (push (if with-host (cons parser host-parser) parser) res))))
     (nreverse res)))
 
 (defun treesit--update-ranges-local
     (query embedded-lang &optional beg end)
-  "Update range for local parsers betwwen BEG and END.
+  "Update range for local parsers between BEG and END.
 Use QUERY to get the ranges, and make sure each range has a local
 parser for EMBEDDED-LANG."
   ;; Clean up.
@@ -701,7 +711,8 @@ parser for EMBEDDED-LANG."
         (treesit-parser-delete parser))))
   ;; Update range.
   (let* ((host-lang (treesit-query-language query))
-         (ranges (treesit-query-range host-lang query beg end)))
+         (host-parser (treesit-parser-create host-lang))
+         (ranges (treesit-query-range host-parser query beg end)))
     (pcase-dolist (`(,beg . ,end) ranges)
       (let ((has-parser nil))
         (dolist (ov (overlays-in beg end))
@@ -719,6 +730,7 @@ parser for EMBEDDED-LANG."
                                   embedded-lang nil t 'embedded))
                 (ov (make-overlay beg end nil nil t)))
             (overlay-put ov 'treesit-parser embedded-parser)
+            (overlay-put ov 'treesit-host-parser host-parser)
             (treesit-parser-set-included-ranges
              embedded-parser `((,beg . ,end)))))))))
 
@@ -1330,6 +1342,72 @@ parser notifying of the change."
       (with-silent-modifications
         (put-text-property (car range) (cdr range) 'fontified nil)))))
 
+(defvar-local treesit--syntax-propertize-start nil
+  "If non-nil, next `syntax-propertize' should start at this position.
+
+When tree-sitter parser reparses, it calls
+`treesit--syntax-propertize-notifier' with the affected region,
+and that function sets this variable to the start of the affected
+region.")
+
+(defun treesit--syntax-propertize-notifier (ranges parser)
+  "Sets `treesit--syntax-propertize-start' to the smallest start.
+Specifically, the smallest start position among all the ranges in
+RANGES for PARSER."
+  (with-current-buffer (treesit-parser-buffer parser)
+    (when-let* ((range-starts (mapcar #'car ranges))
+                (min-range-start
+                 (seq-reduce
+                  #'min (cdr range-starts) (car range-starts))))
+      (if (null treesit--syntax-propertize-start)
+          (setq treesit--syntax-propertize-start min-range-start)
+        (setq treesit--syntax-propertize-start
+              (min treesit--syntax-propertize-start min-range-start))))))
+
+(defvar-local treesit--pre-redisplay-tick nil
+  "The last `buffer-chars-modified-tick' that we've processed.
+Because `pre-redisplay-functions' could be called multiple times
+during a single command loop, we use this variable to debounce
+calls to `treesit--pre-redisplay'.")
+
+(defun treesit--pre-redisplay (&rest _)
+  "Force reparse and consequently run all notifiers.
+
+One of the notifiers is `treesit--font-lock-notifier', which will
+mark the region whose syntax has changed to \"need to refontify\".
+
+For example, when the user types the final slash of a C block
+comment /* xxx */, not only do we need to fontify the slash, but
+also the whole block comment, which previously wasn't fontified
+as comment due to incomplete parse tree."
+  (unless (eq treesit--pre-redisplay-tick (buffer-chars-modified-tick))
+    ;; `treesit-update-ranges' will force the host language's parser to
+    ;; reparse and set correct ranges for embedded parsers.  Then
+    ;; `treesit-parser-root-node' will force those parsers to reparse.
+    (treesit-update-ranges)
+    ;; Force repase on _all_ the parsers might not be necessary, but
+    ;; this is probably the most robust way.
+    (dolist (parser (treesit-parser-list))
+      (treesit-parser-root-node parser))
+    (setq treesit--pre-redisplay-tick (buffer-chars-modified-tick))))
+
+(defun treesit--pre-syntax-ppss (start end)
+  "Force reparse and consequently run all notifiers.
+
+Similar to font-lock, we want to update the `syntax' text
+property before `syntax-ppss' starts working on the text.  We
+also want to extend the to-be-propertized region to include the
+whole region affected by the last reparse.
+
+START and END mark the current to-be-propertized region."
+  (treesit--pre-redisplay)
+  (let ((new-start treesit--syntax-propertize-start))
+    (if (and new-start (< new-start start))
+        (progn
+          (setq treesit--syntax-propertize-start nil)
+          (cons (max new-start (point-min)) end))
+      nil)))
+
 ;;; Indent
 
 (define-error 'treesit-indent-error
@@ -1599,7 +1677,7 @@ no-node
 
 comment-end
 
-    Matches if text after point matches `treesit-comment-end'.
+    Matches if text after point matches `comment-end-skip'.
 
 catch-all
 
@@ -1734,11 +1812,17 @@ Return (ANCHOR . OFFSET).  This function is used by
                 (forward-line 0)
                 (skip-chars-forward " \t")
                 (point)))
-         (local-parsers (treesit-local-parsers-at bol))
+         (local-parsers (treesit-local-parsers-at bol nil t))
          (smallest-node
-          (cond ((null (treesit-parser-list)) nil)
-                (local-parsers (treesit-node-at
-                                bol (car local-parsers)))
+          (cond ((car local-parsers)
+                 (let ((local-parser (caar local-parsers))
+                       (host-parser (cdar local-parsers)))
+                   (if (eq (treesit-node-start
+                            (treesit-parser-root-node local-parser))
+                           bol)
+                       (treesit-node-at bol host-parser)
+                     (treesit-node-at bol local-parser))))
+                ((null (treesit-parser-list)) nil)
                 ((eq 1 (length (treesit-parser-list nil nil t)))
                  (treesit-node-at bol))
                 ((treesit-language-at bol)
@@ -2358,7 +2442,7 @@ the current line if the beginning of the defun is 
indented."
          (forward-line 1))
         ;; Moving backward, but there are some whitespace (and only
         ;; whitespace) between point and BOL: go back to BOL.
-        ((looking-back (rx (+ (or " " "\t")))
+        ((looking-back (rx bol (+ (or " " "\t")))
                        (line-beginning-position))
          (beginning-of-line))))
 
@@ -2852,7 +2936,14 @@ before calling this function."
     (treesit-font-lock-recompute-features)
     (dolist (parser (treesit-parser-list))
       (treesit-parser-add-notifier
-       parser #'treesit--font-lock-notifier)))
+       parser #'treesit--font-lock-notifier))
+    (add-hook 'pre-redisplay-functions #'treesit--pre-redisplay 0 t))
+  ;; Syntax
+  (dolist (parser (treesit-parser-list))
+    (treesit-parser-add-notifier
+     parser #'treesit--syntax-propertize-notifier))
+  (add-hook 'syntax-propertize-extend-region-functions
+            #'treesit--pre-syntax-ppss 0 t)
   ;; Indent.
   (when treesit-simple-indent-rules
     (setq-local treesit-simple-indent-rules
@@ -3344,7 +3435,8 @@ The value should be an alist where each element has the 
form
     (LANG . (URL REVISION SOURCE-DIR CC C++))
 
 Only LANG and URL are mandatory.  LANG is the language symbol.
-URL is the Git repository URL for the grammar.
+URL is the URL of the grammar's Git repository or a directory
+where the repository has been cloned.
 
 REVISION is the Git tag or branch of the desired version,
 defaulting to the latest default branch.
@@ -3478,6 +3570,26 @@ content as signal data, and erase buffer afterwards."
                                  (buffer-string)))
     (erase-buffer)))
 
+(defun treesit--git-checkout-branch (repo-dir revision)
+  "Checkout REVISION in a repo located in REPO-DIR."
+  (treesit--call-process-signal
+   "git" nil t nil "-C" repo-dir "checkout" revision))
+
+(defun treesit--git-clone-repo (url revision workdir)
+  "Clone repo pointed by URL at commit REVISION to WORKDIR.
+
+REVISION may be nil, in which case the cloned repo will be at its
+default branch."
+  (message "Cloning repository")
+  ;; git clone xxx --depth 1 --quiet [-b yyy] workdir
+  (if revision
+      (treesit--call-process-signal
+       "git" nil t nil "clone" url "--depth" "1" "--quiet"
+       "-b" revision workdir)
+    (treesit--call-process-signal
+     "git" nil t nil "clone" url "--depth" "1" "--quiet"
+     workdir)))
+
 (defun treesit--install-language-grammar-1
     (out-dir lang url &optional revision source-dir cc c++)
   "Install and compile a tree-sitter language grammar library.
@@ -3491,8 +3603,12 @@ For LANG, URL, REVISION, SOURCE-DIR, GRAMMAR-DIR, CC, 
C++, see
 `treesit-language-source-alist'.  If anything goes wrong, this
 function signals an error."
   (let* ((lang (symbol-name lang))
+         (maybe-repo-dir (expand-file-name url))
+         (url-is-dir (file-accessible-directory-p maybe-repo-dir))
          (default-directory (make-temp-file "treesit-workdir" t))
-         (workdir (expand-file-name "repo"))
+         (workdir (if url-is-dir
+                      maybe-repo-dir
+                    (expand-file-name "repo")))
          (source-dir (expand-file-name (or source-dir "src") workdir))
          (cc (or cc (seq-find #'executable-find '("cc" "gcc" "c99"))
                  ;; If no C compiler found, just use cc and let
@@ -3507,15 +3623,10 @@ function signals an error."
          (lib-name (concat "libtree-sitter-" lang soext)))
     (unwind-protect
         (with-temp-buffer
-          (message "Cloning repository")
-          ;; git clone xxx --depth 1 --quiet [-b yyy] workdir
-          (if revision
-              (treesit--call-process-signal
-               "git" nil t nil "clone" url "--depth" "1" "--quiet"
-               "-b" revision workdir)
-            (treesit--call-process-signal
-             "git" nil t nil "clone" url "--depth" "1" "--quiet"
-             workdir))
+          (if url-is-dir
+              (when revision
+                (treesit--git-checkout-branch workdir revision))
+            (treesit--git-clone-repo url revision workdir))
           ;; We need to go into the source directory because some
           ;; header files use relative path (#include "../xxx").
           ;; cd "${sourcedir}"
@@ -3562,7 +3673,9 @@ function signals an error."
             ;; Ignore errors, in case the old version is still used.
             (ignore-errors (delete-file old-fname)))
           (message "Library installed to %s/%s" out-dir lib-name))
-      (when (file-exists-p workdir)
+      ;; Remove workdir if it's not a repo owned by user and we
+      ;; managed to create it in the first place.
+      (when (and (not url-is-dir) (file-exists-p workdir))
         (delete-directory workdir t)))))
 
 ;;; Etc
diff --git a/lisp/tutorial.el b/lisp/tutorial.el
index eb494be8d4d..d754db238de 100644
--- a/lisp/tutorial.el
+++ b/lisp/tutorial.el
@@ -1,6 +1,6 @@
 ;;; tutorial.el --- tutorial for Emacs  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: help, internal
diff --git a/lisp/type-break.el b/lisp/type-break.el
index d3371d66863..182f4656b16 100644
--- a/lisp/type-break.el
+++ b/lisp/type-break.el
@@ -1,6 +1,6 @@
 ;;; type-break.el --- encourage rests from typing at appropriate intervals  
-*- lexical-binding: t -*-
 
-;; Copyright (C) 1994-1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1994-1995, 1997, 2000-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Noah Friedman <friedman@splode.com>
diff --git a/lisp/uniquify.el b/lisp/uniquify.el
index 7119ae7eac3..7085089dbe3 100644
--- a/lisp/uniquify.el
+++ b/lisp/uniquify.el
@@ -1,6 +1,6 @@
 ;;; uniquify.el --- unique buffer names dependent on file name -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1989, 1995-1997, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1989, 1995-1997, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Dick King <king@reasoning.com>
diff --git a/lisp/url/ChangeLog.1 b/lisp/url/ChangeLog.1
index 4cd0a151446..37feda0e026 100644
--- a/lisp/url/ChangeLog.1
+++ b/lisp/url/ChangeLog.1
@@ -3068,7 +3068,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1999, 2001-2002, 2004-2023 Free Software Foundation,
+  Copyright (C) 1999, 2001-2002, 2004-2024 Free Software Foundation,
   Inc.
 
   This file is part of GNU Emacs.
diff --git a/lisp/url/url-auth.el b/lisp/url/url-auth.el
index 6848c0c73a7..8f4df780a54 100644
--- a/lisp/url/url-auth.el
+++ b/lisp/url/url-auth.el
@@ -1,6 +1,6 @@
 ;;; url-auth.el --- Uniform Resource Locator authorization modules -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes, hypermedia
 
diff --git a/lisp/url/url-cache.el b/lisp/url/url-cache.el
index 51c52d701e9..0d27321cc47 100644
--- a/lisp/url/url-cache.el
+++ b/lisp/url/url-cache.el
@@ -1,6 +1,6 @@
 ;;; url-cache.el --- Uniform Resource Locator retrieval tool  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes, hypermedia
 
diff --git a/lisp/url/url-cid.el b/lisp/url/url-cid.el
index a716b37abbe..17a0318e652 100644
--- a/lisp/url/url-cid.el
+++ b/lisp/url/url-cid.el
@@ -1,6 +1,6 @@
 ;;; url-cid.el --- Content-ID URL loader  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1998-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes
 
diff --git a/lisp/url/url-cookie.el b/lisp/url/url-cookie.el
index 22b36980c9e..4c1ea2e185b 100644
--- a/lisp/url/url-cookie.el
+++ b/lisp/url/url-cookie.el
@@ -1,6 +1,6 @@
 ;;; url-cookie.el --- URL cookie support  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes, hypermedia
 
diff --git a/lisp/url/url-dav.el b/lisp/url/url-dav.el
index 7e7cd863f46..632b2dac9d0 100644
--- a/lisp/url/url-dav.el
+++ b/lisp/url/url-dav.el
@@ -1,6 +1,6 @@
 ;;; url-dav.el --- WebDAV support  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Bill Perry <wmperry@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/url/url-domsuf.el b/lisp/url/url-domsuf.el
index 671885e418f..b720f73efd7 100644
--- a/lisp/url/url-domsuf.el
+++ b/lisp/url/url-domsuf.el
@@ -1,6 +1,6 @@
 ;;; url-domsuf.el --- Say what domain names can have cookies set.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 
diff --git a/lisp/url/url-expand.el b/lisp/url/url-expand.el
index b3f29a7063d..39d4d722cc8 100644
--- a/lisp/url/url-expand.el
+++ b/lisp/url/url-expand.el
@@ -1,6 +1,6 @@
 ;;; url-expand.el --- expand-file-name for URLs -*- lexical-binding: t -*-
 
-;; Copyright (C) 1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes
 
diff --git a/lisp/url/url-file.el b/lisp/url/url-file.el
index f63fce3e000..5277e99a158 100644
--- a/lisp/url/url-file.el
+++ b/lisp/url/url-file.el
@@ -1,6 +1,6 @@
 ;;; url-file.el --- File retrieval code  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes
 
diff --git a/lisp/url/url-ftp.el b/lisp/url/url-ftp.el
index c3ea4dce714..439de574382 100644
--- a/lisp/url/url-ftp.el
+++ b/lisp/url/url-ftp.el
@@ -1,6 +1,6 @@
 ;;; url-ftp.el --- FTP wrapper  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes
 
diff --git a/lisp/url/url-future.el b/lisp/url/url-future.el
index 9b528835a7b..790da8b5d6d 100644
--- a/lisp/url/url-future.el
+++ b/lisp/url/url-future.el
@@ -1,6 +1,6 @@
 ;;; url-future.el --- general futures facility for url.el -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Teodor Zlatanov <tzz@lifelogs.com>
 ;; Keywords: data
diff --git a/lisp/url/url-gw.el b/lisp/url/url-gw.el
index 568ce8679f5..62be70827fa 100644
--- a/lisp/url/url-gw.el
+++ b/lisp/url/url-gw.el
@@ -1,6 +1,6 @@
 ;;; url-gw.el --- Gateway munging for URL loading  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Bill Perry <wmperry@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/url/url-handlers.el b/lisp/url/url-handlers.el
index cb4c811185c..9edc7865a74 100644
--- a/lisp/url/url-handlers.el
+++ b/lisp/url/url-handlers.el
@@ -1,6 +1,6 @@
 ;;; url-handlers.el --- file-name-handler stuff for URL loading  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes, hypermedia
 
diff --git a/lisp/url/url-history.el b/lisp/url/url-history.el
index 0264f16366d..e4f353afd02 100644
--- a/lisp/url/url-history.el
+++ b/lisp/url/url-history.el
@@ -1,6 +1,6 @@
 ;;; url-history.el --- Global history tracking for URL package  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes, hypermedia
 
diff --git a/lisp/url/url-http.el b/lisp/url/url-http.el
index ada6341ee73..d6a1d0eade8 100644
--- a/lisp/url/url-http.el
+++ b/lisp/url/url-http.el
@@ -1,6 +1,6 @@
 ;;; url-http.el --- HTTP retrieval routines  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999, 2001, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2001, 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Bill Perry <wmperry@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
@@ -358,10 +358,6 @@ Use `url-http-referer' as the Referer-header (subject to 
`url-privacy-level')."
                   (url-port url-http-target-url))
                (format "Host: %s\r\n"
                        (url-http--encode-string (puny-encode-domain host))))
-             ;; Who its from
-             (if url-personal-mail-address
-                 (concat
-                  "From: " url-personal-mail-address "\r\n"))
              ;; Encodings we understand
              (if (or url-mime-encoding-string
                     ;; MS-Windows loads zlib dynamically, so recheck
diff --git a/lisp/url/url-imap.el b/lisp/url/url-imap.el
index 6fa34e6c791..abfd21bc375 100644
--- a/lisp/url/url-imap.el
+++ b/lisp/url/url-imap.el
@@ -1,6 +1,6 @@
 ;;; url-imap.el --- IMAP retrieval routines  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Simon Josefsson <jas@pdc.kth.se>
 ;; Keywords: comm, data, processes
diff --git a/lisp/url/url-irc.el b/lisp/url/url-irc.el
index e11b4a6a58e..e6499bce31e 100644
--- a/lisp/url/url-irc.el
+++ b/lisp/url/url-irc.el
@@ -1,6 +1,6 @@
 ;;; url-irc.el --- IRC URL interface  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes
 
diff --git a/lisp/url/url-ldap.el b/lisp/url/url-ldap.el
index f06ba1cd8de..1bdd5099637 100644
--- a/lisp/url/url-ldap.el
+++ b/lisp/url/url-ldap.el
@@ -1,6 +1,6 @@
 ;;; url-ldap.el --- LDAP Uniform Resource Locator retrieval code  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1998-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes
 
diff --git a/lisp/url/url-mailto.el b/lisp/url/url-mailto.el
index 04d6d9681ff..c2d347a1646 100644
--- a/lisp/url/url-mailto.el
+++ b/lisp/url/url-mailto.el
@@ -1,6 +1,6 @@
 ;;; url-mailto.el --- Mail Uniform Resource Locator retrieval code  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes
 
diff --git a/lisp/url/url-methods.el b/lisp/url/url-methods.el
index 9643e992044..5681a4e3785 100644
--- a/lisp/url/url-methods.el
+++ b/lisp/url/url-methods.el
@@ -1,6 +1,6 @@
 ;;; url-methods.el --- Load URL schemes as needed  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes, hypermedia
 
diff --git a/lisp/url/url-misc.el b/lisp/url/url-misc.el
index 96f5c46ea00..23dd5f2d743 100644
--- a/lisp/url/url-misc.el
+++ b/lisp/url/url-misc.el
@@ -1,6 +1,6 @@
 ;;; url-misc.el --- Misc Uniform Resource Locator retrieval code  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-1999, 2002, 2004-2023 Free Software Foundation,
+;; Copyright (C) 1996-1999, 2002, 2004-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Keywords: comm, data, processes
diff --git a/lisp/url/url-news.el b/lisp/url/url-news.el
index 592f34213ee..9271a2d7a63 100644
--- a/lisp/url/url-news.el
+++ b/lisp/url/url-news.el
@@ -1,6 +1,6 @@
 ;;; url-news.el --- News Uniform Resource Locator retrieval code  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes
 
diff --git a/lisp/url/url-nfs.el b/lisp/url/url-nfs.el
index 76f9b04076c..d00ec6d27f4 100644
--- a/lisp/url/url-nfs.el
+++ b/lisp/url/url-nfs.el
@@ -1,6 +1,6 @@
 ;;; url-nfs.el --- NFS URL interface  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes
 
diff --git a/lisp/url/url-parse.el b/lisp/url/url-parse.el
index cd0e155e954..e7b6541342a 100644
--- a/lisp/url/url-parse.el
+++ b/lisp/url/url-parse.el
@@ -1,6 +1,6 @@
 ;;; url-parse.el --- Uniform Resource Locator parser -*- lexical-binding: t -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes
 
diff --git a/lisp/url/url-privacy.el b/lisp/url/url-privacy.el
index 2be77b33035..aa710588f49 100644
--- a/lisp/url/url-privacy.el
+++ b/lisp/url/url-privacy.el
@@ -1,6 +1,6 @@
 ;;; url-privacy.el --- Global history tracking for URL package  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes, hypermedia
 
@@ -59,16 +59,6 @@
            ('tty "TTY")
            (_ nil)))))
 
-  (setq url-personal-mail-address (or url-personal-mail-address
-                                     user-mail-address
-                                     (format "%s@%s"  (user-real-login-name)
-                                             (system-name))))
-
-  (if (or (memq url-privacy-level '(paranoid high))
-         (and (listp url-privacy-level)
-              (memq 'email url-privacy-level)))
-      (setq url-personal-mail-address nil))
-
   (setq url-os-type
        (cond
         ((or (eq url-privacy-level 'paranoid)
diff --git a/lisp/url/url-proxy.el b/lisp/url/url-proxy.el
index 0c330069789..15f117f0a34 100644
--- a/lisp/url/url-proxy.el
+++ b/lisp/url/url-proxy.el
@@ -1,6 +1,6 @@
 ;;; url-proxy.el --- Proxy server support  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2004-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes, hypermedia
 
diff --git a/lisp/url/url-queue.el b/lisp/url/url-queue.el
index f89f38bf965..79340059bca 100644
--- a/lisp/url/url-queue.el
+++ b/lisp/url/url-queue.el
@@ -1,6 +1,6 @@
 ;;; url-queue.el --- Fetching web pages in parallel   -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: comm
diff --git a/lisp/url/url-tramp.el b/lisp/url/url-tramp.el
index 172e0de6ab0..a56e707457c 100644
--- a/lisp/url/url-tramp.el
+++ b/lisp/url/url-tramp.el
@@ -1,6 +1,6 @@
 ;;; url-tramp.el --- file-name-handler magic invoking Tramp for some protocols 
 -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, data, processes, hypermedia
diff --git a/lisp/url/url-util.el b/lisp/url/url-util.el
index a7cb8364b5f..5f45b98c7a5 100644
--- a/lisp/url/url-util.el
+++ b/lisp/url/url-util.el
@@ -1,6 +1,6 @@
 ;;; url-util.el --- Miscellaneous helper routines for URL library -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Bill Perry <wmperry@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
@@ -335,7 +335,7 @@ appropriate coding-system; see `decode-coding-string'."
              str (substring str (match-end 0)))))
     (concat tmp str)))
 
-(defconst url-unreserved-chars
+(defvar url-unreserved-chars
   '(?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y 
?z
     ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y 
?Z
     ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9
diff --git a/lisp/url/url-vars.el b/lisp/url/url-vars.el
index 630de7f4e43..09b3019a553 100644
--- a/lisp/url/url-vars.el
+++ b/lisp/url/url-vars.el
@@ -1,6 +1,6 @@
 ;;; url-vars.el --- Variables for Uniform Resource Locator tool  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes, hypermedia
 
@@ -90,6 +90,7 @@ This is what is sent to HTTP servers as the FROM field in an 
HTTP
 request."
   :type '(choice (const :tag "Unspecified" nil) string)
   :group 'url)
+(make-obsolete-variable 'url-personal-mail-address nil "30.1")
 
 (defcustom url-directory-index-file "index.html"
   "The filename to look for when indexing a directory.
@@ -113,18 +114,22 @@ paranoid -- don't send anything
 
 If a list, this should be a list of symbols of what NOT to send.
 Valid symbols are:
-email    -- the email address
+email    -- the email address (in Emacs 29 or older)
 os       -- the operating system info
 emacs    -- the version of Emacs
 lastloc  -- the last location (see also `url-lastloc-privacy-level')
 agent    -- do not send the User-Agent string
 cookies  -- never accept HTTP cookies
 
+Emacs 30 and newer never includes the email address in the
+User-Agent string.  If you expect to use older versions of Emacs,
+it is recommended to always customize this list to include `email'.
+
 Samples:
 
  (setq url-privacy-level \\='high)
  (setq url-privacy-level \\='(email lastloc))    ;; equivalent to \\='high
- (setq url-privacy-level \\='(os))
+ (setq url-privacy-level \\='(email lastloc os emacs))
 
 ::NOTE::
 This variable controls several other variables and is _NOT_ automatically
diff --git a/lisp/url/url.el b/lisp/url/url.el
index 09e555a7b15..dea251b453b 100644
--- a/lisp/url/url.el
+++ b/lisp/url/url.el
@@ -1,6 +1,6 @@
 ;;; url.el --- Uniform Resource Locator retrieval tool  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1996-1999, 2001, 2004-2023 Free Software Foundation,
+;; Copyright (C) 1996-1999, 2001, 2004-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Bill Perry <wmperry@gnu.org>
diff --git a/lisp/use-package/use-package-bind-key.el 
b/lisp/use-package/use-package-bind-key.el
index 47eb066eba0..18c3f29cf34 100644
--- a/lisp/use-package/use-package-bind-key.el
+++ b/lisp/use-package/use-package-bind-key.el
@@ -1,6 +1,6 @@
 ;;; use-package-bind-key.el --- Support for the :bind/:bind-keymap keywords  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@newartisans.com>
 ;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/use-package/use-package-core.el 
b/lisp/use-package/use-package-core.el
index 34c45b7aec3..d9343e14839 100644
--- a/lisp/use-package/use-package-core.el
+++ b/lisp/use-package/use-package-core.el
@@ -1,6 +1,6 @@
 ;;; use-package-core.el --- A configuration macro for simplifying your .emacs  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@newartisans.com>
 ;; Maintainer: John Wiegley <johnw@newartisans.com>
@@ -1619,7 +1619,7 @@ ARG is the normalized input to the `:vc' keyword, as 
returned by
 the `use-package-normalize/:vc' function.
 
 REST is a plist of other (following) keywords and their
-arguments, each having already been normalised by the respective
+arguments, each having already been normalized by the respective
 function.
 
 STATE is a plist of any state that keywords processed before
@@ -1690,7 +1690,7 @@ node `(use-package) Creating an extension'."
       (`(,(pred symbolp) . ,(or (pred plistp)    ; plist/version string + name
                                 (pred stringp)))
        (use-package-normalize--vc-arg arg))
-      (_ (use-package-error "Unrecognised argument to :vc.\
+      (_ (use-package-error "Unrecognized argument to :vc.\
  The keyword wants an argument of nil, t, a name of a package,\
  or a cons-cell as accepted by `package-vc-selected-packages', where \
  the accepted plist is augmented by a `:rev' keyword.")))))
diff --git a/lisp/use-package/use-package-delight.el 
b/lisp/use-package/use-package-delight.el
index 4f571cd3990..c458d263cf0 100644
--- a/lisp/use-package/use-package-delight.el
+++ b/lisp/use-package/use-package-delight.el
@@ -1,6 +1,6 @@
 ;;; use-package-delight.el --- Support for the :delight keyword  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@newartisans.com>
 ;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/use-package/use-package-diminish.el 
b/lisp/use-package/use-package-diminish.el
index f683694dbd8..79421a0e273 100644
--- a/lisp/use-package/use-package-diminish.el
+++ b/lisp/use-package/use-package-diminish.el
@@ -1,6 +1,6 @@
 ;;; use-package-diminish.el --- Support for the :diminish keyword  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@newartisans.com>
 ;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/use-package/use-package-ensure-system-package.el 
b/lisp/use-package/use-package-ensure-system-package.el
index ef4afac1a0b..6c7f8c0a1ea 100644
--- a/lisp/use-package/use-package-ensure-system-package.el
+++ b/lisp/use-package/use-package-ensure-system-package.el
@@ -1,11 +1,10 @@
 ;;; use-package-ensure-system-package.el --- auto install system packages  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Justin Talbott <justin@waymondo.com>
 ;; Keywords: convenience, tools, extensions
 ;; URL: https://github.com/waymondo/use-package-ensure-system-package
-;; Version: 0.2
 ;; Package-Requires: ((use-package "2.1") (system-packages "1.0.4"))
 ;; Filename: use-package-ensure-system-package.el
 
diff --git a/lisp/use-package/use-package-ensure.el 
b/lisp/use-package/use-package-ensure.el
index 395a0bbda00..5f75b6b59ea 100644
--- a/lisp/use-package/use-package-ensure.el
+++ b/lisp/use-package/use-package-ensure.el
@@ -1,6 +1,6 @@
 ;;; use-package-ensure.el --- Support for the :ensure and :pin keywords  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@newartisans.com>
 ;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/use-package/use-package-jump.el 
b/lisp/use-package/use-package-jump.el
index 4fc5c3f0a8e..604b2600b3d 100644
--- a/lisp/use-package/use-package-jump.el
+++ b/lisp/use-package/use-package-jump.el
@@ -1,6 +1,6 @@
 ;;; use-package-jump.el --- Attempt to jump to a use-package declaration  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@newartisans.com>
 ;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/use-package/use-package-lint.el 
b/lisp/use-package/use-package-lint.el
index 9239d01148a..15c58809478 100644
--- a/lisp/use-package/use-package-lint.el
+++ b/lisp/use-package/use-package-lint.el
@@ -1,6 +1,6 @@
 ;;; use-package-lint.el --- Attempt to find errors in use-package declarations 
 -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@newartisans.com>
 ;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/use-package/use-package.el b/lisp/use-package/use-package.el
index f5e6a551bb3..fc5c994a5f9 100644
--- a/lisp/use-package/use-package.el
+++ b/lisp/use-package/use-package.el
@@ -1,6 +1,6 @@
 ;;; use-package.el --- A configuration macro for simplifying your .emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@newartisans.com>
 ;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/userlock.el b/lisp/userlock.el
index 91d5b7308dd..db94bb214e6 100644
--- a/lisp/userlock.el
+++ b/lisp/userlock.el
@@ -1,6 +1,6 @@
 ;;; userlock.el --- handle file access contention between multiple users  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Richard King
 ;; (according to authors.el)
diff --git a/lisp/vc/add-log.el b/lisp/vc/add-log.el
index 22ae6db72ab..d4751f66723 100644
--- a/lisp/vc/add-log.el
+++ b/lisp/vc/add-log.el
@@ -1,6 +1,6 @@
 ;;; add-log.el --- change log maintenance commands for Emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1985-1986, 1988, 1993-1994, 1997-1998, 2000-2023 Free
+;; Copyright (C) 1985-1986, 1988, 1993-1994, 1997-1998, 2000-2024 Free
 ;; Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/vc/compare-w.el b/lisp/vc/compare-w.el
index 728198eb361..4aca2707115 100644
--- a/lisp/vc/compare-w.el
+++ b/lisp/vc/compare-w.el
@@ -1,6 +1,6 @@
 ;;; compare-w.el --- compare text between windows for Emacs  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1986-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: convenience files vc
diff --git a/lisp/vc/cvs-status.el b/lisp/vc/cvs-status.el
index 7532a059d3b..c9ad1d13d24 100644
--- a/lisp/vc/cvs-status.el
+++ b/lisp/vc/cvs-status.el
@@ -1,6 +1,6 @@
 ;;; cvs-status.el --- major mode for browsing `cvs status' output -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: pcl-cvs cvs status tree vc tools
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index 24a925eda73..83d580d98dd 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -1,6 +1,6 @@
 ;;; diff-mode.el --- a mode for viewing/editing context diffs -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: convenience patch diff vc
@@ -3014,7 +3014,7 @@ hunk text is not found in the source file."
       (goto-char (point-min))
       (while (progn (diff-file-next) (not (eobp)))
         (push (diff-find-file-name nil t) files)))
-    (list backend (nreverse files) nil nil 'patch)))
+    (list backend (delete nil (nreverse files)) nil nil 'patch)))
 
 (defun diff--filter-substring (str)
   (when diff-font-lock-prettify
diff --git a/lisp/vc/diff.el b/lisp/vc/diff.el
index a411d98da31..a64fbc47853 100644
--- a/lisp/vc/diff.el
+++ b/lisp/vc/diff.el
@@ -1,6 +1,6 @@
 ;;; diff.el --- run `diff'  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1992, 1994, 1996, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1992, 1994, 1996, 2001-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Frank Bresz
diff --git a/lisp/vc/ediff-diff.el b/lisp/vc/ediff-diff.el
index 42c313b3f07..83bd7cde12f 100644
--- a/lisp/vc/ediff-diff.el
+++ b/lisp/vc/ediff-diff.el
@@ -1,6 +1,6 @@
 ;;; ediff-diff.el --- diff-related utilities  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: ediff
diff --git a/lisp/vc/ediff-help.el b/lisp/vc/ediff-help.el
index e8d4b3d4f5d..56e1ec80c5c 100644
--- a/lisp/vc/ediff-help.el
+++ b/lisp/vc/ediff-help.el
@@ -1,6 +1,6 @@
 ;;; ediff-help.el --- Code related to the contents of Ediff help buffers  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: ediff
diff --git a/lisp/vc/ediff-hook.el b/lisp/vc/ediff-hook.el
index 2f860d2ae73..3c78990d393 100644
--- a/lisp/vc/ediff-hook.el
+++ b/lisp/vc/ediff-hook.el
@@ -1,6 +1,6 @@
 ;;; ediff-hook.el --- setup for Ediff's menus and autoloads  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: ediff
diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el
index 28630792211..c5eda873b5e 100644
--- a/lisp/vc/ediff-init.el
+++ b/lisp/vc/ediff-init.el
@@ -1,6 +1,6 @@
 ;;; ediff-init.el --- Macros, variables, and defsubsts used by Ediff  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: ediff
diff --git a/lisp/vc/ediff-merg.el b/lisp/vc/ediff-merg.el
index b1cc9fd8c28..606c23cb8aa 100644
--- a/lisp/vc/ediff-merg.el
+++ b/lisp/vc/ediff-merg.el
@@ -1,6 +1,6 @@
 ;;; ediff-merg.el --- merging utilities  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: ediff
diff --git a/lisp/vc/ediff-mult.el b/lisp/vc/ediff-mult.el
index 3fda8c7f2f1..66d4935cd75 100644
--- a/lisp/vc/ediff-mult.el
+++ b/lisp/vc/ediff-mult.el
@@ -1,6 +1,6 @@
 ;;; ediff-mult.el --- support for multi-file/multi-buffer processing in Ediff  
-*- lexical-binding:t -*-
 
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: ediff
diff --git a/lisp/vc/ediff-ptch.el b/lisp/vc/ediff-ptch.el
index e62434360aa..f8d4c1c1c4b 100644
--- a/lisp/vc/ediff-ptch.el
+++ b/lisp/vc/ediff-ptch.el
@@ -1,6 +1,6 @@
 ;;; ediff-ptch.el --- Ediff's  patch support  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: ediff
diff --git a/lisp/vc/ediff-util.el b/lisp/vc/ediff-util.el
index be698370b97..597d8a5e643 100644
--- a/lisp/vc/ediff-util.el
+++ b/lisp/vc/ediff-util.el
@@ -1,6 +1,6 @@
 ;;; ediff-util.el --- the core commands and utilities of ediff  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: ediff
diff --git a/lisp/vc/ediff-vers.el b/lisp/vc/ediff-vers.el
index ed85764682f..52856b06399 100644
--- a/lisp/vc/ediff-vers.el
+++ b/lisp/vc/ediff-vers.el
@@ -1,6 +1,6 @@
 ;;; ediff-vers.el --- version control interface to Ediff  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1995-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1997, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: ediff
diff --git a/lisp/vc/ediff-wind.el b/lisp/vc/ediff-wind.el
index 7d7f849b09c..0e172e60277 100644
--- a/lisp/vc/ediff-wind.el
+++ b/lisp/vc/ediff-wind.el
@@ -1,6 +1,6 @@
 ;;; ediff-wind.el --- window manipulation utilities  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Package: ediff
diff --git a/lisp/vc/ediff.el b/lisp/vc/ediff.el
index 7e3b20d8939..30cc107d60b 100644
--- a/lisp/vc/ediff.el
+++ b/lisp/vc/ediff.el
@@ -1,6 +1,6 @@
 ;;; ediff.el --- a comprehensive visual interface to diff & patch  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
 ;; Created: February 2, 1994
diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el
index c77f4494c1a..1f766eea455 100644
--- a/lisp/vc/log-edit.el
+++ b/lisp/vc/log-edit.el
@@ -1,6 +1,6 @@
 ;;; log-edit.el --- Major mode for editing CVS commit messages -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: pcl-cvs cvs commit log vc
@@ -61,12 +61,12 @@
   "C-c C-d" #'log-edit-show-diff
   "C-c C-f" #'log-edit-show-files
   "C-c C-k" #'log-edit-kill-buffer
-  "C-a"     #'log-edit-beginning-of-line
   "M-n"     #'log-edit-next-comment
   "M-p"     #'log-edit-previous-comment
   "M-r"     #'log-edit-comment-search-backward
   "M-s"     #'log-edit-comment-search-forward
-  "C-c ?"   #'log-edit-mode-help)
+  "C-c ?"   #'log-edit-mode-help
+  "<remap> <move-beginning-of-line>" #'log-edit-beginning-of-line)
 
 (easy-menu-define log-edit-menu log-edit-mode-map
   "Menu used for `log-edit-mode'."
@@ -76,6 +76,8 @@
     "--"
     ["Insert ChangeLog" log-edit-insert-changelog
      :help "Insert a log message by looking at the ChangeLog"]
+    ["Generate ChangeLog" log-edit-generate-changelog-from-diff
+     :help "Generate a log message from the diff and insert it into this 
buffer"]
     ["Add to ChangeLog" log-edit-add-to-changelog
      :help "Insert this log message into the appropriate ChangeLog file"]
     "--"
@@ -93,6 +95,60 @@
     ["Search comment backward" log-edit-comment-search-backward
      :help "Search backwards through comment history for substring match of 
str"]))
 
+(defvar log-edit-tool-bar-map
+  (let ((map (make-sparse-keymap)))
+    (tool-bar-local-item-from-menu 'find-file "new" map
+                                   nil :label "New File"
+                                  :vert-only t)
+    (tool-bar-local-item-from-menu 'menu-find-file-existing "open" map
+                                   nil :label "Open" :vert-only t)
+    (tool-bar-local-item-from-menu 'dired "diropen" map nil :vert-only t)
+    (tool-bar-local-item-from-menu 'kill-this-buffer "close" map nil
+                                   :vert-only t)
+    (define-key-after map [separator-1] menu-bar-separator)
+    (tool-bar-local-item-from-menu 'log-edit-done "commit"
+                                   map log-edit-mode-map :vert-only t
+                                   :help
+                                   "Exit log buffer and commit the changes")
+    (define-key-after map [separator-2] menu-bar-separator)
+    (tool-bar-local-item-from-menu 'log-edit-insert-changelog
+                                   "load-changelog"
+                                   map log-edit-mode-map :vert-only t
+                                   :help
+                                   "Produce log message from ChangeLog file")
+    (tool-bar-local-item-from-menu 'log-edit-generate-changelog-from-diff
+                                   "gen-changelog"
+                                   map log-edit-mode-map :vert-only t
+                                   :help
+                                   "Generate log message skeleton from diffs")
+    (tool-bar-local-item-from-menu 'log-edit-add-to-changelog
+                                   "ins-changelog"
+                                   map log-edit-mode-map :vert-only t
+                                   :help
+                                   "Insert this log message into ChangeLog 
file")
+    (define-key-after map [separator-3] menu-bar-separator)
+    (tool-bar-local-item-from-menu 'log-edit-show-diff
+                                   "view-diff"
+                                   map log-edit-mode-map :vert-only t
+                                   :help
+                                   "View diffs for the files to be committed")
+    (tool-bar-local-item-from-menu 'log-edit-show-files
+                                   "info"
+                                   map log-edit-mode-map :vert-only t
+                                   :help
+                                   "View list of files to be committed")
+    (define-key-after map [separator-4] menu-bar-separator)
+    (tool-bar-local-item-from-menu 'undo "undo" map nil)
+    (define-key-after map [separator-5] menu-bar-separator)
+    (tool-bar-local-item-from-menu (lookup-key menu-bar-edit-menu [cut])
+                                   "cut" map nil)
+    (tool-bar-local-item-from-menu (lookup-key menu-bar-edit-menu [copy])
+                                   "copy" map nil)
+    (tool-bar-local-item-from-menu (lookup-key menu-bar-edit-menu [paste])
+                                   "paste" map nil)
+    map)
+  "Like the default `tool-bar-map', but with additions for Log-Edit mode.")
+
 (defcustom log-edit-confirm 'changed
   "If non-nil, `log-edit-done' will request confirmation.
 If `changed', only request confirmation if the list of files has
@@ -511,25 +567,90 @@ the \\[vc-prefix-map] prefix for VC commands, for 
example).
   (setq-local fill-paragraph-function #'log-edit-fill-entry)
   (make-local-variable 'log-edit-comment-ring-index)
   (add-hook 'kill-buffer-hook 'log-edit-remember-comment nil t)
-  (hack-dir-local-variables-non-file-buffer))
+  (hack-dir-local-variables-non-file-buffer)
+  ;; Replace the tool bar map with `log-edit-tool-bar-map'.
+  (setq-local tool-bar-map log-edit-tool-bar-map))
 
 (defun log-edit--insert-filled-defuns (func-names)
   "Insert FUNC-NAMES, following ChangeLog formatting."
   (if (not func-names)
       (insert ":")
+    ;; Insert a space unless this list of defun names is being
+    ;; inserted at the start of a line or after a space character.
     (unless (or (memq (char-before) '(?\n ?\s))
                 (> (current-column) fill-column))
       (insert " "))
-    (cl-loop for first-fun = t then nil
-             for def in func-names do
-             (when (> (+ (current-column) (string-width def)) fill-column)
-               (unless first-fun
-                 (insert ")"))
-               (insert "\n"))
-             (insert (if (memq (char-before) '(?\n ?\s))
-                         "(" ", ")
-                     def))
-    (insert "):")))
+    (let ((inside-paren-pair nil)
+          (first-line        t)
+          name)
+      ;; Now insert the functions names one by one, inserting newlines
+      ;; as appropriate.
+      (while func-names
+        (setq name (car func-names))
+        (setq func-names (cdr func-names))
+        ;; If inserting `name' after preexisting text in the first
+        ;; line would overflow the fill column, place it on its own
+        ;; line.
+        (if (and first-line
+                 (> (current-column) 0)
+                 (> (+ (current-column)
+                       (string-width name)
+                       ;; If this be the last name, the column must be
+                       ;; followed by an extra colon character.
+                       (if func-names 1 2))
+                    fill-column))
+            (progn
+              (insert "\n")
+              ;; Iterate over this function name again.
+              (setq func-names (cons name func-names)))
+          (if inside-paren-pair
+              ;; If `name' is not the first item in a list of defuns
+              ;; and inserting it would overflow the fill column,
+              ;; start a new list of defuns on the next line.
+              (if (> (+ (current-column)
+                        (string-width name)
+                        ;; If this be the last name, the column must
+                        ;; be followed by an extra colon character;
+                        ;; however, there are two separator characters
+                        ;; that will be deleted, so the number of
+                        ;; columns to add to this in the case of
+                        ;; `name' being final and in other cases are 0
+                        ;; and 1 respectively.
+                        (if func-names 0 1))
+                     fill-column)
+                  (progn
+                    (delete-char -2)
+                    (insert ")\n")
+                    (setq inside-paren-pair nil
+                          ;; Iterate over this function name again.
+                          func-names (cons name func-names)))
+                ;; Insert this defun name with a separator attached.
+                (insert name ", "))
+            ;; Otherwise, decide whether to start a list of defuns or
+            ;; to insert `name' on its own line.
+            (if (> (+ (current-column)
+                      (string-width name)
+                      (if func-names 1 2)) ; The column number of
+                                           ; line after inserting
+                                           ; `name'...
+                   fill-column)
+                ;; ...would leave insufficient space for any
+                ;; subsequent defun names so insert it on its own
+                ;; line.
+                (insert (if func-names
+                            (format "(%s)\n" name)
+                          (format "(%s):" name)))
+              ;; Insert a new defun list, unless `name' is the last
+              ;; function name.
+              (insert (if (not func-names)
+                          (format "(%s):" name)
+                        (setq inside-paren-pair t)
+                        (format "(%s, " name))))))
+        (setq first-line nil))
+      ;; Close any open list of defuns.
+      (when inside-paren-pair
+        (delete-char -2)
+        (insert "):")))))
 
 (defun log-edit-fill-entry (&optional justify)
   "Like \\[fill-paragraph], but for filling ChangeLog-formatted entries.
@@ -537,32 +658,70 @@ Consecutive function entries without prose (i.e., lines 
of the
 form \"(FUNCTION):\") will be combined into \"(FUNC1, FUNC2):\"
 according to `fill-column'."
   (save-excursion
-    (pcase-let ((`(,beg ,end) (log-edit-changelog-paragraph)))
+    (let* ((range (log-edit-changelog-paragraph))
+           (beg (car range))
+           (end (cadr range)))
       (if (= beg end)
           ;; Not a ChangeLog entry, fill as normal.
           nil
-        (cl-callf copy-marker end)
+        (setq end (copy-marker end))
         (goto-char beg)
-        (cl-loop
-         for defuns-beg =
-         (and (< beg end)
-              (re-search-forward
-               (concat "\\(?1:" change-log-unindented-file-names-re
-                       "\\)\\|^\\(?1:\\)[[:blank:]]*(")
-               end t)
-              (copy-marker (match-end 1)))
-         ;; Fill prose between log entries.
-         do (let ((fill-indent-according-to-mode t)
-                  (end (if defuns-beg (match-beginning 0) end))
-                  (beg (progn (goto-char beg) (line-beginning-position))))
-              (when (<= (line-end-position) end)
-                (fill-region beg end justify)))
-         while defuns-beg
-         for defuns = (progn (goto-char defuns-beg)
-                             (change-log-read-defuns end))
-         do (progn (delete-region defuns-beg (point))
-                   (log-edit--insert-filled-defuns defuns)
-                   (setq beg (point))))
+        (let* ((defuns-beg nil)
+               (defuns nil))
+          (while
+              (progn
+                ;; Match a regexp against the next ChangeLog entry.
+                ;; `defuns-beg' will be the end of the file name,
+                ;; which marks the beginning of the list of defuns.
+                (setq defuns-beg
+                      (and (< beg end)
+                           (re-search-forward
+                            (concat "\\(?1:"
+                                    change-log-unindented-file-names-re
+                                    "\\)\\|^\\(?1:\\)[[:blank:]]*(")
+                            end t)
+                           (copy-marker (match-end 1))))
+                ;; Fill the intervening prose between the end of the
+                ;; last match and the beginning of the current match.
+                (let ((fill-indent-according-to-mode t)
+                      (end (if defuns-beg
+                               (match-beginning 0) end))
+                      (beg (progn (goto-char beg)
+                                  (line-beginning-position)))
+                      space-beg space-end)
+                  (when (<= (line-end-position) end)
+                    ;; Replace space characters within parentheses
+                    ;; that resemble ChangeLog defun names between BEG
+                    ;; and END with non-breaking spaces to prevent
+                    ;; them from being considered break points by
+                    ;; `fill-region'.
+                    (save-excursion
+                      (goto-char beg)
+                      (when (re-search-forward
+                             "^[[:blank:]]*(.*\\([[:space:]]\\).*):"
+                             end t)
+                        (replace-regexp-in-region "[[:space:]]" " "
+                                                  (setq space-beg
+                                                        (copy-marker
+                                                         (match-beginning 0)))
+                                                  (setq space-end
+                                                        (copy-marker
+                                                         (match-end 0))))))
+                    (fill-region beg end justify))
+                  ;; Restore the spaces replaced by NBSPs.
+                  (when space-beg
+                    (replace-string-in-region " " " "
+                                              space-beg space-end)
+                    (set-marker space-beg nil)
+                    (set-marker space-end nil)))
+                defuns-beg)
+            (goto-char defuns-beg)
+            (setq defuns (change-log-read-defuns end))
+            (progn
+              (delete-region defuns-beg (point))
+              (log-edit--insert-filled-defuns defuns)
+              (setq beg (point))))
+          nil)
         t))))
 
 (defun log-edit-hide-buf (&optional buf where)
@@ -1230,3 +1389,7 @@ line of MSG."
 (provide 'log-edit)
 
 ;;; log-edit.el ends here
+
+;; Local Variables:
+;; coding: utf-8-unix
+;; End:
diff --git a/lisp/vc/log-view.el b/lisp/vc/log-view.el
index af24fcfd398..e9e6602e414 100644
--- a/lisp/vc/log-view.el
+++ b/lisp/vc/log-view.el
@@ -1,6 +1,6 @@
 ;;; log-view.el --- Major mode for browsing revision log histories -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: tools, vc
@@ -516,7 +516,8 @@ If called interactively, visit the version at point."
     (switch-to-buffer (vc-find-revision (if log-view-per-file-logs
                                            (log-view-current-file)
                                          (car log-view-vc-fileset))
-                                       (log-view-current-tag)))))
+                                       (log-view-current-tag)
+                                        log-view-vc-backend))))
 
 
 (defun log-view-extract-comment ()
@@ -562,7 +563,8 @@ If called interactively, annotate the version at point."
     (vc-annotate (if log-view-per-file-logs
                     (log-view-current-file)
                   (car log-view-vc-fileset))
-                (log-view-current-tag))))
+                (log-view-current-tag)
+                 nil nil nil log-view-vc-backend)))
 
 ;;
 ;; diff
diff --git a/lisp/vc/pcvs-defs.el b/lisp/vc/pcvs-defs.el
index 3bbf2355b81..05f07c6e999 100644
--- a/lisp/vc/pcvs-defs.el
+++ b/lisp/vc/pcvs-defs.el
@@ -1,6 +1,6 @@
 ;;; pcvs-defs.el --- variable definitions for PCL-CVS  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: pcl-cvs
diff --git a/lisp/vc/pcvs-info.el b/lisp/vc/pcvs-info.el
index 86655ef6fde..ad3dc265874 100644
--- a/lisp/vc/pcvs-info.el
+++ b/lisp/vc/pcvs-info.el
@@ -1,6 +1,6 @@
 ;;; pcvs-info.el --- internal representation of a fileinfo entry  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: pcl-cvs
diff --git a/lisp/vc/pcvs-parse.el b/lisp/vc/pcvs-parse.el
index df10efab41e..1c46324d7ce 100644
--- a/lisp/vc/pcvs-parse.el
+++ b/lisp/vc/pcvs-parse.el
@@ -1,6 +1,6 @@
 ;;; pcvs-parse.el --- the CVS output parser  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: pcl-cvs
diff --git a/lisp/vc/pcvs-util.el b/lisp/vc/pcvs-util.el
index 5ff94405d11..10daa07d668 100644
--- a/lisp/vc/pcvs-util.el
+++ b/lisp/vc/pcvs-util.el
@@ -1,6 +1,6 @@
 ;;; pcvs-util.el --- utility functions for PCL-CVS  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: pcl-cvs
diff --git a/lisp/vc/pcvs.el b/lisp/vc/pcvs.el
index 03426d47c5f..e987a685585 100644
--- a/lisp/vc/pcvs.el
+++ b/lisp/vc/pcvs.el
@@ -1,6 +1,6 @@
 ;;; pcvs.el --- a front-end to CVS  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
 
 ;; Author: The PCL-CVS Trust <pcl-cvs@cyclic.com>
 ;;     Per Cederqvist <ceder@lysator.liu.se>
diff --git a/lisp/vc/smerge-mode.el b/lisp/vc/smerge-mode.el
index e42b82c7064..a16c7871ff9 100644
--- a/lisp/vc/smerge-mode.el
+++ b/lisp/vc/smerge-mode.el
@@ -1,6 +1,6 @@
 ;;; smerge-mode.el --- Minor mode to resolve diff3 conflicts -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: vc, tools, revision control, merge, diff3, cvs, conflict
diff --git a/lisp/vc/vc-annotate.el b/lisp/vc/vc-annotate.el
index de6c3adbbdb..b206abec27f 100644
--- a/lisp/vc/vc-annotate.el
+++ b/lisp/vc/vc-annotate.el
@@ -1,6 +1,6 @@
 ;;; vc-annotate.el --- VC Annotate Support  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Martin Lorentzson <emwson@emw.ericsson.se>
 ;; Maintainer: emacs-devel@gnu.org
@@ -162,6 +162,11 @@ List of factors, used to expand/compress the time scale.  
See `vc-annotate'."
   :type '(repeat number)
   :group 'vc)
 
+(defcustom vc-annotate-use-short-revision t
+  "If non-nil, \\[vc-annotate] will use short revisions in its buffer name."
+  :type 'boolean
+  :group 'vc)
+
 (defvar-keymap vc-annotate-mode-map
   :doc "Local keymap used for VC-Annotate mode."
   "a"   #'vc-annotate-revision-previous-to-line
@@ -397,7 +402,10 @@ should be applied to the background or to the foreground."
    (save-current-buffer
      (vc-ensure-vc-buffer)
      (list buffer-file-name
-          (let ((def (vc-working-revision buffer-file-name)))
+          (let ((def (funcall (if vc-annotate-use-short-revision
+                                   #'vc-short-revision
+                                 #'vc-working-revision)
+                               buffer-file-name)))
             (if (null current-prefix-arg) def
               (vc-read-revision
                (format-prompt "Annotate from revision" def)
diff --git a/lisp/vc/vc-bzr.el b/lisp/vc/vc-bzr.el
index f66e37fffa4..a357dc4827f 100644
--- a/lisp/vc/vc-bzr.el
+++ b/lisp/vc/vc-bzr.el
@@ -1,6 +1,6 @@
 ;;; vc-bzr.el --- VC backend for the bzr revision control system  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Dave Love <fx@gnu.org>
 ;;        Riccardo Murri <riccardo.murri@gmail.com>
diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el
index 145697d1b06..52039f8da74 100644
--- a/lisp/vc/vc-cvs.el
+++ b/lisp/vc/vc-cvs.el
@@ -1,6 +1,6 @@
 ;;; vc-cvs.el --- non-resident support for CVS version-control  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1995, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF (see vc.el for full credits)
 ;; Package: vc
diff --git a/lisp/vc/vc-dav.el b/lisp/vc/vc-dav.el
index a0e3866cca2..ae2cf149771 100644
--- a/lisp/vc/vc-dav.el
+++ b/lisp/vc/vc-dav.el
@@ -1,6 +1,6 @@
 ;;; vc-dav.el --- vc.el support for WebDAV  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2001, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Bill Perry <wmperry@gnu.org>
 ;; Keywords: url, vc
diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el
index d5226910211..d733b36f8ff 100644
--- a/lisp/vc/vc-dir.el
+++ b/lisp/vc/vc-dir.el
@@ -1,6 +1,6 @@
 ;;; vc-dir.el --- Directory status display under VC  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Dan Nicolaescu <dann@ics.uci.edu>
 ;; Keywords: vc tools
diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el
index fd5f655a0f6..998cef649ff 100644
--- a/lisp/vc/vc-dispatcher.el
+++ b/lisp/vc/vc-dispatcher.el
@@ -1,6 +1,6 @@
 ;;; vc-dispatcher.el --- generic command-dispatcher facility.  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF (see below for full credits)
 ;; Keywords: vc tools
diff --git a/lisp/vc/vc-filewise.el b/lisp/vc/vc-filewise.el
index 99df438e294..a87592ba0fd 100644
--- a/lisp/vc/vc-filewise.el
+++ b/lisp/vc/vc-filewise.el
@@ -1,6 +1,6 @@
 ;;; vc-filewise.el --- common functions for file-oriented back ends.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1992-1996, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1996, 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF (see vc.el for full credits)
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 2e057ecfaa7..456417e566e 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -1,6 +1,6 @@
 ;;; vc-git.el --- VC backend for the git version control system -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Alexandre Julliard <julliard@winehq.org>
 ;; Keywords: vc tools
@@ -89,6 +89,7 @@
 ;; - make-version-backups-p (file)                 NOT NEEDED
 ;; - previous-revision (file rev)                  OK
 ;; - next-revision (file rev)                      OK
+;; - file-name-changes (rev)                       OK
 ;; - check-headers ()                              COULD BE SUPPORTED
 ;; - delete-file (file)                            OK
 ;; - rename-file (old new)                         OK
@@ -152,6 +153,18 @@ comparing changes.  See Man page `git-blame' for more."
                  (repeat :tag "Argument List" :value ("") string))
   :version "30.1")
 
+(defcustom vc-git-file-name-changes-switches '("-M" "-C")
+  "String or list of string to pass to Git when finding previous names.
+
+This option should usually at least contain '-M'.  You can adjust
+the flags to change the similarity thresholds (default 50%).  Or
+add `--find-copies-harder' (slower in large projects, since it
+uses a full scan)."
+  :type '(choice (const :tag "None" nil)
+                 (string :tag "Argument String")
+                 (repeat :tag "Argument List" :value ("") string))
+  :version "30.1")
+
 (defcustom vc-git-resolve-conflicts t
   "When non-nil, mark conflicted file as resolved upon saving.
 That is performed after all conflict markers in it have been
@@ -1416,7 +1429,16 @@ This prompts for a branch to merge from."
 ;; Long explanation here:
 ;; 
https://stackoverflow.com/questions/46487476/git-log-follow-graph-skips-commits
 (defcustom vc-git-print-log-follow nil
-  "If true, follow renames in Git logs for a single file."
+  "If non-nil, use the flag `--follow' when producing single file logs.
+
+A non-nil value will make the printed log automatically follow
+the file renames.  The downsides is that the log produced this
+way may omit certain (merge) commits, and that `log-view-diff'
+fails on commits that used the previous name, in that log buffer.
+
+When this variable is nil, and the log ends with a rename, we
+show a button below that which allows to show the log for the
+file name before the rename."
   :type 'boolean
   :version "26.1")
 
@@ -1835,8 +1857,11 @@ This requires git 1.8.4 or later, for the \"-L\" option 
of \"git log\"."
 (defun vc-git--rev-parse (rev)
   (with-temp-buffer
     (and
-     (vc-git--out-ok "rev-parse" rev)
-     (buffer-substring-no-properties (point-min) (+ (point-min) 40)))))
+     (apply #'vc-git--out-ok "rev-parse"
+            (append (when vc-use-short-revision '("--short"))
+                    (list rev)))
+     (goto-char (point-min))
+     (buffer-substring-no-properties (point) (pos-eol)))))
 
 (defun vc-git-next-revision (file rev)
   "Git-specific version of `vc-next-revision'."
@@ -1866,6 +1891,31 @@ This requires git 1.8.4 or later, for the \"-L\" option 
of \"git log\"."
                    (progn (forward-line 1) (1- (point)))))))))
     (or (vc-git-symbolic-commit next-rev) next-rev)))
 
+(defun vc-git-file-name-changes (rev)
+  (with-temp-buffer
+    (let ((root (vc-git-root default-directory)))
+      (unless vc-git-print-log-follow
+        (apply #'vc-git-command (current-buffer) t nil
+               "diff"
+               "--name-status"
+               "--diff-filter=ADCR"
+               (concat rev "^") rev
+               (vc-switches 'git 'file-name-changes)))
+      (let (res)
+        (goto-char (point-min))
+        (while (re-search-forward 
"^\\([ADCR]\\)[0-9]*\t\\([^\n\t]+\\)\\(?:\t\\([^\n\t]+\\)\\)?" nil t)
+          (pcase (match-string 1)
+            ("A" (push (cons nil (match-string 2)) res))
+            ("D" (push (cons (match-string 2) nil) res))
+            ((or "C" "R") (push (cons (match-string 2) (match-string 3)) res))
+            ;; ("M" (push (cons (match-string 1) (match-string 1)) res))
+            ))
+        (mapc (lambda (c)
+                (if (car c) (setcar c (expand-file-name (car c) root)))
+                (if (cdr c) (setcdr c (expand-file-name (cdr c) root))))
+              res)
+        (nreverse res)))))
+
 (defun vc-git-delete-file (file)
   (vc-git-command nil 0 file "rm" "-f" "--"))
 
@@ -1932,6 +1982,7 @@ This requires git 1.8.4 or later, for the \"-L\" option 
of \"git log\"."
 (defvar compilation-environment)
 
 ;; Derived from `lgrep'.
+;;;###autoload
 (defun vc-git-grep (regexp &optional files dir)
   "Run git grep, searching for REGEXP in FILES in directory DIR.
 The search is limited to file names matching shell pattern FILES.
diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el
index 9df517ea847..7de41a2ae50 100644
--- a/lisp/vc/vc-hg.el
+++ b/lisp/vc/vc-hg.el
@@ -1,6 +1,6 @@
 ;;; vc-hg.el --- VC backend for the mercurial version control system  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; Author: Ivan Kanis
 ;; Maintainer: emacs-devel@gnu.org
@@ -77,6 +77,7 @@
 ;; - make-version-backups-p (file)             ??
 ;; - previous-revision (file rev)              OK
 ;; - next-revision (file rev)                  OK
+;; - file-name-changes (rev)                   OK
 ;; - check-headers ()                          ??
 ;; - delete-file (file)                        TEST IT
 ;; - rename-file (old new)                     OK
@@ -583,8 +584,8 @@ Optional arg REVISION is a revision to annotate from."
     (vc-annotate-convert-time
      (let ((str (match-string-no-properties 2)))
        (encode-time 0 0 0
-                    (string-to-number (substring str 6 8))
-                    (string-to-number (substring str 4 6))
+                    (string-to-number (substring str 8 10))
+                    (string-to-number (substring str 5 7))
                     (string-to-number (substring str 0 4)))))))
 
 (defun vc-hg-annotate-extract-revision-at-line ()
@@ -1203,6 +1204,22 @@ REV is ignored."
         (vc-hg-command buffer 0 file "cat" "-r" rev)
       (vc-hg-command buffer 0 file "cat"))))
 
+(defun vc-hg-file-name-changes (rev)
+  (unless (member "--follow" vc-hg-log-switches)
+    (with-temp-buffer
+      (let ((root (vc-hg-root default-directory)))
+        (vc-hg-command (current-buffer) t nil
+                       "log" "-g" "-p" "-r" rev)
+        (let (res)
+          (goto-char (point-min))
+          (while (re-search-forward "^diff --git a/\\([^ \n]+\\) b/\\([^ 
\n]+\\)" nil t)
+            (when (not (equal (match-string 1) (match-string 2)))
+              (push (cons
+                     (expand-file-name (match-string 1) root)
+                     (expand-file-name (match-string 2) root))
+                    res)))
+          (nreverse res))))))
+
 (defun vc-hg-find-ignore-file (file)
   "Return the root directory of the repository of FILE."
   (expand-file-name ".hgignore"
diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el
index 8451128286b..1493845e2d9 100644
--- a/lisp/vc/vc-hooks.el
+++ b/lisp/vc/vc-hooks.el
@@ -1,6 +1,6 @@
 ;;; vc-hooks.el --- resident support for version-control  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1992-1996, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1996, 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF (see vc.el for full credits)
 ;; Maintainer: emacs-devel@gnu.org
@@ -185,7 +185,7 @@ revision number and lock status."
   "Version Control minor mode.
 This minor mode is automatically activated whenever you visit a file under
 control of one of the revision control systems in `vc-handled-backends'.
-VC commands are globally reachable under the prefix `\\[vc-prefix-map]':
+VC commands are globally reachable under the prefix \\[vc-prefix-map]:
 \\{vc-prefix-map}")
 
 (defmacro vc-error-occurred (&rest body)
@@ -506,6 +506,18 @@ If FILE is not registered, this function always returns 
nil."
                            (vc-call-backend
                             backend 'working-revision file))))))
 
+(defvar vc-use-short-revision nil
+  "If non-nil, VC backend functions should return short revisions if possible.
+This is set to t when calling `vc-short-revision', which will
+then call the \\=`working-revision' backend function.")
+
+(defun vc-short-revision (file &optional backend)
+  "Return the repository version for FILE in a shortened form.
+If FILE is not registered, this function always returns nil."
+  (let ((vc-use-short-revision t))
+    (vc-call-backend (or backend (vc-backend file))
+                     'working-revision file)))
+
 (defun vc-default-registered (backend file)
   "Check if FILE is registered in BACKEND using vc-BACKEND-master-templates."
   (let ((sym (vc-make-backend-sym backend 'master-templates)))
diff --git a/lisp/vc/vc-rcs.el b/lisp/vc/vc-rcs.el
index 3d6907cbec1..1a43b440d18 100644
--- a/lisp/vc/vc-rcs.el
+++ b/lisp/vc/vc-rcs.el
@@ -1,6 +1,6 @@
 ;;; vc-rcs.el --- support for RCS version-control  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF (see vc.el for full credits)
 ;; Maintainer: emacs-devel@gnu.org
@@ -714,7 +714,7 @@ Optional arg REVISION is a revision to annotate from."
             (insert insn)
           (delete-char insn)))
       ;; Now apply the forward-chronological edits (directly from the
-      ;; parse-tree) for the branch(es), if necessary.  We re-use vars
+      ;; parse-tree) for the branch(es), if necessary.  We reuse vars
       ;; `pre' and `meta' for the sake of internal func `r/d/a'.
       (while nbls
         (setq pre (cdr (pop nbls)))
diff --git a/lisp/vc/vc-sccs.el b/lisp/vc/vc-sccs.el
index 03e9d12b76f..7e87849337a 100644
--- a/lisp/vc/vc-sccs.el
+++ b/lisp/vc/vc-sccs.el
@@ -1,6 +1,6 @@
 ;;; vc-sccs.el --- support for SCCS version-control  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF (see vc.el for full credits)
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/vc/vc-src.el b/lisp/vc/vc-src.el
index 69903e8e681..c85c90f7897 100644
--- a/lisp/vc/vc-src.el
+++ b/lisp/vc/vc-src.el
@@ -1,6 +1,6 @@
 ;;; vc-src.el --- support for SRC version-control  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF (see vc.el for full credits)
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/vc/vc-svn.el b/lisp/vc/vc-svn.el
index 6c93c8b3cab..96baa642b44 100644
--- a/lisp/vc/vc-svn.el
+++ b/lisp/vc/vc-svn.el
@@ -1,6 +1,6 @@
 ;;; vc-svn.el --- non-resident support for Subversion version-control  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author:      FSF (see vc.el for full credits)
 ;; Maintainer:  Stefan Monnier <monnier@gnu.org>
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index 3085e4b9f76..f612daaa569 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -1,6 +1,6 @@
 ;;; vc.el --- drive a version-control system from within Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1992-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1998, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: FSF (see below for full credits)
 ;; Maintainer: emacs-devel@gnu.org
@@ -517,6 +517,13 @@
 ;;   Return the revision number that precedes REV for FILE, or nil if no such
 ;;   revision exists.
 ;;
+;; - file-name-changes (rev)
+;;
+;;   Return the list of pairs with changes in file names in REV.  When
+;;   a file was added, it should be a cons with nil car.  When
+;;   deleted, a cons with nil cdr.  When copied or renamed, a cons
+;;   with the source name as car and destination name as cdr.
+;;
 ;; - next-revision (file rev)
 ;;
 ;;   Return the revision number that follows REV for FILE, or nil if no such
@@ -668,7 +675,7 @@
 ;;;; New Primitives:
 ;;
 ;; - uncommit: undo last checkin, leave changes in place in the workfile,
-;;   stash the commit comment for re-use.
+;;   stash the commit comment for reuse.
 ;;
 ;; - deal with push operations.
 ;;
@@ -1067,6 +1074,7 @@ Within directories, only files already under version 
control are noticed."
 
 (defvar vc-dir-backend)
 (defvar log-view-vc-backend)
+(defvar log-view-vc-fileset)
 (defvar log-edit-vc-backend)
 (defvar diff-vc-backend)
 (defvar diff-vc-revisions)
@@ -1148,6 +1156,11 @@ BEWARE: this function may change the current buffer."
              (vc-state buffer-file-name)
              (vc-checkout-model backend buffer-file-name))
        (list backend (list buffer-file-name))))
+     ((derived-mode-p 'log-view-mode)
+      ;; 'log-view-mode' stashes the backend and the fileset in the
+      ;; two special variables, so we use them to avoid any possible
+      ;; mistakes from a decision made here ad-hoc.
+      (list log-view-vc-backend log-view-vc-fileset))
      ((and (buffer-live-p vc-parent-buffer)
            ;; FIXME: Why this test?  --Stef
            (or (buffer-file-name vc-parent-buffer)
@@ -2682,22 +2695,55 @@ Not all VC backends support short logs!")
 
 (defvar log-view-vc-fileset)
 (defvar log-view-message-re)
+;; XXX: File might have been renamed multiple times, so to support
+;; multiple jumps back, this probably should be a stack of entries.
+(defvar log-view-vc-prev-revision nil)
+(defvar log-view-vc-prev-fileset nil)
 
 (defun vc-print-log-setup-buttons (working-revision is-start-revision limit 
pl-return)
   "Insert at the end of the current buffer buttons to show more log entries.
 In the new log, leave point at WORKING-REVISION (if non-nil).
-LIMIT is the number of entries currently shown.
-Does nothing if IS-START-REVISION is non-nil, or if LIMIT is nil,
+LIMIT is the current maximum number of entries shown, or the
+revision (string) before which to stop.  Does nothing if
+IS-START-REVISION is non-nil and LIMIT is 1, or if LIMIT is nil,
 or if PL-RETURN is `limit-unsupported'."
+  ;; LIMIT=1 is set by vc-annotate-show-log-revision-at-line
+  ;; or by vc-print-root-log with current-prefix-arg=1.
+  ;; In either case only one revision is wanted, no buttons.
   (when (and limit (not (eq 'limit-unsupported pl-return))
-            (not is-start-revision))
+             (not (and is-start-revision
+                       (eql limit 1))))
     (let ((entries 0))
       (goto-char (point-min))
       (while (re-search-forward log-view-message-re nil t)
         (cl-incf entries))
-      ;; If we got fewer entries than we asked for, then displaying
-      ;; the "more" buttons isn't useful.
-      (when (>= entries limit)
+      (if (or (stringp limit)
+              (< entries limit))
+          ;; The log has been printed in full.  Perhaps it started
+          ;; with a copy or rename?
+          ;; FIXME: We'd probably still want this button even when
+          ;; vc-log-show-limit is customized to 0 (should be rare).
+          (let* ((last-revision (log-view-current-tag (point-max)))
+                 ;; XXX: Could skip this when vc-git-print-log-follow = t.
+                 (name-changes
+                  (condition-case nil
+                      (vc-call-backend log-view-vc-backend
+                                       'file-name-changes last-revision)
+                    (vc-not-supported nil)))
+                 (matching-changes
+                  (cl-delete-if-not (lambda (f) (member f log-view-vc-fileset))
+                                    name-changes :key #'cdr))
+                 (old-names (delq nil (mapcar #'car matching-changes))))
+            (when old-names
+              (goto-char (point-max))
+              (unless (looking-back "\n\n" (- (point) 2))
+                (insert "\n"))
+              (vc-print-log-renamed-add-button old-names log-view-vc-backend
+                                               log-view-vc-fileset
+                                               working-revision
+                                               last-revision
+                                               limit)))
+        ;; Perhaps there are more entries in the log.
         (goto-char (point-max))
         (insert "\n")
         (insert-text-button
@@ -2718,16 +2764,57 @@ or if PL-RETURN is `limit-unsupported'."
          'help-echo "Show the log again, including all entries")
         (insert "\n")))))
 
+(defun vc-print-log-renamed-add-button ( renamed-files backend
+                                         current-fileset
+                                         current-revision
+                                         revision limit)
+  "Print the button for jump to the log for a different fileset.
+RENAMED-FILES is the fileset to use.  BACKEND is the VC backend.
+REVISION is the revision from which to start the new log.
+CURRENT-FILESET, if non-nil, is the fileset to use in the \"back\"
+button for.  Same for CURRENT-REVISION.  LIMIT means the usual."
+  (let ((relatives (mapcar #'file-relative-name renamed-files))
+        (from-to (if current-fileset "from" "to"))
+        (before-after (if current-fileset "before" "after")))
+    (insert
+     (format
+      "Renamed %s %s"
+      from-to
+      (mapconcat (lambda (s)
+                   (propertize s 'font-lock-face
+                               'log-view-file))
+                 relatives
+                 ", "))
+     " ")
+    (insert-text-button
+     "View log"
+     'action (lambda (&rest _ignore)
+               ;; To set up parent buffer in the new viewer.
+               (with-current-buffer vc-parent-buffer
+                 (let ((log-view-vc-prev-fileset current-fileset)
+                       (log-view-vc-prev-revision current-revision))
+                   (vc-print-log-internal backend renamed-files
+                                          revision t limit))))
+     ;; XXX: Showing the full history for OLD-NAMES (with
+     ;; IS-START-REVISION=nil) can be better sometimes
+     ;; (e.g. when some edits still occurred after a rename
+     ;; -- multiple branches scenario), but it also can hurt
+     ;; in others because of Git's automatic history
+     ;; simplification: as a result, the logs for some
+     ;; use-package's files before merge could not be found.
+     'help-echo
+     (format
+      "Show the log for the file name(s) %s the rename"
+      before-after))))
+
 (defun vc-print-log-internal (backend files working-revision
                                       &optional is-start-revision limit type)
   "For specified BACKEND and FILES, show the VC log.
 Leave point at WORKING-REVISION, if it is non-nil.
 If IS-START-REVISION is non-nil, start the log from WORKING-REVISION
 \(not all backends support this); i.e., show only WORKING-REVISION and
-earlier revisions.  Show up to LIMIT entries (non-nil means unlimited)."
-  ;; As of 2013/04 the only thing that passes IS-START-REVISION non-nil
-  ;; is vc-annotate-show-log-revision-at-line, which sets LIMIT = 1.
-
+earlier revisions.  Show up to LIMIT entries (nil means unlimited).
+LIMIT can also be a string, which means the revision before which to stop."
   ;; Don't switch to the output buffer before running the command,
   ;; so that any buffer-local settings in the vc-controlled
   ;; buffer can be accessed by the command.
@@ -2739,8 +2826,22 @@ earlier revisions.  Show up to LIMIT entries (non-nil 
means unlimited)."
       (vc-log-internal-common
        backend buffer-name files type
        (lambda (bk buf _type-arg files-arg)
-        (vc-call-backend bk 'print-log files-arg buf shortlog
-                          (when is-start-revision working-revision) limit))
+         (vc-call-backend bk 'print-log files-arg buf shortlog
+                          (when is-start-revision working-revision) limit)
+         (when log-view-vc-prev-fileset
+           (with-current-buffer buf
+             (let ((inhibit-read-only t)
+                   (pmark (process-mark (get-buffer-process buf))))
+               (goto-char (point-min))
+               (vc-print-log-renamed-add-button log-view-vc-prev-fileset
+                                                backend
+                                                nil
+                                                nil
+                                                log-view-vc-prev-revision
+                                                limit)
+               (insert "\n\n")
+               (when (< pmark (point))
+                 (set-marker pmark (point)))))))
        (lambda (_bk _files-arg ret)
          (save-excursion
            (vc-print-log-setup-buttons working-revision
diff --git a/lisp/vcursor.el b/lisp/vcursor.el
index 48fa1160deb..ec5adbd832c 100644
--- a/lisp/vcursor.el
+++ b/lisp/vcursor.el
@@ -1,6 +1,6 @@
 ;;; vcursor.el --- manipulate an alternative ("virtual") cursor  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
 
 ;; Author: Peter Stephenson <pws@ibmth.df.unipi.it>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/version.el b/lisp/version.el
index 0eb4ea76f4f..a84f7f161f0 100644
--- a/lisp/version.el
+++ b/lisp/version.el
@@ -1,6 +1,6 @@
 ;;; version.el --- record version number of Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985, 1992, 1994-1995, 1999-2023 Free Software
+;; Copyright (C) 1985, 1992, 1994-1995, 1999-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/view.el b/lisp/view.el
index 8760b91d06c..2ac7479739f 100644
--- a/lisp/view.el
+++ b/lisp/view.el
@@ -1,6 +1,6 @@
 ;;; view.el --- peruse file or buffer without editing  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Author: K. Shane Hartman
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/visual-wrap.el b/lisp/visual-wrap.el
new file mode 100644
index 00000000000..d95cf4bb569
--- /dev/null
+++ b/lisp/visual-wrap.el
@@ -0,0 +1,204 @@
+;;; visual-wrap.el --- Smart line-wrapping with wrap-prefix -*- 
lexical-binding: t -*-
+
+;; Copyright (C) 2011-2021, 2024 Free Software Foundation, Inc.
+
+;; Author: Stephen Berman <stephen.berman@gmx.net>
+;;         Stefan Monnier <monnier@iro.umontreal.ca>
+;; Maintainer: emacs-devel@gnu.org
+;; Keywords: convenience
+;; Package: emacs
+
+;; This file is part of GNU Emacs.
+
+;; This program 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.
+
+;; This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package provides the `visual-wrap-prefix-mode' minor mode
+;; which sets the wrap-prefix property on the fly so that
+;; single-long-line paragraphs get word-wrapped in a way similar to
+;; what you'd get with M-q using adaptive-fill-mode, but without
+;; actually changing the buffer's text.
+
+;;; Code:
+
+(defcustom visual-wrap-extra-indent 0
+  "Number of extra spaces to indent in `visual-wrap-prefix-mode'.
+
+`visual-wrap-prefix-mode' indents the visual lines to the level
+of the actual line plus `visual-wrap-extra-indent'.  A negative
+value will do a relative de-indent.
+
+Examples:
+
+actual indent = 2
+extra indent = -1
+
+  Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed
+ do eiusmod tempor incididunt ut labore et dolore magna
+ aliqua. Ut enim ad minim veniam, quis nostrud exercitation
+ ullamco laboris nisi ut aliquip ex ea commodo consequat.
+
+actual indent = 2
+extra indent = 2
+
+  Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed
+    do eiusmod tempor incididunt ut labore et dolore magna
+    aliqua. Ut enim ad minim veniam, quis nostrud exercitation
+    ullamco laboris nisi ut aliquip ex ea commodo consequat."
+  :type 'integer
+  :safe 'integerp
+  :version "30.1"
+  :group 'visual-line)
+
+(defun visual-wrap--face-extend-p (face)
+  ;; Before Emacs 27, faces always extended beyond EOL, so we check
+  ;; for a non-default background instead.
+  (cond
+   ((listp face)
+    (plist-get face (if (fboundp 'face-extend-p) :extend :background)))
+   ((symbolp face)
+    (if (fboundp 'face-extend-p)
+        (face-extend-p face nil t)
+      (face-background face nil t)))))
+
+(defun visual-wrap--prefix-face (fcp _beg end)
+  ;; If the fill-context-prefix already specifies a face, just use that.
+  (cond ((get-text-property 0 'face fcp))
+        ;; Else, if the last character is a newline and has a face
+        ;; that extends beyond EOL, assume that this face spans the
+        ;; whole line and apply it to the prefix to preserve the
+        ;; "block" visual effect.
+        ;;
+        ;; NB: the face might not actually span the whole line: see
+        ;; for example removed lines in diff-mode, where the first
+        ;; character has the diff-indicator-removed face, while the
+        ;; rest of the line has the diff-removed face.
+        ((= (char-before end) ?\n)
+         (let ((eol-face (get-text-property (1- end) 'face)))
+           ;; `eol-face' can be a face, a "face value"
+           ;; (plist of face properties) or a list of one of those.
+           (if (or (not (consp eol-face)) (keywordp (car eol-face)))
+               ;; A single face.
+               (if (visual-wrap--face-extend-p eol-face) eol-face)
+             ;; A list of faces.  Keep the ones that extend beyond EOL.
+             (delq nil (mapcar (lambda (f)
+                                 (if (visual-wrap--face-extend-p f) f))
+                               eol-face)))))))
+
+(defun visual-wrap--prefix (fcp)
+  (let ((fcp-len (string-width fcp)))
+    (cond
+     ((= 0 visual-wrap-extra-indent)
+      fcp)
+     ((< 0 visual-wrap-extra-indent)
+      (concat fcp (make-string visual-wrap-extra-indent ?\s)))
+     ((< 0 (+ visual-wrap-extra-indent fcp-len))
+      (substring fcp
+                 0
+                 (+ visual-wrap-extra-indent fcp-len)))
+     (t
+      ""))))
+
+(defun visual-wrap-fill-context-prefix (beg end)
+  "Compute visual wrap prefix from text between BEG and END.
+This is like `fill-context-prefix', but with prefix length adjusted
+by `visual-wrap-extra-indent'."
+  (let* ((fcp
+          ;; `fill-context-prefix' ignores prefixes that look like
+          ;; paragraph starts, in order to avoid inadvertently
+          ;; creating a new paragraph while filling, but here we're
+          ;; only dealing with single-line "paragraphs" and we don't
+          ;; actually modify the buffer, so this restriction doesn't
+          ;; make much sense (and is positively harmful in
+          ;; taskpaper-mode where paragraph-start matches everything).
+          (or (let ((paragraph-start regexp-unmatchable))
+                    (fill-context-prefix beg end))
+                  ;; Note: fill-context-prefix may return nil; See:
+                  ;; http://article.gmane.org/gmane.emacs.devel/156285
+              ""))
+         (prefix (visual-wrap--prefix fcp))
+         (face (visual-wrap--prefix-face fcp beg end)))
+    (if face
+        (propertize prefix 'face face)
+      prefix)))
+
+(defun visual-wrap-prefix-function (beg end)
+  "Indent the region between BEG and END with visual filling."
+  ;; Any change at the beginning of a line might change its wrap
+  ;; prefix, which affects the whole line.  So we need to "round-up"
+  ;; `end' to the nearest end of line.  We do the same with `beg'
+  ;; although it's probably not needed.
+  (goto-char end)
+  (unless (bolp) (forward-line 1))
+  (setq end (point))
+  (goto-char beg)
+  (forward-line 0)
+  (setq beg (point))
+  (while (< (point) end)
+    (let ((lbp (point)))
+      (put-text-property
+       (point) (progn (search-forward "\n" end 'move) (point))
+       'wrap-prefix
+       (let ((pfx (visual-wrap-fill-context-prefix
+                  lbp (point))))
+        ;; Remove any `wrap-prefix' property that might have been
+        ;; added earlier.  Otherwise, we end up with a string
+        ;; containing a `wrap-prefix' string containing a
+        ;; `wrap-prefix' string ...
+        (remove-text-properties
+         0 (length pfx) '(wrap-prefix) pfx)
+         (let ((dp (get-text-property 0 'display pfx)))
+           (when (and dp (eq dp (get-text-property (1- lbp) 'display)))
+             ;; There's a `display' property which covers not just the
+             ;; prefix but also the previous newline.  So it's not
+             ;; just making the prefix more pretty and could interfere
+             ;; or even defeat our efforts (e.g. it comes from
+             ;; `adaptive-fill-mode').
+             (remove-text-properties
+             0 (length pfx) '(display) pfx)))
+        pfx))))
+  `(jit-lock-bounds ,beg . ,end))
+
+;;;###autoload
+(define-minor-mode visual-wrap-prefix-mode
+  "Display continuation lines with prefixes from surrounding context.
+To enable this minor mode across all buffers, enable
+`global-visual-wrap-prefix-mode'."
+  :lighter ""
+  :group 'visual-line
+  (if visual-wrap-prefix-mode
+      (progn
+        ;; HACK ATTACK!  We want to run after font-lock (so our
+        ;; wrap-prefix includes the faces applied by font-lock), but
+        ;; jit-lock-register doesn't accept an `append' argument, so
+        ;; we add ourselves beforehand, to make sure we're at the end
+        ;; of the hook (bug#15155).
+        (add-hook 'jit-lock-functions
+                  #'visual-wrap-prefix-function 'append t)
+        (jit-lock-register #'visual-wrap-prefix-function))
+    (jit-lock-unregister #'visual-wrap-prefix-function)
+    (with-silent-modifications
+      (save-restriction
+        (widen)
+        (remove-text-properties (point-min) (point-max) '(wrap-prefix nil))))))
+
+;;;###autoload
+(define-globalized-minor-mode global-visual-wrap-prefix-mode
+  visual-wrap-prefix-mode visual-wrap-prefix-mode
+  :init-value nil
+  :group 'visual-line)
+
+(provide 'visual-wrap)
+;;; visual-wrap.el ends here
diff --git a/lisp/w32-fns.el b/lisp/w32-fns.el
index d9b91cfb6ea..a68f1ceec35 100644
--- a/lisp/w32-fns.el
+++ b/lisp/w32-fns.el
@@ -1,6 +1,6 @@
 ;;; w32-fns.el --- Lisp routines for 32-bit Windows  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Geoff Voelker <voelker@cs.washington.edu>
 ;; Keywords: internal
diff --git a/lisp/w32-vars.el b/lisp/w32-vars.el
index a3deab9bc3a..0c567dda918 100644
--- a/lisp/w32-vars.el
+++ b/lisp/w32-vars.el
@@ -1,6 +1,6 @@
 ;;; w32-vars.el --- MS-Windows specific user options  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; Author: Jason Rumney <jasonr@gnu.org>
 ;; Keywords: internal
diff --git a/lisp/wdired.el b/lisp/wdired.el
index b5b01f0d089..d5d593483dc 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -1,6 +1,6 @@
 ;;; wdired.el --- Rename files editing their names in dired buffers -*- 
coding: utf-8; lexical-binding: t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Filename: wdired.el
 ;; Author: Juan León Lahoz García <juanleon1@gmail.com>
diff --git a/lisp/whitespace.el b/lisp/whitespace.el
index f4095c99089..15c1b83fcc1 100644
--- a/lisp/whitespace.el
+++ b/lisp/whitespace.el
@@ -1,9 +1,9 @@
 ;;; whitespace.el --- minor mode to visualize TAB, (HARD) SPACE, NEWLINE -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: data, wp
+;; Keywords: data, text
 ;; Version: 13.2.2
 ;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
 
@@ -1774,10 +1774,10 @@ cleaning up these problems."
               (when has-bogus
                 (goto-char (point-max))
                 (insert (substitute-command-keys
-                         " Type `\\[whitespace-cleanup]'")
+                         " Type \\[whitespace-cleanup]")
                         " to cleanup the buffer.\n\n"
                         (substitute-command-keys
-                         " Type `\\[whitespace-cleanup-region]'")
+                         " Type \\[whitespace-cleanup-region]")
                         " to cleanup a region.\n\n"))
               (whitespace-display-window (current-buffer))))))
       has-bogus)))
diff --git a/lisp/wid-browse.el b/lisp/wid-browse.el
index 9578531fcc3..bb56f3f62fb 100644
--- a/lisp/wid-browse.el
+++ b/lisp/wid-browse.el
@@ -1,6 +1,6 @@
 ;;; wid-browse.el --- functions for browsing widgets  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
 
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: extensions
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index 6ae00171d84..cd06acd3f99 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -1,6 +1,6 @@
 ;;; wid-edit.el --- Functions for creating and using widgets -*- 
lexical-binding:t -*-
 ;;
-;; Copyright (C) 1996-1997, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 1999-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/widget.el b/lisp/widget.el
index 0d4396ad1c1..11954378af1 100644
--- a/lisp/widget.el
+++ b/lisp/widget.el
@@ -1,6 +1,6 @@
 ;;; widget.el --- a library of user interface components  -*- lexical-binding: 
t; -*-
 ;;
-;; Copyright (C) 1996-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2001-2024 Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: help, extensions, faces, hypermedia
diff --git a/lisp/windmove.el b/lisp/windmove.el
index 96b8597ae09..b4e77102abd 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -1,6 +1,6 @@
 ;;; windmove.el --- directional window-selection routines  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
 
 ;; Author: Hovav Shacham <hovav@cs.stanford.edu>
 ;; Created: 17 October 1998
@@ -641,7 +641,7 @@ Default value of MODIFIERS is `shift-meta'."
 
 (defun windmove-delete-in-direction (dir &optional arg)
   "Delete the window at direction DIR.
-If prefix ARG is `\\[universal-argument]', also kill the buffer in that window.
+If prefix ARG is \\[universal-argument], also kill the buffer in that window.
 With \\`M-0' prefix, delete the selected window and
 select the window at direction DIR.
 When `windmove-wrap-around' is non-nil, takes the window
diff --git a/lisp/window.el b/lisp/window.el
index 4a11d5f13b7..58d4100a029 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -1,6 +1,6 @@
 ;;; window.el --- GNU Emacs window commands aside from those written in C  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: internal
@@ -5737,7 +5737,8 @@ The current window configuration is retained in the top 
window,
 the lower window takes up the whole width of the frame.  SIZE is
 handled as in `split-window-below', and interactively is the
 prefix numeric argument."
-  (interactive "p")
+  (interactive `(,(when current-prefix-arg
+                    (prefix-numeric-value current-prefix-arg))))
   (split-window-below size (frame-root-window)))
 
 (defun split-window-right (&optional size window-to-split)
@@ -5777,7 +5778,8 @@ The current window configuration is retained within the 
left
 window, and a new window is created on the right, taking up the
 whole height of the frame.  SIZE is treated as by
 `split-window-right' and interactively, is the prefix numeric argument."
-  (interactive "p")
+  (interactive `(,(when current-prefix-arg
+                    (prefix-numeric-value current-prefix-arg))))
   (split-window-right size (frame-root-window)))
 
 ;;; Balancing windows.
@@ -6862,6 +6864,7 @@ BUFFER in a window of the selected frame.
 If ARGS is a list whose car is a symbol, use (car ARGS) as a
 function to do the work.  Pass it BUFFER as first argument, and
 pass the elements of (cdr ARGS) as the remaining arguments."
+  (declare (obsolete display-buffer-pop-up-frame "30.1"))
   (if (and args (symbolp (car args)))
       (apply (car args) buffer (cdr args))
     (let ((window (get-buffer-window buffer 0)))
@@ -6881,9 +6884,8 @@ pass the elements of (cdr ARGS) as the remaining 
arguments."
        ;; Stay on the same frame if requested.
        (when (or (cdr (assq 'same-frame args)) (cdr (assq 'same-window args)))
         (let* ((pop-up-windows t)
-               pop-up-frames
                special-display-buffer-names special-display-regexps)
-          (display-buffer buffer)))
+          (display-buffer buffer '((pop-up-frames . nil)))))
        ;; If no window yet, make one in a new frame.
        (let* ((frame
               (with-current-buffer buffer
@@ -6996,6 +6998,13 @@ Emacs Lisp manual for an example."
          (const :tag "Always" t))
   :group 'windows)
 
+(defun window--pop-up-frames (alist)
+ (let* ((override (assq 'pop-up-frames alist))
+        (pop-up (if override (cdr override) pop-up-frames)))
+   (if (eq pop-up 'graphic-only)
+       (display-graphic-p)
+     pop-up)))
+
 (defcustom display-buffer-reuse-frames nil
   "Non-nil means `display-buffer' should reuse frames.
 If the buffer in question is already displayed in a frame, raise
@@ -7742,6 +7751,8 @@ Action alist entries are:
     Possible values are nil (the selected frame), t (any live
     frame), visible (any visible frame), 0 (any visible or
     iconified frame) or an existing live frame.
+ `pop-up-frames' -- Same effect as the eponymous variable.
+    Takes precedence over the variable.
  `pop-up-frame-parameters' -- The value specifies an alist of
     frame parameters to give a new frame, if one is created.
  `window-height' -- The value specifies the desired height of the
@@ -7787,6 +7798,14 @@ Action alist entries are:
     and `preserve-size' are applied.  The function is supposed
     to fill the window body with some contents that might depend
     on dimensions of the displayed window.
+ `post-command-select-window' -- A non-nil value means that after the
+    current command is executed and the hook `post-command-hook' is called,
+    the window displayed by this function will be selected.  A nil value
+    means that if functions like `pop-to-buffer' selected another window,
+    at the end of this command that window will be deselected, and the
+    window that was selected before calling this function will remain
+    selected regardless of which windows were selected afterwards within
+    this command.
 
 The entries `window-height', `window-width', `window-size' and
 `preserve-size' are applied only when the window used for
@@ -7830,18 +7849,29 @@ specified by the ACTION argument."
                           user-action special-action action extra-action
                           display-buffer-base-action
                           display-buffer-fallback-action))
-           (functions (apply 'append
+           (functions (apply #'append
                              (mapcar (lambda (x)
                                        (setq x (car x))
                                        (if (functionp x) (list x) x))
                                      actions)))
-           (alist (apply 'append (mapcar 'cdr actions)))
+           (alist (apply #'append (mapcar #'cdr actions)))
            window)
       (unless (buffer-live-p buffer)
         (error "Invalid buffer"))
       (while (and functions (not window))
         (setq window (funcall (car functions) buffer alist)
               functions (cdr functions)))
+      (when-let ((select (assq 'post-command-select-window alist)))
+        (letrec ((old-selected-window (selected-window))
+                 (postfun
+                  (lambda ()
+                    (if (cdr select)
+                        (when (window-live-p window)
+                          (select-window window))
+                      (when (window-live-p old-selected-window)
+                        (select-window old-selected-window)))
+                    (remove-hook 'post-command-hook postfun))))
+          (add-hook 'post-command-hook postfun)))
       (and (windowp window) window))))
 
 (defun display-buffer-other-frame (buffer)
@@ -7978,9 +8008,7 @@ called only by `display-buffer' or a function directly or
 indirectly called by the latter."
   (let* ((alist-entry (assq 'reusable-frames alist))
         (frames (cond (alist-entry (cdr alist-entry))
-                      ((if (eq pop-up-frames 'graphic-only)
-                           (display-graphic-p)
-                         pop-up-frames)
+                      ((window--pop-up-frames alist)
                        0)
                       (display-buffer-reuse-frames 0)
                       (t (last-nonminibuffer-frame))))
@@ -8034,9 +8062,7 @@ indirectly called by the latter."
   (let* ((alist-entry (assq 'reusable-frames alist))
          (alist-mode-entry (assq 'mode alist))
         (frames (cond (alist-entry (cdr alist-entry))
-                      ((if (eq pop-up-frames 'graphic-only)
-                           (display-graphic-p)
-                         pop-up-frames)
+                      ((window--pop-up-frames alist)
                        0)
                       (display-buffer-reuse-frames 0)
                       (t (last-nonminibuffer-frame))))
@@ -8182,9 +8208,7 @@ text-only terminal), try with 
`display-buffer-pop-up-frame'.
 ALIST is an association list of action symbols and values.  See
 Info node `(elisp) Buffer Display Action Alists' for details of
 such alists."
-  (and (if (eq pop-up-frames 'graphic-only)
-          (display-graphic-p)
-        pop-up-frames)
+  (and (window--pop-up-frames alist)
        (display-buffer-pop-up-frame buffer alist)))
 
 (defun display-buffer--maybe-pop-up-window (buffer alist)
@@ -8548,9 +8572,7 @@ indirectly called by the latter."
          (cdr (assq 'inhibit-same-window alist)))
         (frames (cond
                  (alist-entry (cdr alist-entry))
-                 ((if (eq pop-up-frames 'graphic-only)
-                      (display-graphic-p)
-                    pop-up-frames)
+                 ((window--pop-up-frames alist)
                   0)
                  (display-buffer-reuse-frames 0)
                  (t (last-nonminibuffer-frame))))
@@ -8603,7 +8625,7 @@ buffer.  ALIST is a buffer display action alist as 
compiled by
   canonical frame lines.  If it is the constant `full-height',
   prefer a full-height window.
 
-If ALIST contains a non-nil `inhibit-same--window' entry, do not
+If ALIST contains a non-nil `inhibit-same-window' entry, do not
 return the selected window."
   (let ((windows
          (window-list-1 nil 'nomini (cdr (assq 'lru-frames alist))))
@@ -10811,7 +10833,8 @@ Used in `repeat-mode'."
   "^ f" #'tear-off-window
   "^ t" #'tab-window-detach
   "-" #'fit-window-to-buffer
-  "0" #'delete-windows-on)
+  "0" #'delete-windows-on
+  "q" #'quit-window)
 (define-key ctl-x-map "w" window-prefix-map)
 
 (provide 'window)
diff --git a/lisp/winner.el b/lisp/winner.el
index 84a7b0ce903..2aa59a86b25 100644
--- a/lisp/winner.el
+++ b/lisp/winner.el
@@ -1,6 +1,6 @@
 ;;; winner.el --- Restore old window configurations  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
 
 ;; Author: Ivar Rummelhoff <ivarru@math.uio.no>
 ;; Created: 27 Feb 1997
diff --git a/lisp/woman.el b/lisp/woman.el
index b908e81a994..2357ba6b132 100644
--- a/lisp/woman.el
+++ b/lisp/woman.el
@@ -1,6 +1,6 @@
 ;;; woman.el --- browse UN*X manual pages `wo (without) man'  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Francis J. Wright <F.J.Wright@qmul.ac.uk>
 ;; Maintainer: emacs-devel@gnu.org
@@ -2566,7 +2566,8 @@ If DELETE is non-nil then delete from point."
                       ;; "\\(\\\\{\\)\\|\\(\n[.']\\)?[ \t]*\\\\}[ \t]*"
                       ;; Interpret bogus `el \}' as `el \{',
                       ;; especially for Tcl/Tk man pages:
-                      "\\(\\\\{\\|el[ \t]*\\\\}\\)\\|\\(\n[.']\\)?[ \t]*\\\\}[ 
\t]*")
+                      "\\(\\\\{\\|el[ \t]*\\\\}\\)\\|\\(\n[.']\\)?[ \t]*\\\\}[ 
\t]*"
+                       nil t)
                      (match-beginning 1))
               (re-search-forward "\\\\}"))
             (delete-region (if delete from (match-beginning 0)) (point))
diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el
index cf7f61b39a7..063b1dd6228 100644
--- a/lisp/x-dnd.el
+++ b/lisp/x-dnd.el
@@ -1,6 +1,6 @@
 ;;; x-dnd.el --- drag and drop support for X  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 ;; Author: Jan Djärv <jan.h.d@swipnet.se>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/xdg.el b/lisp/xdg.el
index 43b29578976..4c675489400 100644
--- a/lisp/xdg.el
+++ b/lisp/xdg.el
@@ -1,6 +1,6 @@
 ;;; xdg.el --- XDG specification and standard support -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Mark Oteiza <mvoteiza@udel.edu>
 ;; Created: 27 January 2017
diff --git a/lisp/xml.el b/lisp/xml.el
index 5a7501dcf41..849377bb758 100644
--- a/lisp/xml.el
+++ b/lisp/xml.el
@@ -1,6 +1,6 @@
 ;;; xml.el --- XML parser -*- lexical-binding: t -*-
 
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Emmanuel Briot <briot@gnat.com>
 ;; Maintainer: Mark A. Hershberger <mah@everybody.org>
diff --git a/lisp/xt-mouse.el b/lisp/xt-mouse.el
index 4ccd35d5277..081b8f32456 100644
--- a/lisp/xt-mouse.el
+++ b/lisp/xt-mouse.el
@@ -1,6 +1,6 @@
 ;;; xt-mouse.el --- support the mouse when emacs run in an xterm -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 1994, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 2000-2024 Free Software Foundation, Inc.
 
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: mouse, terminals
@@ -40,6 +40,8 @@
 
 ;;; Code:
 
+(require 'mwheel)
+
 (defvar xterm-mouse-debug-buffer nil)
 
 (defun xterm-mouse-translate (_event)
@@ -63,9 +65,13 @@ https://invisible-island.net/xterm/ctlseqs/ctlseqs.html)."
           (is-move (eq 'mouse-movement ev-command))
           (is-down (string-match "down-" (symbol-name ev-command))))
 
-      ;; Mouse events symbols must have an 'event-kind property with
-      ;; the value 'mouse-click.
-      (when ev-command (put ev-command 'event-kind 'mouse-click))
+      ;; Mouse events symbols must have an 'event-kind property set.
+      ;; Most of them use the value 'mouse-click, but 'mouse-movement has
+      ;; a different value.  See head_table in keyboard.c. (bug#67457)
+      (when ev-command (put ev-command 'event-kind
+                            (if (eq ev-command 'mouse-movement)
+                                'mouse-movement
+                              'mouse-click)))
 
       (cond
        ((null event) nil)              ;Unknown/bogus byte sequence!
@@ -189,6 +195,12 @@ single byte."
           (cons n c))
       (cons (- (setq c (xterm-mouse--read-coordinate)) 32) c))))
 
+(defun xterm-mouse--button-p (event btn)
+  (and (symbolp event)
+       (string-prefix-p "mouse-" (symbol-name event))
+       (eq btn (car (read-from-string (symbol-name event)
+                                      (length "mouse-"))))))
+
 ;; XTerm reports mouse events as
 ;; <EVENT-CODE> <X> <Y> in default mode, and
 ;; <EVENT-CODE> ";" <X> ";" <Y> <"M" or "m"> in extended mode.
@@ -226,13 +238,22 @@ single byte."
              ;; Spurious release event without previous button-down
              ;; event: assume, that the last button was button 1.
              (t 1)))
-       (sym (if move 'mouse-movement
-              (intern (concat (if ctrl "C-" "")
-                              (if meta "M-" "")
-                              (if shift "S-" "")
-                              (if down "down-" "")
-                              "mouse-"
-                              (number-to-string btn))))))
+       (sym
+        (if move 'mouse-movement
+          (intern
+           (concat
+            (if ctrl "C-" "")
+            (if meta "M-" "")
+            (if shift "S-" "")
+            (if down "down-" "")
+            (cond
+             ;; BEWARE: `mouse-wheel-UP-event' corresponds to
+             ;; `wheel-DOWN' events and vice versa!!
+             ((xterm-mouse--button-p mouse-wheel-down-event btn)  "wheel-up")
+             ((xterm-mouse--button-p mouse-wheel-up-event btn)    "wheel-down")
+             ((xterm-mouse--button-p mouse-wheel-left-event btn)  "wheel-left")
+             ((xterm-mouse--button-p mouse-wheel-right-event btn) 
"wheel-right")
+             (t (format "mouse-%d" btn))))))))
     (list sym (1- x) (1- y))))
 
 (defun xterm-mouse--set-click-count (event click-count)
diff --git a/lisp/xwidget.el b/lisp/xwidget.el
index 7daca81f9f7..cca01c8cb3a 100644
--- a/lisp/xwidget.el
+++ b/lisp/xwidget.el
@@ -1,6 +1,6 @@
 ;;; xwidget.el --- api functions for xwidgets  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Joakim Verona <joakim@verona.se>
 
diff --git a/lisp/yank-media.el b/lisp/yank-media.el
index abc137d9c38..e33c36da5b6 100644
--- a/lisp/yank-media.el
+++ b/lisp/yank-media.el
@@ -1,6 +1,6 @@
 ;;; yank-media.el --- Yanking images and HTML  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: utility
diff --git a/lwlib/ChangeLog.1 b/lwlib/ChangeLog.1
index 460e73f4dcc..a033a797387 100644
--- a/lwlib/ChangeLog.1
+++ b/lwlib/ChangeLog.1
@@ -1964,7 +1964,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1995-1999, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1995-1999, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/lwlib/Makefile.in b/lwlib/Makefile.in
index 70f6cd17d78..fbb60b35b24 100644
--- a/lwlib/Makefile.in
+++ b/lwlib/Makefile.in
@@ -1,7 +1,7 @@
 ### @configure_input@
 
 # Copyright (C) 1992, 1993 Lucid, Inc.
-# Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 #
 # This file is part of the Lucid Widget Library.
 #
diff --git a/lwlib/deps.mk b/lwlib/deps.mk
index d55374d3023..20671375706 100644
--- a/lwlib/deps.mk
+++ b/lwlib/deps.mk
@@ -1,7 +1,7 @@
 ### deps.mk --- lwlib/Makefile fragment for GNU Emacs
 
 # Copyright (C) 1992, 1993 Lucid, Inc.
-# Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 #
 # This file is part of the Lucid Widget Library.
 #
diff --git a/lwlib/lwlib-Xaw.c b/lwlib/lwlib-Xaw.c
index f23576162c6..a700a5b168d 100644
--- a/lwlib/lwlib-Xaw.c
+++ b/lwlib/lwlib-Xaw.c
@@ -1,7 +1,7 @@
 /* The lwlib interface to Athena widgets.
 
 Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu>
-Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of the Lucid Widget Library.
 
diff --git a/lwlib/lwlib-Xlw.c b/lwlib/lwlib-Xlw.c
index 03f5809ca37..40e079e08c4 100644
--- a/lwlib/lwlib-Xlw.c
+++ b/lwlib/lwlib-Xlw.c
@@ -1,7 +1,7 @@
 /* The lwlib interface to "xlwmenu" menus.
 
 Copyright (C) 1992 Lucid, Inc.
-Copyright (C) 1994, 2000-2023 Free Software Foundation, Inc.
+Copyright (C) 1994, 2000-2024 Free Software Foundation, Inc.
 
 This file is part of the Lucid Widget Library.
 
diff --git a/lwlib/lwlib-Xm.c b/lwlib/lwlib-Xm.c
index 451b9a38746..dd3f63605a4 100644
--- a/lwlib/lwlib-Xm.c
+++ b/lwlib/lwlib-Xm.c
@@ -1,6 +1,6 @@
 /* The lwlib interface to Motif widgets.
 
-Copyright (C) 1994-1997, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1994-1997, 1999-2024 Free Software Foundation, Inc.
 Copyright (C) 1992 Lucid, Inc.
 
 This file is part of the Lucid Widget Library.
diff --git a/lwlib/lwlib-int.h b/lwlib/lwlib-int.h
index 09f674f75a8..897ecc16179 100644
--- a/lwlib/lwlib-int.h
+++ b/lwlib/lwlib-int.h
@@ -1,6 +1,6 @@
 /*
 Copyright (C) 1992 Lucid, Inc.
-Copyright (C) 2000-2023 Free Software Foundation, Inc.
+Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 This file is part of the Lucid Widget Library.
 
diff --git a/lwlib/lwlib-utils.c b/lwlib/lwlib-utils.c
index f7606fa0361..b9478a885ee 100644
--- a/lwlib/lwlib-utils.c
+++ b/lwlib/lwlib-utils.c
@@ -1,7 +1,7 @@
 /* Defines some widget utility functions.
 
 Copyright (C) 1992 Lucid, Inc.
-Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of the Lucid Widget Library.
 
diff --git a/lwlib/lwlib-widget.h b/lwlib/lwlib-widget.h
index 7c8af4286c1..3c7da530cb0 100644
--- a/lwlib/lwlib-widget.h
+++ b/lwlib/lwlib-widget.h
@@ -1,6 +1,6 @@
 /*
 Copyright (C) 1992, 1993 Lucid, Inc.
-Copyright (C) 1994, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1994, 1999-2024 Free Software Foundation, Inc.
 
 This file is part of the Lucid Widget Library.
 
diff --git a/lwlib/lwlib.c b/lwlib/lwlib.c
index cf519de8968..354faeed5b2 100644
--- a/lwlib/lwlib.c
+++ b/lwlib/lwlib.c
@@ -1,7 +1,7 @@
 /* A general interface to the widgets of different toolkits.
 
 Copyright (C) 1992, 1993 Lucid, Inc.
-Copyright (C) 1994-1996, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1994-1996, 1999-2024 Free Software Foundation, Inc.
 
 This file is part of the Lucid Widget Library.
 
diff --git a/lwlib/lwlib.h b/lwlib/lwlib.h
index 341d0a75428..ec990c98241 100644
--- a/lwlib/lwlib.h
+++ b/lwlib/lwlib.h
@@ -1,6 +1,6 @@
 /*
 Copyright (C) 1992, 1993 Lucid, Inc.
-Copyright (C) 1994, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1994, 1999-2024 Free Software Foundation, Inc.
 
 This file is part of the Lucid Widget Library.
 
diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c
index 84d41bd8e01..0f8f94b803c 100644
--- a/lwlib/xlwmenu.c
+++ b/lwlib/xlwmenu.c
@@ -1,7 +1,7 @@
 /* Implements a lightweight menubar widget.
 
 Copyright (C) 1992 Lucid, Inc.
-Copyright (C) 1994-1995, 1997, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1994-1995, 1997, 1999-2024 Free Software Foundation, Inc.
 
 This file is part of the Lucid Widget Library.
 
diff --git a/lwlib/xlwmenu.h b/lwlib/xlwmenu.h
index 6b59b945ce3..ce54ed04461 100644
--- a/lwlib/xlwmenu.h
+++ b/lwlib/xlwmenu.h
@@ -1,6 +1,6 @@
 /* Interface of a lightweight menubar widget.
 
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
 Copyright (C) 1992 Lucid, Inc.
 
 This file is part of the Lucid Widget Library.
diff --git a/lwlib/xlwmenuP.h b/lwlib/xlwmenuP.h
index a05d202fb7f..869c3502341 100644
--- a/lwlib/xlwmenuP.h
+++ b/lwlib/xlwmenuP.h
@@ -1,6 +1,6 @@
 /* Internals of a lightweight menubar widget.
 
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
 Copyright (C) 1992 Lucid, Inc.
 
 This file is part of the Lucid Widget Library.
diff --git a/m4/00gnulib.m4 b/m4/00gnulib.m4
index 7fe03e0b9c0..99c99d1b0fb 100644
--- a/m4/00gnulib.m4
+++ b/m4/00gnulib.m4
@@ -1,5 +1,5 @@
-# 00gnulib.m4 serial 8
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+# 00gnulib.m4 serial 9
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
@@ -49,14 +49,14 @@ dnl AC_REQUIRE([gl_COMPILER_CLANG])
     [if test $gl_cv_compiler_clang = yes; then
        dnl Test whether the compiler supports the option
        dnl '-Werror=implicit-function-declaration'.
-       save_ac_compile="$ac_compile"
+       saved_ac_compile="$ac_compile"
        ac_compile="$ac_compile -Werror=implicit-function-declaration"
        dnl Use _AC_COMPILE_IFELSE instead of AC_COMPILE_IFELSE, to avoid a
        dnl warning "AC_COMPILE_IFELSE was called before 
AC_USE_SYSTEM_EXTENSIONS".
        _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])],
          
[gl_cv_compiler_check_decl_option='-Werror=implicit-function-declaration'],
          [gl_cv_compiler_check_decl_option=none])
-       ac_compile="$save_ac_compile"
+       ac_compile="$saved_ac_compile"
      else
        gl_cv_compiler_check_decl_option=none
      fi
@@ -71,11 +71,11 @@ dnl Redefine _AC_CHECK_DECL_BODY so that it references 
ac_compile_for_check_decl
 dnl instead of ac_compile.  If, for whatever reason, the override of AC_PROG_CC
 dnl in zzgnulib.m4 is inactive, use the original ac_compile.
 m4_define([_AC_CHECK_DECL_BODY],
-[  ac_save_ac_compile="$ac_compile"
+[  ac_saved_ac_compile="$ac_compile"
   if test -n "$ac_compile_for_check_decl"; then
     ac_compile="$ac_compile_for_check_decl"
   fi]
-m4_defn([_AC_CHECK_DECL_BODY])[  ac_compile="$ac_save_ac_compile"
+m4_defn([_AC_CHECK_DECL_BODY])[  ac_compile="$ac_saved_ac_compile"
 ])
 
 # gl_00GNULIB
diff --git a/m4/__inline.m4 b/m4/__inline.m4
index acf8668bc58..992e16f4ea7 100644
--- a/m4/__inline.m4
+++ b/m4/__inline.m4
@@ -1,5 +1,5 @@
 # Test for __inline keyword
-dnl Copyright 2017-2023 Free Software Foundation, Inc.
+dnl Copyright 2017-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/absolute-header.m4 b/m4/absolute-header.m4
index e7947648881..0e9f9ba763a 100644
--- a/m4/absolute-header.m4
+++ b/m4/absolute-header.m4
@@ -1,5 +1,5 @@
-# absolute-header.m4 serial 17
-dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
+# absolute-header.m4 serial 18
+dnl Copyright (C) 2006-2024 Free Software Foundation, Inc.
 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.
@@ -66,7 +66,7 @@ AC_DEFUN([gl_ABSOLUTE_HEADER_ONE],
   esac
 changequote(,)
   case "$host_os" in
-    mingw*)
+    mingw* | windows*)
       dnl For the sake of native Windows compilers (excluding gcc),
       dnl treat backslash as a directory separator, like /.
       dnl Actually, these compilers use a double-backslash as
diff --git a/m4/acl.m4 b/m4/acl.m4
index 38b1dc66212..2050d108b0c 100644
--- a/m4/acl.m4
+++ b/m4/acl.m4
@@ -1,7 +1,7 @@
 # acl.m4 - check for access control list (ACL) primitives
-# serial 29
+# serial 30
 
-# Copyright (C) 2002, 2004-2023 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2004-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -27,7 +27,7 @@ AC_DEFUN_ONCE([gl_FUNC_ACL],
     dnl On all platforms, the ACL related API is declared in <sys/acl.h>.
     AC_CHECK_HEADERS([sys/acl.h])
     if test $ac_cv_header_sys_acl_h = yes; then
-      ac_save_LIBS=$LIBS
+      gl_saved_LIBS=$LIBS
 
       dnl Test for POSIX-draft-like API (GNU/Linux, FreeBSD, Mac OS X,
       dnl IRIX, Tru64, Cygwin >= 2.5).
@@ -129,7 +129,7 @@ int type = ACL_TYPE_EXTENDED;]])],
         fi
       fi
 
-      LIBS=$ac_save_LIBS
+      LIBS=$gl_saved_LIBS
     fi
 
     if test "$enable_acl$use_acl" = yes0; then
diff --git a/m4/alloca.m4 b/m4/alloca.m4
index c685fac918a..90960215382 100644
--- a/m4/alloca.m4
+++ b/m4/alloca.m4
@@ -1,5 +1,5 @@
 # alloca.m4 serial 21
-dnl Copyright (C) 2002-2004, 2006-2007, 2009-2023 Free Software Foundation,
+dnl Copyright (C) 2002-2004, 2006-2007, 2009-2024 Free Software Foundation,
 dnl Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
diff --git a/m4/assert_h.m4 b/m4/assert_h.m4
index d255855d313..d3d4c42519f 100644
--- a/m4/assert_h.m4
+++ b/m4/assert_h.m4
@@ -1,5 +1,5 @@
 # assert-h.m4
-dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2011-2024 Free Software Foundation, Inc.
 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.
@@ -9,10 +9,10 @@ dnl From Paul Eggert.
 AC_DEFUN([gl_ASSERT_H],
 [
   AC_CACHE_CHECK([for static_assert], [gl_cv_static_assert],
-    [gl_save_CFLAGS=$CFLAGS
+    [gl_saved_CFLAGS=$CFLAGS
      for gl_working in "yes, a keyword" "yes, an <assert.h> macro"; do
       AS_CASE([$gl_working],
-        [*assert.h*], [CFLAGS="$gl_save_CFLAGS -DINCLUDE_ASSERT_H"])
+        [*assert.h*], [CFLAGS="$gl_saved_CFLAGS -DINCLUDE_ASSERT_H"])
 
       AC_COMPILE_IFELSE(
        [AC_LANG_PROGRAM(
@@ -32,7 +32,7 @@ AC_DEFUN([gl_ASSERT_H],
           ]])],
        [gl_cv_static_assert=$gl_working],
        [gl_cv_static_assert=no])
-      CFLAGS=$gl_save_CFLAGS
+      CFLAGS=$gl_saved_CFLAGS
       test "$gl_cv_static_assert" != no && break
      done])
 
diff --git a/m4/builtin-expect.m4 b/m4/builtin-expect.m4
index 531ed48af7f..8faffc50354 100644
--- a/m4/builtin-expect.m4
+++ b/m4/builtin-expect.m4
@@ -1,6 +1,6 @@
 dnl Check for __builtin_expect.
 
-dnl Copyright 2016-2023 Free Software Foundation, Inc.
+dnl Copyright 2016-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/byteswap.m4 b/m4/byteswap.m4
index 8058d178bce..5493d901916 100644
--- a/m4/byteswap.m4
+++ b/m4/byteswap.m4
@@ -1,5 +1,5 @@
 # byteswap.m4 serial 5
-dnl Copyright (C) 2005, 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005, 2007, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/c-bool.m4 b/m4/c-bool.m4
index f614371bb28..44fba3c012f 100644
--- a/m4/c-bool.m4
+++ b/m4/c-bool.m4
@@ -1,6 +1,6 @@
 # Check for bool that conforms to C2023.
 
-dnl Copyright 2022-2023 Free Software Foundation, Inc.
+dnl Copyright 2022-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/canonicalize.m4 b/m4/canonicalize.m4
index d319645fd3f..05dc6dd264d 100644
--- a/m4/canonicalize.m4
+++ b/m4/canonicalize.m4
@@ -1,6 +1,6 @@
-# canonicalize.m4 serial 38
+# canonicalize.m4 serial 39
 
-dnl Copyright (C) 2003-2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003-2007, 2009-2024 Free Software Foundation, Inc.
 
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -66,8 +66,8 @@ AC_DEFUN([gl_CANONICALIZE_LGPL_SEPARATE],
   dnl available through the linker option '-loldnames'.
   AC_REQUIRE([AC_CANONICAL_HOST])
   case "$host_os" in
-    mingw*) ;;
-    *)      AC_CHECK_FUNCS([getcwd]) ;;
+    mingw* | windows*) ;;
+    *) AC_CHECK_FUNCS([getcwd]) ;;
   esac
 
   AC_REQUIRE([gl_DOUBLE_SLASH_ROOT])
@@ -158,16 +158,16 @@ AC_DEFUN([gl_FUNC_REALPATH_WORKS],
       esac
      ],
      [case "$host_os" in
-                       # Guess yes on glibc systems.
-        *-gnu* | gnu*) gl_cv_func_realpath_works="guessing yes" ;;
-                       # Guess 'nearly' on musl systems.
-        *-musl*)       gl_cv_func_realpath_works="guessing nearly" ;;
-                       # Guess no on Cygwin.
-        cygwin*)       gl_cv_func_realpath_works="guessing no" ;;
-                       # Guess no on native Windows.
-        mingw*)        gl_cv_func_realpath_works="guessing no" ;;
-                       # If we don't know, obey --enable-cross-guesses.
-        *)             gl_cv_func_realpath_works="$gl_cross_guess_normal" ;;
+                           # Guess yes on glibc systems.
+        *-gnu* | gnu*)     gl_cv_func_realpath_works="guessing yes" ;;
+                           # Guess 'nearly' on musl systems.
+        *-musl*)           gl_cv_func_realpath_works="guessing nearly" ;;
+                           # Guess no on Cygwin.
+        cygwin*)           gl_cv_func_realpath_works="guessing no" ;;
+                           # Guess no on native Windows.
+        mingw* | windows*) gl_cv_func_realpath_works="guessing no" ;;
+                           # If we don't know, obey --enable-cross-guesses.
+        *)                 gl_cv_func_realpath_works="$gl_cross_guess_normal" 
;;
       esac
      ])
     rm -rf conftest.a conftest.l conftest.d
diff --git a/m4/clock_time.m4 b/m4/clock_time.m4
index 28534db1c76..c016575c8ea 100644
--- a/m4/clock_time.m4
+++ b/m4/clock_time.m4
@@ -1,5 +1,5 @@
-# clock_time.m4 serial 13
-dnl Copyright (C) 2002-2006, 2009-2023 Free Software Foundation, Inc.
+# clock_time.m4 serial 14
+dnl Copyright (C) 2002-2006, 2009-2024 Free Software Foundation, Inc.
 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.
@@ -32,7 +32,7 @@ AC_DEFUN([gl_CLOCK_TIME],
   CLOCK_TIME_LIB=
   AC_SUBST([CLOCK_TIME_LIB])
   case "$host_os" in
-    mingw*)
+    mingw* | windows*)
       ac_cv_func_clock_getres=no
       ac_cv_func_clock_gettime=no
       ac_cv_func_clock_settime=no
diff --git a/m4/codeset.m4 b/m4/codeset.m4
index 5804f472e9a..94dccce7775 100644
--- a/m4/codeset.m4
+++ b/m4/codeset.m4
@@ -1,5 +1,5 @@
 # codeset.m4 serial 5 (gettext-0.18.2)
-dnl Copyright (C) 2000-2002, 2006, 2008-2014, 2016, 2019-2023 Free Software
+dnl Copyright (C) 2000-2002, 2006, 2008-2014, 2016, 2019-2024 Free Software
 dnl Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
diff --git a/m4/copy-file-range.m4 b/m4/copy-file-range.m4
index fa6ab341091..443e598ba55 100644
--- a/m4/copy-file-range.m4
+++ b/m4/copy-file-range.m4
@@ -1,5 +1,5 @@
-# copy-file-range.m4
-dnl Copyright 2019-2023 Free Software Foundation, Inc.
+# copy-file-range.m4 serial 5
+dnl Copyright 2019-2024 Free Software Foundation, Inc.
 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.
@@ -17,22 +17,33 @@ AC_DEFUN([gl_FUNC_COPY_FILE_RANGE],
   dnl Programs that use copy_file_range must fall back on read+write
   dnl anyway, and there's little point to substituting the Gnulib stub
   dnl for a glibc stub.
-  AC_CACHE_CHECK([for copy_file_range], [gl_cv_func_copy_file_range],
-    [AC_LINK_IFELSE(
-       [AC_LANG_PROGRAM(
-          [[#include <unistd.h>
-          ]],
-          [[ssize_t (*func) (int, off_t *, int, off_t *, size_t, unsigned)
-              = copy_file_range;
-            return func (0, 0, 0, 0, 0, 0) & 127;
-          ]])
-       ],
-       [gl_cv_func_copy_file_range=yes],
-       [gl_cv_func_copy_file_range=no])
-    ])
-
+  case "$host_os" in
+    *-gnu* | gnu*)
+      AC_CACHE_CHECK([for copy_file_range], [gl_cv_func_copy_file_range],
+        [AC_LINK_IFELSE(
+           [AC_LANG_PROGRAM(
+              [[#include <unistd.h>
+              ]],
+              [[ssize_t (*func) (int, off_t *, int, off_t *, size_t, unsigned)
+                  = copy_file_range;
+                return func (0, 0, 0, 0, 0, 0) & 127;
+              ]])
+           ],
+           [gl_cv_func_copy_file_range=yes],
+           [gl_cv_func_copy_file_range=no])
+        ])
+      gl_cv_onwards_func_copy_file_range="$gl_cv_func_copy_file_range"
+      ;;
+    *)
+      gl_CHECK_FUNCS_ANDROID([copy_file_range], [[#include <unistd.h>]])
+      gl_cv_func_copy_file_range="$ac_cv_func_copy_file_range"
+      ;;
+  esac
   if test "$gl_cv_func_copy_file_range" != yes; then
     HAVE_COPY_FILE_RANGE=0
+    case "$gl_cv_onwards_func_copy_file_range" in
+      future*) REPLACE_COPY_FILE_RANGE=1 ;;
+    esac
   else
     AC_DEFINE([HAVE_COPY_FILE_RANGE], 1,
       [Define to 1 if the function copy_file_range exists.])
diff --git a/m4/d-type.m4 b/m4/d-type.m4
index 3f63bbe78ee..b06bca5a7dc 100644
--- a/m4/d-type.m4
+++ b/m4/d-type.m4
@@ -5,7 +5,7 @@ dnl
 dnl Check whether struct dirent has a member named d_type.
 dnl
 
-# Copyright (C) 1997, 1999-2004, 2006, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 1997, 1999-2004, 2006, 2009-2024 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
diff --git a/m4/dirent_h.m4 b/m4/dirent_h.m4
index b6c189c0d9f..3e3d967f499 100644
--- a/m4/dirent_h.m4
+++ b/m4/dirent_h.m4
@@ -1,5 +1,5 @@
-# dirent_h.m4 serial 20
-dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
+# dirent_h.m4 serial 22
+dnl Copyright (C) 2008-2024 Free Software Foundation, Inc.
 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.
@@ -32,14 +32,13 @@ AC_DEFUN_ONCE([gl_DIRENT_H],
 dnl Determine whether <dirent.h> needs to override the DIR type.
 AC_DEFUN_ONCE([gl_DIRENT_DIR],
 [
-  dnl Set DIR_HAS_FD_MEMBER if dirfd() works, i.e. not always returns -1,
-  dnl or has the __KLIBC__ workaround as in lib/dirfd.c.
+  dnl Set DIR_HAS_FD_MEMBER if dirfd() works, i.e. not always returns -1.
   dnl We could use the findings from gl_FUNC_DIRFD and gl_PREREQ_DIRFD, but
   dnl it's simpler since we know the affected platforms.
   AC_REQUIRE([AC_CANONICAL_HOST])
   case "$host_os" in
-    mingw*) DIR_HAS_FD_MEMBER=0 ;;
-    *)      DIR_HAS_FD_MEMBER=1 ;;
+    mingw* | windows* | os2*) DIR_HAS_FD_MEMBER=0 ;;
+    *)                        DIR_HAS_FD_MEMBER=1 ;;
   esac
   AC_SUBST([DIR_HAS_FD_MEMBER])
 ])
diff --git a/m4/dirfd.m4 b/m4/dirfd.m4
index 7968b1287ce..e58582e6145 100644
--- a/m4/dirfd.m4
+++ b/m4/dirfd.m4
@@ -1,8 +1,8 @@
-# serial 28   -*- Autoconf -*-
+# serial 30   -*- Autoconf -*-
 
 dnl Find out how to get the file descriptor associated with an open DIR*.
 
-# Copyright (C) 2001-2006, 2008-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2006, 2008-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -40,15 +40,12 @@ AC_DEFUN([gl_FUNC_DIRFD],
     HAVE_DIRFD=0
   else
     HAVE_DIRFD=1
-    dnl Replace dirfd() on native Windows, to support fdopendir().
+    dnl Replace dirfd() on native Windows and OS/2 kLIBC,
+    dnl to support fdopendir().
     AC_REQUIRE([gl_DIRENT_DIR])
     if test $DIR_HAS_FD_MEMBER = 0; then
       REPLACE_DIRFD=1
     fi
-    dnl OS/2 kLIBC dirfd() does not work.
-    case "$host_os" in
-      os2*) REPLACE_DIRFD=1 ;;
-    esac
   fi
 ])
 
@@ -58,7 +55,7 @@ AC_DEFUN([gl_PREREQ_DIRFD],
   AC_CACHE_CHECK([how to get the file descriptor associated with an open DIR*],
                  [gl_cv_sys_dir_fd_member_name],
     [
-      dirfd_save_CFLAGS=$CFLAGS
+      gl_saved_CFLAGS=$CFLAGS
       for ac_expr in d_fd dd_fd; do
 
         CFLAGS="$CFLAGS -DDIR_FD_MEMBER_NAME=$ac_expr"
@@ -68,7 +65,7 @@ AC_DEFUN([gl_PREREQ_DIRFD],
           [[DIR *dir_p = opendir("."); (void) dir_p->DIR_FD_MEMBER_NAME;]])],
           [dir_fd_found=yes]
         )
-        CFLAGS=$dirfd_save_CFLAGS
+        CFLAGS=$gl_saved_CFLAGS
         test "$dir_fd_found" = yes && break
       done
       test "$dir_fd_found" = yes || ac_expr=no_such_member
diff --git a/m4/double-slash-root.m4 b/m4/double-slash-root.m4
index 1776e5eb75d..00f23a70b0c 100644
--- a/m4/double-slash-root.m4
+++ b/m4/double-slash-root.m4
@@ -1,5 +1,5 @@
 # double-slash-root.m4 serial 4   -*- Autoconf -*-
-dnl Copyright (C) 2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006, 2008-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/dup2.m4 b/m4/dup2.m4
index e1cc73e18db..f6759b647a6 100644
--- a/m4/dup2.m4
+++ b/m4/dup2.m4
@@ -1,5 +1,5 @@
-#serial 27
-dnl Copyright (C) 2002, 2005, 2007, 2009-2023 Free Software Foundation, Inc.
+#serial 28
+dnl Copyright (C) 2002, 2005, 2007, 2009-2024 Free Software Foundation, Inc.
 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.
@@ -67,7 +67,7 @@ AC_DEFUN([gl_FUNC_DUP2],
       ],
       [gl_cv_func_dup2_works=yes], [gl_cv_func_dup2_works=no],
       [case "$host_os" in
-         mingw*) # on this platform, dup2 always returns 0 for success
+         mingw* | windows*) # on this platform, dup2 always returns 0 for 
success
            gl_cv_func_dup2_works="guessing no" ;;
          cygwin*) # on cygwin 1.5.x, dup2(1,1) returns 0
            gl_cv_func_dup2_works="guessing no" ;;
diff --git a/m4/eealloc.m4 b/m4/eealloc.m4
index cb3e08fe53a..d8862a1e0f3 100644
--- a/m4/eealloc.m4
+++ b/m4/eealloc.m4
@@ -1,5 +1,5 @@
 # eealloc.m4 serial 3
-dnl Copyright (C) 2003, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/environ.m4 b/m4/environ.m4
index 741dfc56a1e..5b9e06b0088 100644
--- a/m4/environ.m4
+++ b/m4/environ.m4
@@ -1,5 +1,5 @@
 # environ.m4 serial 8
-dnl Copyright (C) 2001-2004, 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2001-2004, 2006-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/errno_h.m4 b/m4/errno_h.m4
index 4c70d225289..8900d6c7257 100644
--- a/m4/errno_h.m4
+++ b/m4/errno_h.m4
@@ -1,5 +1,5 @@
 # errno_h.m4 serial 14
-dnl Copyright (C) 2004, 2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2004, 2006, 2008-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/euidaccess.m4 b/m4/euidaccess.m4
index 7429779c152..e3d828f6ca5 100644
--- a/m4/euidaccess.m4
+++ b/m4/euidaccess.m4
@@ -1,5 +1,5 @@
 # euidaccess.m4 serial 17
-dnl Copyright (C) 2002-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/execinfo.m4 b/m4/execinfo.m4
index 269e697a45a..a76c33525e6 100644
--- a/m4/execinfo.m4
+++ b/m4/execinfo.m4
@@ -1,6 +1,6 @@
 # Check for GNU-style execinfo.h.
 
-dnl Copyright 2012-2023 Free Software Foundation, Inc.
+dnl Copyright 2012-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/explicit_bzero.m4 b/m4/explicit_bzero.m4
index aa74bea3d26..59576b7e018 100644
--- a/m4/explicit_bzero.m4
+++ b/m4/explicit_bzero.m4
@@ -1,4 +1,4 @@
-dnl Copyright 2017-2023 Free Software Foundation, Inc.
+dnl Copyright 2017-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/extensions.m4 b/m4/extensions.m4
index 5336b8daf7e..6fc2e300e0a 100644
--- a/m4/extensions.m4
+++ b/m4/extensions.m4
@@ -1,7 +1,7 @@
 # serial 23  -*- Autoconf -*-
 # Enable extensions on systems that normally disable them.
 
-# Copyright (C) 2003, 2006-2023 Free Software Foundation, Inc.
+# Copyright (C) 2003, 2006-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
diff --git a/m4/extern-inline.m4 b/m4/extern-inline.m4
index f9894d7fe5c..680250ec774 100644
--- a/m4/extern-inline.m4
+++ b/m4/extern-inline.m4
@@ -1,6 +1,6 @@
 dnl 'extern inline' a la ISO C99.
 
-dnl Copyright 2012-2023 Free Software Foundation, Inc.
+dnl Copyright 2012-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/faccessat.m4 b/m4/faccessat.m4
index a858bfee33d..b8c058cef28 100644
--- a/m4/faccessat.m4
+++ b/m4/faccessat.m4
@@ -1,7 +1,7 @@
 # serial 12
 # See if we need to provide faccessat replacement.
 
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/fchmodat.m4 b/m4/fchmodat.m4
index 5356da40bae..9750572a5a3 100644
--- a/m4/fchmodat.m4
+++ b/m4/fchmodat.m4
@@ -1,5 +1,5 @@
 # fchmodat.m4 serial 8
-dnl Copyright (C) 2004-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2004-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/fcntl.m4 b/m4/fcntl.m4
index 524a99af80a..02b93f8357c 100644
--- a/m4/fcntl.m4
+++ b/m4/fcntl.m4
@@ -1,5 +1,5 @@
 # fcntl.m4 serial 11
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/fcntl_h.m4 b/m4/fcntl_h.m4
index 68f4e648021..ba4eb4494db 100644
--- a/m4/fcntl_h.m4
+++ b/m4/fcntl_h.m4
@@ -1,6 +1,6 @@
 # serial 20
 # Configure fcntl.h.
-dnl Copyright (C) 2006-2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006-2007, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/fdopendir.m4 b/m4/fdopendir.m4
index dfcc46c03e2..bf361ff154c 100644
--- a/m4/fdopendir.m4
+++ b/m4/fdopendir.m4
@@ -1,7 +1,7 @@
 # serial 15
 # See if we need to provide fdopendir.
 
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/filemode.m4 b/m4/filemode.m4
index 3cafc5cd1e1..b72317281b3 100644
--- a/m4/filemode.m4
+++ b/m4/filemode.m4
@@ -1,5 +1,5 @@
 # filemode.m4 serial 9
-dnl Copyright (C) 2002, 2005-2006, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002, 2005-2006, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/flexmember.m4 b/m4/flexmember.m4
index 13f7e870d31..9df6c03cd3b 100644
--- a/m4/flexmember.m4
+++ b/m4/flexmember.m4
@@ -1,7 +1,7 @@
 # serial 5
 # Check for flexible array member support.
 
-# Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2006, 2009-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
diff --git a/m4/fpending.m4 b/m4/fpending.m4
index 6991f81066d..05064b851ec 100644
--- a/m4/fpending.m4
+++ b/m4/fpending.m4
@@ -1,6 +1,6 @@
 # serial 23
 
-# Copyright (C) 2000-2001, 2004-2023 Free Software Foundation, Inc.
+# Copyright (C) 2000-2001, 2004-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
diff --git a/m4/fpieee.m4 b/m4/fpieee.m4
index 706b33141d3..239cf4a7e2d 100644
--- a/m4/fpieee.m4
+++ b/m4/fpieee.m4
@@ -1,5 +1,5 @@
 # fpieee.m4 serial 2  -*- coding: utf-8 -*-
-dnl Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/free.m4 b/m4/free.m4
index 0389dea3f49..4f6dc2e256d 100644
--- a/m4/free.m4
+++ b/m4/free.m4
@@ -1,5 +1,5 @@
 # free.m4 serial 6
-# Copyright (C) 2003-2005, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2003-2005, 2009-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
diff --git a/m4/fstatat.m4 b/m4/fstatat.m4
index 083076911ff..c22569b7961 100644
--- a/m4/fstatat.m4
+++ b/m4/fstatat.m4
@@ -1,5 +1,5 @@
-# fstatat.m4 serial 4
-dnl Copyright (C) 2004-2023 Free Software Foundation, Inc.
+# fstatat.m4 serial 5
+dnl Copyright (C) 2004-2024 Free Software Foundation, Inc.
 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.
@@ -50,7 +50,7 @@ AC_DEFUN([gl_FUNC_FSTATAT],
     esac
 
     case $host_os in
-      solaris*)
+      darwin* | solaris*)
         REPLACE_FSTATAT=1 ;;
     esac
 
diff --git a/m4/fsusage.m4 b/m4/fsusage.m4
index 724a863ac30..31d424c857d 100644
--- a/m4/fsusage.m4
+++ b/m4/fsusage.m4
@@ -1,7 +1,7 @@
 # serial 35
 # Obtaining file system usage information.
 
-# Copyright (C) 1997-1998, 2000-2001, 2003-2023 Free Software Foundation, Inc.
+# Copyright (C) 1997-1998, 2000-2001, 2003-2024 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
diff --git a/m4/fsync.m4 b/m4/fsync.m4
index 857e495506f..08e3db8931e 100644
--- a/m4/fsync.m4
+++ b/m4/fsync.m4
@@ -1,5 +1,5 @@
 # fsync.m4 serial 2
-dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2008-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/futimens.m4 b/m4/futimens.m4
index dc0b21b9d51..ac961e7bde5 100644
--- a/m4/futimens.m4
+++ b/m4/futimens.m4
@@ -1,7 +1,7 @@
 # serial 11
 # See if we need to provide futimens replacement.
 
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/getdelim.m4 b/m4/getdelim.m4
index 60555b9718b..0dbd8bc6f8b 100644
--- a/m4/getdelim.m4
+++ b/m4/getdelim.m4
@@ -1,6 +1,6 @@
 # getdelim.m4 serial 19
 
-dnl Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005-2007, 2009-2024 Free Software Foundation, Inc.
 dnl
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
diff --git a/m4/getdtablesize.m4 b/m4/getdtablesize.m4
index 8bcda9053b6..3b89456baf9 100644
--- a/m4/getdtablesize.m4
+++ b/m4/getdtablesize.m4
@@ -1,5 +1,5 @@
 # getdtablesize.m4 serial 8
-dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2008-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/getgroups.m4 b/m4/getgroups.m4
index 241fec88e3c..f6e0cbd3fce 100644
--- a/m4/getgroups.m4
+++ b/m4/getgroups.m4
@@ -1,9 +1,9 @@
-# serial 24
+# serial 25
 
 dnl From Jim Meyering.
 dnl A wrapper around AC_FUNC_GETGROUPS.
 
-# Copyright (C) 1996-1997, 1999-2004, 2008-2023 Free Software Foundation, Inc.
+# Copyright (C) 1996-1997, 1999-2004, 2008-2024 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -20,7 +20,7 @@ AC_DEFUN([AC_FUNC_GETGROUPS],
 
   # If we don't yet have getgroups, see if it's in -lbsd.
   # This is reported to be necessary on an ITOS 3000WS running SEIUX 3.1.
-  ac_save_LIBS=$LIBS
+  gl_saved_LIBS=$LIBS
   if test $ac_cv_func_getgroups = no; then
     AC_CHECK_LIB(bsd, getgroups, [GETGROUPS_LIB=-lbsd])
   fi
@@ -56,7 +56,7 @@ AC_DEFUN([AC_FUNC_GETGROUPS],
         [Define to 1 if your system has a working `getgroups' function.])
       ;;
   esac
-  LIBS=$ac_save_LIBS
+  LIBS=$gl_saved_LIBS
 ])# AC_FUNC_GETGROUPS
 
 AC_DEFUN([gl_FUNC_GETGROUPS],
diff --git a/m4/getline.m4 b/m4/getline.m4
index 83e7e9315f6..1a7e89034bc 100644
--- a/m4/getline.m4
+++ b/m4/getline.m4
@@ -1,6 +1,6 @@
 # getline.m4 serial 33
 
-dnl Copyright (C) 1998-2003, 2005-2007, 2009-2023 Free Software Foundation,
+dnl Copyright (C) 1998-2003, 2005-2007, 2009-2024 Free Software Foundation,
 dnl Inc.
 dnl
 dnl This file is free software; the Free Software Foundation
diff --git a/m4/getloadavg.m4 b/m4/getloadavg.m4
index ee83b32f1e0..9d0236f77fe 100644
--- a/m4/getloadavg.m4
+++ b/m4/getloadavg.m4
@@ -1,13 +1,13 @@
 # Check for getloadavg.
 
-# Copyright (C) 1992-1996, 1999-2000, 2002-2003, 2006, 2008-2023 Free Software
+# Copyright (C) 1992-1996, 1999-2000, 2002-2003, 2006, 2008-2024 Free Software
 # Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-#serial 12
+#serial 13
 
 # Autoconf defines AC_FUNC_GETLOADAVG, but that is obsolescent.
 # New applications should use gl_GETLOADAVG instead.
@@ -20,7 +20,7 @@ AC_DEFUN([gl_GETLOADAVG],
 # Persuade glibc <stdlib.h> to declare getloadavg().
 AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
 
-gl_save_LIBS=$LIBS
+gl_saved_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.
@@ -81,12 +81,12 @@ if test $ac_cv_func_getloadavg != yes; then
    fi
 fi
 
-if test "x$gl_save_LIBS" = x; then
+if test "x$gl_saved_LIBS" = x; then
   GETLOADAVG_LIBS=$LIBS
 else
-  GETLOADAVG_LIBS=`echo "$LIBS" | sed "s!$gl_save_LIBS!!"`
+  GETLOADAVG_LIBS=`echo "$LIBS" | sed "s!$gl_saved_LIBS!!"`
 fi
-LIBS=$gl_save_LIBS
+LIBS=$gl_saved_LIBS
 
 AC_SUBST([GETLOADAVG_LIBS])dnl
 
diff --git a/m4/getopt.m4 b/m4/getopt.m4
index 7981a09552b..be812d8459b 100644
--- a/m4/getopt.m4
+++ b/m4/getopt.m4
@@ -1,5 +1,5 @@
-# getopt.m4 serial 48
-dnl Copyright (C) 2002-2006, 2008-2023 Free Software Foundation, Inc.
+# getopt.m4 serial 49
+dnl Copyright (C) 2002-2006, 2008-2024 Free Software Foundation, Inc.
 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.
@@ -197,8 +197,8 @@ main ()
           fi
         else
           case "$host_os" in
-            darwin* | aix* | mingw*) gl_cv_func_getopt_posix="guessing no";;
-            *)                       gl_cv_func_getopt_posix="guessing yes";;
+            darwin* | aix* | mingw* | windows*) 
gl_cv_func_getopt_posix="guessing no";;
+            *)                                  
gl_cv_func_getopt_posix="guessing yes";;
           esac
         fi
       ])
diff --git a/m4/getrandom.m4 b/m4/getrandom.m4
index 7b7f9ce2ee8..55be445c31a 100644
--- a/m4/getrandom.m4
+++ b/m4/getrandom.m4
@@ -1,5 +1,5 @@
-# getrandom.m4 serial 11
-dnl Copyright 2020-2023 Free Software Foundation, Inc.
+# getrandom.m4 serial 13
+dnl Copyright 2020-2024 Free Software Foundation, Inc.
 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.
@@ -9,6 +9,8 @@ dnl Written by Paul Eggert.
 AC_DEFUN([gl_FUNC_GETRANDOM],
 [
   AC_REQUIRE([gl_SYS_RANDOM_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
   gl_CHECK_FUNCS_ANDROID([getrandom],
     [[/* Additional includes are needed before <sys/random.h> on uClibc
          and Mac OS X.  */
@@ -45,7 +47,7 @@ AC_DEFUN([gl_FUNC_GETRANDOM],
   fi
 
   case "$host_os" in
-    mingw*)
+    mingw* | windows*)
       AC_CHECK_HEADERS([bcrypt.h], [], [],
         [[#include <windows.h>
         ]])
diff --git a/m4/gettime.m4 b/m4/gettime.m4
index ec1f97ee0d5..1ec018d5154 100644
--- a/m4/gettime.m4
+++ b/m4/gettime.m4
@@ -1,5 +1,5 @@
-# gettime.m4 serial 14
-dnl Copyright (C) 2002, 2004-2006, 2009-2023 Free Software Foundation, Inc.
+# gettime.m4 serial 15
+dnl Copyright (C) 2002, 2004-2006, 2009-2024 Free Software Foundation, Inc.
 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.
@@ -64,5 +64,5 @@ AC_DEFUN([gl_GETTIME_RES],
   dnl Prerequisites of lib/gettime-res.c.
   AC_REQUIRE([gl_CLOCK_TIME])
   AC_REQUIRE([gl_TIMESPEC])
-  AC_CHECK_FUNCS_ONCE([timespec_getres])
+  gl_CHECK_FUNCS_ANDROID([timespec_getres], [[#include <time.h>]])
 ])
diff --git a/m4/gettimeofday.m4 b/m4/gettimeofday.m4
index 5051d61cc87..35269914ced 100644
--- a/m4/gettimeofday.m4
+++ b/m4/gettimeofday.m4
@@ -1,6 +1,6 @@
-# serial 29
+# serial 30
 
-# Copyright (C) 2001-2003, 2005, 2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2003, 2005, 2007, 2009-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -57,7 +57,7 @@ int gettimeofday (struct timeval *restrict, struct timezone 
*restrict);
     dnl On mingw, the original gettimeofday has only a precision of 15.6
     dnl milliseconds. So override it.
     case "$host_os" in
-      mingw*) REPLACE_GETTIMEOFDAY=1 ;;
+      mingw* | windows*) REPLACE_GETTIMEOFDAY=1 ;;
     esac
   fi
   AC_DEFINE_UNQUOTED([GETTIMEOFDAY_TIMEZONE], [$gl_gettimeofday_timezone],
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
index 2426eb63985..00691c0d6c3 100644
--- a/m4/gnulib-common.m4
+++ b/m4/gnulib-common.m4
@@ -1,5 +1,5 @@
-# gnulib-common.m4 serial 87
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+# gnulib-common.m4 serial 91
+dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
 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.
@@ -79,7 +79,7 @@ AC_DEFUN([gl_COMMON_BODY], [
 #if (defined __has_attribute \
      && (!defined __clang_minor__ \
          || (defined __apple_build_version__ \
-             ? 6000000 <= __apple_build_version__ \
+             ? 7000000 <= __apple_build_version__ \
              : 5 <= __clang_major__)))
 # define _GL_HAS_ATTRIBUTE(attr) __has_attribute (__##attr##__)
 #else
@@ -114,10 +114,14 @@ AC_DEFUN([gl_COMMON_BODY], [
 # define _GL_ATTR_warn_unused_result _GL_GNUC_PREREQ (3, 4)
 #endif
 
-/* Disable GCC -Wpedantic if using __has_c_attribute and this is not C23+.  */
-#if (defined __has_c_attribute && _GL_GNUC_PREREQ (4, 6) \
-     && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) <= 201710)
-# pragma GCC diagnostic ignored "-Wpedantic"
+/* Use __has_c_attribute if available.  However, do not use with
+   pre-C23 GCC, which can issue false positives if -Wpedantic.  */
+#if (defined __has_c_attribute \
+     && ! (_GL_GNUC_PREREQ (4, 6) \
+           && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) <= 201710))
+# define _GL_HAVE___HAS_C_ATTRIBUTE 1
+#else
+# define _GL_HAVE___HAS_C_ATTRIBUTE 0
 #endif
 
 /* Define if, in a function declaration, the attributes in bracket syntax
@@ -242,7 +246,7 @@ AC_DEFUN([gl_COMMON_BODY], [
    in C++ also: namespace, class, template specialization.  */
 #ifndef _GL_ATTRIBUTE_DEPRECATED
 # ifndef _GL_BRACKET_BEFORE_ATTRIBUTE
-#  ifdef __has_c_attribute
+#  if _GL_HAVE___HAS_C_ATTRIBUTE
 #   if __has_c_attribute (__deprecated__)
 #    define _GL_ATTRIBUTE_DEPRECATED [[__deprecated__]]
 #   endif
@@ -291,7 +295,7 @@ AC_DEFUN([gl_COMMON_BODY], [
 /* Applies to: Empty statement (;), inside a 'switch' statement.  */
 /* Always expands to something.  */
 #ifndef _GL_ATTRIBUTE_FALLTHROUGH
-# ifdef __has_c_attribute
+# if _GL_HAVE___HAS_C_ATTRIBUTE
 #  if __has_c_attribute (__fallthrough__)
 #   define _GL_ATTRIBUTE_FALLTHROUGH [[__fallthrough__]]
 #  endif
@@ -380,7 +384,7 @@ AC_DEFUN([gl_COMMON_BODY], [
 #   if !defined __apple_build_version__ && __clang_major__ >= 10
 #    define _GL_ATTRIBUTE_MAYBE_UNUSED [[__maybe_unused__]]
 #   endif
-#  elif defined __has_c_attribute
+#  elif _GL_HAVE___HAS_C_ATTRIBUTE
 #   if __has_c_attribute (__maybe_unused__)
 #    define _GL_ATTRIBUTE_MAYBE_UNUSED [[__maybe_unused__]]
 #   endif
@@ -411,7 +415,7 @@ AC_DEFUN([gl_COMMON_BODY], [
 #   if __clang_major__ >= 1000
 #    define _GL_ATTRIBUTE_NODISCARD [[__nodiscard__]]
 #   endif
-#  elif defined __has_c_attribute
+#  elif _GL_HAVE___HAS_C_ATTRIBUTE
 #   if __has_c_attribute (__nodiscard__)
 #    define _GL_ATTRIBUTE_NODISCARD [[__nodiscard__]]
 #   endif
@@ -466,11 +470,25 @@ AC_DEFUN([gl_COMMON_BODY], [
 /* _GL_ATTRIBUTE_NOTHROW declares that the function does not throw exceptions.
  */
 /* Applies to: functions.  */
+/* After a function's parameter list, this attribute must come first, before
+   other attributes.  */
 #ifndef _GL_ATTRIBUTE_NOTHROW
-# if _GL_HAS_ATTRIBUTE (nothrow) && !defined __cplusplus
-#  define _GL_ATTRIBUTE_NOTHROW __attribute__ ((__nothrow__))
+# if defined __cplusplus
+#  if _GL_GNUC_PREREQ (2, 8) || __clang_major >= 4
+#   if __cplusplus >= 201103L
+#    define _GL_ATTRIBUTE_NOTHROW noexcept (true)
+#   else
+#    define _GL_ATTRIBUTE_NOTHROW throw ()
+#   endif
+#  else
+#   define _GL_ATTRIBUTE_NOTHROW
+#  endif
 # else
-#  define _GL_ATTRIBUTE_NOTHROW
+#  if _GL_HAS_ATTRIBUTE (nothrow)
+#   define _GL_ATTRIBUTE_NOTHROW __attribute__ ((__nothrow__))
+#  else
+#   define _GL_ATTRIBUTE_NOTHROW
+#  endif
 # endif
 #endif
 
@@ -1056,6 +1074,7 @@ AC_DEFUN([gl_CC_GNULIB_WARNINGS],
     dnl -Wno-pedantic                         >= 4.8          >= 3.9
     dnl -Wno-sign-compare                     >= 3            >= 3.9
     dnl -Wno-sign-conversion                  >= 4.3          >= 3.9
+    dnl -Wno-tautological-out-of-range-compare  -             >= 3.9
     dnl -Wno-type-limits                      >= 4.3          >= 3.9
     dnl -Wno-undef                            >= 3            >= 3.9
     dnl -Wno-unsuffixed-float-constants       >= 4.5
@@ -1081,6 +1100,9 @@ AC_DEFUN([gl_CC_GNULIB_WARNINGS],
       #if __GNUC__ + (__GNUC_MINOR__ >= 8) > 4 || (__clang_major__ + 
(__clang_minor__ >= 9) > 3)
       -Wno-pedantic
       #endif
+      #if 3 < __clang_major__ + (9 <= __clang_minor__)
+      -Wno-tautological-constant-out-of-range-compare
+      #endif
       #if __GNUC__ + (__GNUC_MINOR__ >= 3) > 4 || (__clang_major__ + 
(__clang_minor__ >= 9) > 3)
       -Wno-sign-conversion
       -Wno-type-limits
@@ -1144,12 +1166,12 @@ AC_DEFUN([gl_PREPARE_CHECK_FUNCS_MACOS],
          if test $gl_cv_compiler_clang = yes; then
            dnl Test whether the compiler supports the option
            dnl '-Werror=unguarded-availability-new'.
-           save_ac_compile="$ac_compile"
+           saved_ac_compile="$ac_compile"
            ac_compile="$ac_compile -Werror=unguarded-availability-new"
            AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])],
              
[gl_cv_compiler_check_future_option='-Werror=unguarded-availability-new'],
              [gl_cv_compiler_check_future_option=none])
-           ac_compile="$save_ac_compile"
+           ac_compile="$saved_ac_compile"
          else
            gl_cv_compiler_check_future_option=none
          fi
@@ -1197,14 +1219,14 @@ AC_DEFUN([gl_CHECK_FUNCS_CASE_FOR_MACOS],
          darwin*)
            if test "x$gl_cv_compiler_check_future_option" != "xnone"; then
              dnl Use a compile test, not a link test.
-             save_ac_compile="$ac_compile"
+             saved_ac_compile="$ac_compile"
              ac_compile="$ac_compile $gl_cv_compiler_check_future_option"
-             save_ac_compile_for_check_decl="$ac_compile_for_check_decl"
+             saved_ac_compile_for_check_decl="$ac_compile_for_check_decl"
              ac_compile_for_check_decl="$ac_compile_for_check_decl 
$gl_cv_compiler_check_future_option"
              unset [ac_cv_have_decl_][$1]
              AC_CHECK_DECL([$1], , , [$2])
-             ac_compile="$save_ac_compile"
-             ac_compile_for_check_decl="$save_ac_compile_for_check_decl"
+             ac_compile="$saved_ac_compile"
+             ac_compile_for_check_decl="$saved_ac_compile_for_check_decl"
              [ac_cv_func_][$1]="$[ac_cv_have_decl_][$1]"
              if test $[ac_cv_func_][$1] = yes; then
                [gl_cv_onwards_func_][$1]=yes
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 14ff92040a4..7a7ebb0f34e 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -1,5 +1,5 @@
 # DO NOT EDIT! GENERATED AUTOMATICALLY!
-# Copyright (C) 2002-2023 Free Software Foundation, Inc.
+# Copyright (C) 2002-2024 Free Software Foundation, Inc.
 #
 # 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
@@ -432,7 +432,8 @@ AC_DEFUN([gl_INIT],
   ])
   gl_STRING_MODULE_INDICATOR([memrchr])
   gl_FUNC_MEMSET_EXPLICIT
-  gl_CONDITIONAL([GL_COND_OBJ_MEMSET_EXPLICIT], [test $HAVE_MEMSET_EXPLICIT = 
0])
+  gl_CONDITIONAL([GL_COND_OBJ_MEMSET_EXPLICIT],
+                 [test $HAVE_MEMSET_EXPLICIT = 0 || test 
$REPLACE_MEMSET_EXPLICIT = 1])
   AM_COND_IF([GL_COND_OBJ_MEMSET_EXPLICIT], [
     gl_PREREQ_MEMSET_EXPLICIT
   ])
@@ -677,7 +678,7 @@ AC_DEFUN([gl_INIT],
     if $gl_gnulib_enabled_260941c0e5dc67ec9e87d1fb321c300b; then :; else
       AC_REQUIRE([AC_CANONICAL_HOST])
       gl_gnulib_enabled_260941c0e5dc67ec9e87d1fb321c300b=true
-      if case $host_os in mingw*) false;; *) :;; esac; then
+      if case $host_os in mingw* | windows*) false;; *) :;; esac; then
         func_gl_gnulib_m4code_open
       fi
     fi
@@ -1005,13 +1006,13 @@ AC_DEFUN([gl_INIT],
   if test $REPLACE_GETLINE = 1; then
     func_gl_gnulib_m4code_getdelim
   fi
-  if case $host_os in mingw*) false;; *) test $HAVE_GETLOADAVG = 0 || test 
$REPLACE_GETLOADAVG = 1;; esac; then
+  if case $host_os in mingw* | windows*) false;; *) test $HAVE_GETLOADAVG = 0 
|| test $REPLACE_GETLOADAVG = 1;; esac; then
     func_gl_gnulib_m4code_open
   fi
   if test $REPLACE_GETOPT = 1; then
     func_gl_gnulib_m4code_be453cec5eecf5731a274f2de7f2db36
   fi
-  if case $host_os in mingw*) false;; *) test $HAVE_GETRANDOM = 0 || test 
$REPLACE_GETRANDOM = 1;; esac; then
+  if case $host_os in mingw* | windows*) false;; *) test $HAVE_GETRANDOM = 0 
|| test $REPLACE_GETRANDOM = 1;; esac; then
     func_gl_gnulib_m4code_open
   fi
   if test $HAVE_READLINKAT = 0 || test $REPLACE_READLINKAT = 1; then
diff --git a/m4/group-member.m4 b/m4/group-member.m4
index 7c56ee3de7d..60b3d526db2 100644
--- a/m4/group-member.m4
+++ b/m4/group-member.m4
@@ -1,6 +1,6 @@
 # serial 14
 
-# Copyright (C) 1999-2001, 2003-2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 1999-2001, 2003-2007, 2009-2024 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
diff --git a/m4/ieee754-h.m4 b/m4/ieee754-h.m4
index 73a8f8350b6..cc8ef32bd32 100644
--- a/m4/ieee754-h.m4
+++ b/m4/ieee754-h.m4
@@ -1,6 +1,6 @@
 # Configure ieee754-h module
 
-dnl Copyright 2018-2023 Free Software Foundation, Inc.
+dnl Copyright 2018-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/include_next.m4 b/m4/include_next.m4
index 9f19215ef05..70cb746f435 100644
--- a/m4/include_next.m4
+++ b/m4/include_next.m4
@@ -1,5 +1,5 @@
-# include_next.m4 serial 26
-dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
+# include_next.m4 serial 27
+dnl Copyright (C) 2006-2024 Free Software Foundation, Inc.
 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.
@@ -74,17 +74,17 @@ EOF
 #endif
 #define DEFINED_IN_CONFTESTD2
 EOF
-     gl_save_CPPFLAGS="$CPPFLAGS"
-     CPPFLAGS="$gl_save_CPPFLAGS -Iconftestd1b -Iconftestd2"
+     gl_saved_CPPFLAGS="$CPPFLAGS"
+     CPPFLAGS="$gl_saved_CPPFLAGS -Iconftestd1b -Iconftestd2"
 dnl We intentionally avoid using AC_LANG_SOURCE here.
      AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED[#include <conftest.h>]],
        [gl_cv_have_include_next=yes],
-       [CPPFLAGS="$gl_save_CPPFLAGS -Iconftestd1a -Iconftestd2"
+       [CPPFLAGS="$gl_saved_CPPFLAGS -Iconftestd1a -Iconftestd2"
         AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED[#include <conftest.h>]],
           [gl_cv_have_include_next=buggy],
           [gl_cv_have_include_next=no])
        ])
-     CPPFLAGS="$gl_save_CPPFLAGS"
+     CPPFLAGS="$gl_saved_CPPFLAGS"
      rm -rf conftestd1a conftestd1b conftestd2
     ])
   PRAGMA_SYSTEM_HEADER=
diff --git a/m4/inttypes.m4 b/m4/inttypes.m4
index e7efbe94167..6abf9dbe280 100644
--- a/m4/inttypes.m4
+++ b/m4/inttypes.m4
@@ -1,5 +1,5 @@
 # inttypes.m4 serial 37
-dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/largefile.m4 b/m4/largefile.m4
index 8b051c0042b..cbe9bc1f63d 100644
--- a/m4/largefile.m4
+++ b/m4/largefile.m4
@@ -1,7 +1,7 @@
 # Enable large files on systems where this is not the default.
 # Enable support for files on Linux file systems with 64-bit inode numbers.
 
-# Copyright 1992-1996, 1998-2023 Free Software Foundation, Inc.
+# Copyright 1992-1996, 1998-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -247,7 +247,7 @@ AC_DEFUN([_AC_SYS_LARGEFILE_PROBE],
     AC_REQUIRE([AC_CANONICAL_HOST])
     if test $ac_opt_found != yes; then
       AS_CASE([$host_os],
-        [mingw*],
+        [mingw* | windows*],
           [ac_cv_sys_largefile_opts="supported through gnulib"
            ac_opt_found=yes]
       )
@@ -305,7 +305,7 @@ AC_DEFUN([gl_LARGEFILE],
 [
   AC_REQUIRE([AC_CANONICAL_HOST])
   case "$host_os" in
-    mingw*)
+    mingw* | windows*)
       dnl Native Windows.
       dnl mingw64 defines off_t to a 64-bit type already, if
       dnl _FILE_OFFSET_BITS=64, which is ensured by AC_SYS_LARGEFILE.
diff --git a/m4/lchmod.m4 b/m4/lchmod.m4
index a1370e163fb..7b263a241eb 100644
--- a/m4/lchmod.m4
+++ b/m4/lchmod.m4
@@ -1,6 +1,6 @@
 #serial 10
 
-dnl Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005-2006, 2008-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/libgmp.m4 b/m4/libgmp.m4
index eb20ada0fa5..782dfbae2e1 100644
--- a/m4/libgmp.m4
+++ b/m4/libgmp.m4
@@ -1,6 +1,6 @@
 # libgmp.m4 serial 8
 # Configure the GMP library or a replacement.
-dnl Copyright 2020-2023 Free Software Foundation, Inc.
+dnl Copyright 2020-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/limits-h.m4 b/m4/limits-h.m4
index 6a5983ebc25..1825328380b 100644
--- a/m4/limits-h.m4
+++ b/m4/limits-h.m4
@@ -1,6 +1,6 @@
 dnl Check whether limits.h has needed features.
 
-dnl Copyright 2016-2023 Free Software Foundation, Inc.
+dnl Copyright 2016-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/lstat.m4 b/m4/lstat.m4
index 2bc46697934..48cc8653fe6 100644
--- a/m4/lstat.m4
+++ b/m4/lstat.m4
@@ -1,6 +1,6 @@
-# serial 34
+# serial 36
 
-# Copyright (C) 1997-2001, 2003-2023 Free Software Foundation, Inc.
+# Copyright (C) 1997-2001, 2003-2024 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -18,7 +18,7 @@ AC_DEFUN([gl_FUNC_LSTAT],
   if test $ac_cv_func_lstat = yes; then
     AC_REQUIRE([gl_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK])
     case $host_os,$gl_cv_func_lstat_dereferences_slashed_symlink in
-      solaris* | *no)
+      darwin* | solaris* | *no)
         REPLACE_LSTAT=1
         ;;
     esac
@@ -62,7 +62,7 @@ AC_DEFUN([gl_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK],
           *-gnu* | gnu*)
             # Guess yes on glibc systems.
             gl_cv_func_lstat_dereferences_slashed_symlink="guessing yes" ;;
-          mingw*)
+          mingw* | windows*)
             # Guess no on native Windows.
             gl_cv_func_lstat_dereferences_slashed_symlink="guessing no" ;;
           *)
diff --git a/m4/malloc.m4 b/m4/malloc.m4
index bc580176f5f..635d6726b11 100644
--- a/m4/malloc.m4
+++ b/m4/malloc.m4
@@ -1,5 +1,5 @@
-# malloc.m4 serial 29
-dnl Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
+# malloc.m4 serial 31
+dnl Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc.
 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.
@@ -16,7 +16,8 @@ AC_DEFUN([_AC_FUNC_MALLOC_IF],
           [[#include <stdlib.h>
           ]],
           [[void *p = malloc (0);
-            int result = !p;
+            void * volatile vp = p;
+            int result = !vp;
             free (p);
             return result;]])
        ],
@@ -26,7 +27,7 @@ AC_DEFUN([_AC_FUNC_MALLOC_IF],
           # Guess yes on platforms where we know the result.
           *-gnu* | freebsd* | netbsd* | openbsd* | bitrig* \
           | gnu* | *-musl* | midipix* | midnightbsd* \
-          | hpux* | solaris* | cygwin* | mingw* | msys* )
+          | hpux* | solaris* | cygwin* | mingw* | windows* | msys* )
             ac_cv_func_malloc_0_nonnull="guessing yes" ;;
           # If we don't know, obey --enable-cross-guesses.
           *) ac_cv_func_malloc_0_nonnull="$gl_cross_guess_normal" ;;
@@ -128,7 +129,7 @@ AC_DEFUN([gl_CHECK_MALLOC_POSIX],
       dnl except on those platforms where we have seen 'test-malloc-gnu',
       dnl 'test-realloc-gnu', 'test-calloc-gnu' fail.
       case "$host_os" in
-        mingw*)
+        mingw* | windows*)
           gl_cv_func_malloc_posix=no ;;
         irix* | solaris*)
           dnl On IRIX 6.5, the three functions return NULL with errno unset
diff --git a/m4/manywarnings.m4 b/m4/manywarnings.m4
index a06f26f672e..3c6795ceb28 100644
--- a/m4/manywarnings.m4
+++ b/m4/manywarnings.m4
@@ -1,5 +1,5 @@
-# manywarnings.m4 serial 24
-dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
+# manywarnings.m4 serial 25
+dnl Copyright (C) 2008-2024 Free Software Foundation, Inc.
 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.
@@ -52,7 +52,7 @@ AC_DEFUN([gl_MANYWARN_ALL_GCC(C)],
     AC_CACHE_CHECK([whether -Wno-missing-field-initializers is needed],
       [gl_cv_cc_nomfi_needed],
       [gl_cv_cc_nomfi_needed=no
-       gl_save_CFLAGS="$CFLAGS"
+       gl_saved_CFLAGS="$CFLAGS"
        CFLAGS="$CFLAGS -Wextra -Werror"
        AC_COMPILE_IFELSE(
          [AC_LANG_PROGRAM(
@@ -71,7 +71,7 @@ AC_DEFUN([gl_MANYWARN_ALL_GCC(C)],
          [CFLAGS="$CFLAGS -Wno-missing-field-initializers"
           AC_COMPILE_IFELSE([],
             [gl_cv_cc_nomfi_needed=yes])])
-       CFLAGS="$gl_save_CFLAGS"
+       CFLAGS="$gl_saved_CFLAGS"
     ])
 
     dnl Next, check if -Werror -Wuninitialized is useful with the
@@ -79,13 +79,13 @@ AC_DEFUN([gl_MANYWARN_ALL_GCC(C)],
     dnl has no effect if -O is not also used
     AC_CACHE_CHECK([whether -Wuninitialized is supported],
       [gl_cv_cc_uninitialized_supported],
-      [gl_save_CFLAGS="$CFLAGS"
+      [gl_saved_CFLAGS="$CFLAGS"
        CFLAGS="$CFLAGS -Werror -Wuninitialized"
        AC_COMPILE_IFELSE(
          [AC_LANG_PROGRAM([[]], [[]])],
          [gl_cv_cc_uninitialized_supported=yes],
          [gl_cv_cc_uninitialized_supported=no])
-       CFLAGS="$gl_save_CFLAGS"
+       CFLAGS="$gl_saved_CFLAGS"
       ])
   ])
 
diff --git a/m4/mbstate_t.m4 b/m4/mbstate_t.m4
index dcd66b96131..b2bcba45e96 100644
--- a/m4/mbstate_t.m4
+++ b/m4/mbstate_t.m4
@@ -1,5 +1,5 @@
 # mbstate_t.m4 serial 14
-dnl Copyright (C) 2000-2002, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2000-2002, 2008-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/md5.m4 b/m4/md5.m4
index 678489e5c5b..7af56a8a3d1 100644
--- a/m4/md5.m4
+++ b/m4/md5.m4
@@ -1,5 +1,5 @@
 # md5.m4 serial 14
-dnl Copyright (C) 2002-2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-2006, 2008-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/memmem.m4 b/m4/memmem.m4
index 3cf46bc2e9c..7985266f8b7 100644
--- a/m4/memmem.m4
+++ b/m4/memmem.m4
@@ -1,5 +1,5 @@
 # memmem.m4 serial 29
-dnl Copyright (C) 2002-2004, 2007-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-2004, 2007-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/mempcpy.m4 b/m4/mempcpy.m4
index 612b77b3c11..94ce05d1a6a 100644
--- a/m4/mempcpy.m4
+++ b/m4/mempcpy.m4
@@ -1,5 +1,5 @@
 # mempcpy.m4 serial 14
-dnl Copyright (C) 2003-2004, 2006-2007, 2009-2023 Free Software Foundation,
+dnl Copyright (C) 2003-2004, 2006-2007, 2009-2024 Free Software Foundation,
 dnl Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
diff --git a/m4/memrchr.m4 b/m4/memrchr.m4
index 7611ac7e3ac..b4ccdfa3c8d 100644
--- a/m4/memrchr.m4
+++ b/m4/memrchr.m4
@@ -1,5 +1,5 @@
 # memrchr.m4 serial 11
-dnl Copyright (C) 2002-2003, 2005-2007, 2009-2023 Free Software Foundation,
+dnl Copyright (C) 2002-2003, 2005-2007, 2009-2024 Free Software Foundation,
 dnl Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
diff --git a/m4/memset_explicit.m4 b/m4/memset_explicit.m4
index 9dcd89a758a..19514ff917e 100644
--- a/m4/memset_explicit.m4
+++ b/m4/memset_explicit.m4
@@ -1,4 +1,5 @@
-dnl Copyright 2022-2023 Free Software Foundation, Inc.
+# memset_explicit.m4 serial 2
+dnl Copyright 2022-2024 Free Software Foundation, Inc.
 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.
@@ -7,9 +8,12 @@ AC_DEFUN([gl_FUNC_MEMSET_EXPLICIT],
 [
   AC_REQUIRE([gl_STRING_H_DEFAULTS])
 
-  AC_CHECK_FUNCS_ONCE([memset_explicit])
+  gl_CHECK_FUNCS_ANDROID([memset_explicit], [[#include <string.h>]])
   if test $ac_cv_func_memset_explicit = no; then
     HAVE_MEMSET_EXPLICIT=0
+    case "$gl_cv_onwards_func_memset_explicit" in
+      future*) REPLACE_MEMSET_EXPLICIT=1 ;;
+    esac
   fi
 ])
 
diff --git a/m4/minmax.m4 b/m4/minmax.m4
index fd09846ffb3..5c0a927da66 100644
--- a/m4/minmax.m4
+++ b/m4/minmax.m4
@@ -1,5 +1,5 @@
 # minmax.m4 serial 4
-dnl Copyright (C) 2005, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/mkostemp.m4 b/m4/mkostemp.m4
index 1b0d0d55946..1c22b8d51b4 100644
--- a/m4/mkostemp.m4
+++ b/m4/mkostemp.m4
@@ -1,5 +1,5 @@
 # mkostemp.m4 serial 4
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/mktime.m4 b/m4/mktime.m4
index 69cce86da5a..0565e5e61fe 100644
--- a/m4/mktime.m4
+++ b/m4/mktime.m4
@@ -1,5 +1,5 @@
-# serial 38
-dnl Copyright (C) 2002-2003, 2005-2007, 2009-2023 Free Software Foundation,
+# serial 39
+dnl Copyright (C) 2002-2003, 2005-2007, 2009-2024 Free Software Foundation,
 dnl Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -264,9 +264,9 @@ main ()
          [gl_cv_func_working_mktime=yes],
          [gl_cv_func_working_mktime=no],
          [case "$host_os" in
-                    # Guess no on native Windows.
-            mingw*) gl_cv_func_working_mktime="guessing no" ;;
-            *)      gl_cv_func_working_mktime="$gl_cross_guess_normal" ;;
+                               # Guess no on native Windows.
+            mingw* | windows*) gl_cv_func_working_mktime="guessing no" ;;
+            *)                 
gl_cv_func_working_mktime="$gl_cross_guess_normal" ;;
           esac
          ])
      fi
@@ -287,7 +287,7 @@ AC_DEFUN([gl_FUNC_MKTIME],
        with the algorithmic workarounds.])
   fi
   case "$host_os" in
-    mingw*)
+    mingw* | windows*)
       REPLACE_MKTIME=1
       AC_DEFINE([NEED_MKTIME_WINDOWS], [1],
         [Define if the compilation of mktime.c should define 'mktime'
diff --git a/m4/mode_t.m4 b/m4/mode_t.m4
index 82197c0214a..af88da51285 100644
--- a/m4/mode_t.m4
+++ b/m4/mode_t.m4
@@ -1,5 +1,5 @@
 # mode_t.m4 serial 2
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/multiarch.m4 b/m4/multiarch.m4
index 3ba5b0f76c6..5f8339f5c7d 100644
--- a/m4/multiarch.m4
+++ b/m4/multiarch.m4
@@ -1,5 +1,5 @@
 # multiarch.m4 serial 9
-dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2008-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/musl.m4 b/m4/musl.m4
index e28a3fed677..34d2c1ff22a 100644
--- a/m4/musl.m4
+++ b/m4/musl.m4
@@ -1,5 +1,5 @@
 # musl.m4 serial 4
-dnl Copyright (C) 2019-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2019-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/nanosleep.m4 b/m4/nanosleep.m4
index b7f22d7b606..c51f590402f 100644
--- a/m4/nanosleep.m4
+++ b/m4/nanosleep.m4
@@ -1,11 +1,11 @@
-# serial 44
+# serial 46
 
 dnl From Jim Meyering.
 dnl Check for the nanosleep function.
 dnl If not found, use the supplied replacement.
 dnl
 
-# Copyright (C) 1999-2001, 2003-2023 Free Software Foundation, Inc.
+# Copyright (C) 1999-2001, 2003-2024 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -21,7 +21,7 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],
 
  AC_CHECK_DECLS_ONCE([alarm])
 
- nanosleep_save_libs=$LIBS
+ gl_saved_LIBS=$LIBS
 
  # Solaris 2.5.1 needs -lposix4 to get the nanosleep function.
  # Solaris 7 prefers the library name -lrt to the obsolescent name -lposix4.
@@ -116,11 +116,14 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],
         *)     gl_cv_func_nanosleep=no ;;
         esac],
        [case "$host_os" in
-          linux*) # Guess it halfway works when the kernel is Linux.
+            # Guess it halfway works when the kernel is Linux.
+          linux*)
             gl_cv_func_nanosleep='guessing no (mishandles large arguments)' ;;
-          mingw*) # Guess no on native Windows.
+            # Guess no on native Windows.
+          mingw* | windows*)
             gl_cv_func_nanosleep='guessing no' ;;
-          *)      # If we don't know, obey --enable-cross-guesses.
+            # If we don't know, obey --enable-cross-guesses.
+          *)
             gl_cv_func_nanosleep="$gl_cross_guess_normal" ;;
         esac
        ])
@@ -140,7 +143,7 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],
  else
    HAVE_NANOSLEEP=0
  fi
- LIBS=$nanosleep_save_libs
+ LIBS=$gl_saved_LIBS
 
  # For backward compatibility.
  LIB_NANOSLEEP="$NANOSLEEP_LIB"
diff --git a/m4/ndk-build.m4 b/m4/ndk-build.m4
index ab4e88ca168..aacb2ed048b 100644
--- a/m4/ndk-build.m4
+++ b/m4/ndk-build.m4
@@ -1,4 +1,4 @@
-dnl Copyright (C) 2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2023-2024 Free Software Foundation, Inc.
 dnl This file is part of GNU Emacs.
 
 dnl GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/m4/nocrash.m4 b/m4/nocrash.m4
index 6a766387618..9730fc09034 100644
--- a/m4/nocrash.m4
+++ b/m4/nocrash.m4
@@ -1,5 +1,5 @@
 # nocrash.m4 serial 5
-dnl Copyright (C) 2005, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/nproc.m4 b/m4/nproc.m4
index c892ad74b7d..e4065776a86 100644
--- a/m4/nproc.m4
+++ b/m4/nproc.m4
@@ -1,5 +1,5 @@
 # nproc.m4 serial 6
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/nstrftime.m4 b/m4/nstrftime.m4
index 04c0b63fbd0..67250dc9455 100644
--- a/m4/nstrftime.m4
+++ b/m4/nstrftime.m4
@@ -1,6 +1,6 @@
 # serial 37
 
-# Copyright (C) 1996-1997, 1999-2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 1996-1997, 1999-2007, 2009-2024 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
diff --git a/m4/off_t.m4 b/m4/off_t.m4
index 880f347250a..f3259f9c245 100644
--- a/m4/off_t.m4
+++ b/m4/off_t.m4
@@ -1,5 +1,5 @@
 # off_t.m4 serial 1
-dnl Copyright (C) 2012-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2012-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/open-cloexec.m4 b/m4/open-cloexec.m4
index fd572fcd1de..a2d50329b97 100644
--- a/m4/open-cloexec.m4
+++ b/m4/open-cloexec.m4
@@ -1,6 +1,6 @@
 # Test whether O_CLOEXEC is defined.
 
-dnl Copyright 2017-2023 Free Software Foundation, Inc.
+dnl Copyright 2017-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/open-slash.m4 b/m4/open-slash.m4
index 1f731f8ad80..45310c0c581 100644
--- a/m4/open-slash.m4
+++ b/m4/open-slash.m4
@@ -1,5 +1,5 @@
 # open-slash.m4 serial 2
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/open.m4 b/m4/open.m4
index 94fa2bb7530..91e5c31b59a 100644
--- a/m4/open.m4
+++ b/m4/open.m4
@@ -1,5 +1,5 @@
-# open.m4 serial 15
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+# open.m4 serial 16
+dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
 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.
@@ -9,7 +9,7 @@ AC_DEFUN([gl_FUNC_OPEN],
   AC_REQUIRE([AC_CANONICAL_HOST])
   AC_REQUIRE([gl_PREPROC_O_CLOEXEC])
   case "$host_os" in
-    mingw* | pw*)
+    mingw* | windows* | pw*)
       REPLACE_OPEN=1
       ;;
     *)
diff --git a/m4/pathmax.m4 b/m4/pathmax.m4
index 6d47d2c026e..a0fc296c9b2 100644
--- a/m4/pathmax.m4
+++ b/m4/pathmax.m4
@@ -1,5 +1,5 @@
 # pathmax.m4 serial 11
-dnl Copyright (C) 2002-2003, 2005-2006, 2009-2023 Free Software Foundation,
+dnl Copyright (C) 2002-2003, 2005-2006, 2009-2024 Free Software Foundation,
 dnl Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
diff --git a/m4/pid_t.m4 b/m4/pid_t.m4
index 0fd7d0a1810..8f8d39d81db 100644
--- a/m4/pid_t.m4
+++ b/m4/pid_t.m4
@@ -1,5 +1,5 @@
 # pid_t.m4 serial 4
-dnl Copyright (C) 2020-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2020-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/pipe2.m4 b/m4/pipe2.m4
index 79de69cd1a4..74b7b284b3e 100644
--- a/m4/pipe2.m4
+++ b/m4/pipe2.m4
@@ -1,5 +1,5 @@
 # pipe2.m4 serial 4
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/printf-posix-rpl.m4 b/m4/printf-posix-rpl.m4
index 36156d43502..0f741192499 100644
--- a/m4/printf-posix-rpl.m4
+++ b/m4/printf-posix-rpl.m4
@@ -1,5 +1,5 @@
 # printf-posix-rpl.m4 serial 4
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/pselect.m4 b/m4/pselect.m4
index 6c3d1b8f97f..005b722b965 100644
--- a/m4/pselect.m4
+++ b/m4/pselect.m4
@@ -1,5 +1,5 @@
 # pselect.m4 serial 11
-dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2011-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/pthread_sigmask.m4 b/m4/pthread_sigmask.m4
index 27795282bee..cb2ee900313 100644
--- a/m4/pthread_sigmask.m4
+++ b/m4/pthread_sigmask.m4
@@ -1,5 +1,5 @@
-# pthread_sigmask.m4 serial 22
-dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
+# pthread_sigmask.m4 serial 23
+dnl Copyright (C) 2011-2024 Free Software Foundation, Inc.
 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.
@@ -47,7 +47,7 @@ AC_DEFUN([gl_FUNC_PTHREAD_SIGMASK],
           if test -n "$LIBMULTITHREAD"; then
             AC_CACHE_CHECK([for pthread_sigmask in $LIBMULTITHREAD],
               [gl_cv_func_pthread_sigmask_in_LIBMULTITHREAD],
-              [gl_save_LIBS="$LIBS"
+              [gl_saved_LIBS="$LIBS"
                LIBS="$LIBS $LIBMULTITHREAD"
                AC_LINK_IFELSE(
                  [AC_LANG_PROGRAM(
@@ -58,7 +58,7 @@ AC_DEFUN([gl_FUNC_PTHREAD_SIGMASK],
                  ],
                  [gl_cv_func_pthread_sigmask_in_LIBMULTITHREAD=yes],
                  [gl_cv_func_pthread_sigmask_in_LIBMULTITHREAD=no])
-               LIBS="$gl_save_LIBS"
+               LIBS="$gl_saved_LIBS"
               ])
             if test $gl_cv_func_pthread_sigmask_in_LIBMULTITHREAD = yes; then
               dnl pthread_sigmask is available with -pthread or -lpthread.
@@ -164,7 +164,7 @@ AC_DEFUN([gl_FUNC_PTHREAD_SIGMASK],
     AC_CACHE_CHECK([whether pthread_sigmask returns error numbers],
       [gl_cv_func_pthread_sigmask_return_works],
       [
-        gl_save_LIBS="$LIBS"
+        gl_saved_LIBS="$LIBS"
         LIBS="$LIBS $PTHREAD_SIGMASK_LIB"
         AC_RUN_IFELSE(
           [AC_LANG_SOURCE([[
@@ -188,7 +188,7 @@ int main ()
                gl_cv_func_pthread_sigmask_return_works="guessing yes";;
            esac
           ])
-        LIBS="$gl_save_LIBS"
+        LIBS="$gl_saved_LIBS"
       ])
     case "$gl_cv_func_pthread_sigmask_return_works" in
       *no)
@@ -214,7 +214,7 @@ int main ()
           [dnl Link against $LIBMULTITHREAD, not only $PTHREAD_SIGMASK_LIB.
            dnl Otherwise we get a false positive on those platforms where
            dnl $gl_cv_func_pthread_sigmask_in_libc_works is "no".
-           gl_save_LIBS=$LIBS
+           gl_saved_LIBS=$LIBS
            LIBS="$LIBS $LIBMULTITHREAD"])
         AC_RUN_IFELSE(
           [AC_LANG_SOURCE([[
@@ -258,7 +258,7 @@ int main ()
           [:],
           [gl_cv_func_pthread_sigmask_unblock_works=no],
           [:])
-        m4_ifdef([gl_][THREADLIB], [LIBS=$gl_save_LIBS])
+        m4_ifdef([gl_][THREADLIB], [LIBS=$gl_saved_LIBS])
       ])
     case "$gl_cv_func_pthread_sigmask_unblock_works" in
       *no)
diff --git a/m4/rawmemchr.m4 b/m4/rawmemchr.m4
index a48d829526f..57d1c2915e3 100644
--- a/m4/rawmemchr.m4
+++ b/m4/rawmemchr.m4
@@ -1,5 +1,5 @@
 # rawmemchr.m4 serial 3
-dnl Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/readlink.m4 b/m4/readlink.m4
index f1d41d2b113..6d78ec84a03 100644
--- a/m4/readlink.m4
+++ b/m4/readlink.m4
@@ -1,5 +1,5 @@
 # readlink.m4 serial 17
-dnl Copyright (C) 2003, 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003, 2007, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/readlinkat.m4 b/m4/readlinkat.m4
index 5c513562919..99822102294 100644
--- a/m4/readlinkat.m4
+++ b/m4/readlinkat.m4
@@ -1,7 +1,7 @@
 # serial 8
 # See if we need to provide readlinkat replacement.
 
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/readutmp.m4 b/m4/readutmp.m4
index 0a47f4bb77d..ec40019735f 100644
--- a/m4/readutmp.m4
+++ b/m4/readutmp.m4
@@ -1,5 +1,5 @@
-# readutmp.m4 serial 30
-dnl Copyright (C) 2002-2023 Free Software Foundation, Inc.
+# readutmp.m4 serial 31
+dnl Copyright (C) 2002-2024 Free Software Foundation, Inc.
 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.
@@ -18,7 +18,7 @@ AC_DEFUN([gl_READUTMP],
     if test $ac_cv_header_systemd_sd_login_h = yes; then
       AC_CACHE_CHECK([for libsystemd version >= 254],
         [gl_cv_lib_readutmp_systemd],
-        [gl_save_LIBS="$LIBS"
+        [gl_saved_LIBS="$LIBS"
          LIBS="$LIBS -lsystemd"
          AC_LINK_IFELSE(
            [AC_LANG_PROGRAM([[
@@ -31,7 +31,7 @@ AC_DEFUN([gl_READUTMP],
            ],
            [gl_cv_lib_readutmp_systemd=yes],
            [gl_cv_lib_readutmp_systemd=no])
-         LIBS="$gl_save_LIBS"
+         LIBS="$gl_saved_LIBS"
         ])
       if test $gl_cv_lib_readutmp_systemd = yes; then
         AC_DEFINE([READUTMP_USE_SYSTEMD], [1],
diff --git a/m4/realloc.m4 b/m4/realloc.m4
index 26053914cbe..a59af2807c9 100644
--- a/m4/realloc.m4
+++ b/m4/realloc.m4
@@ -1,5 +1,5 @@
-# realloc.m4 serial 27
-dnl Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
+# realloc.m4 serial 29
+dnl Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc.
 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.
@@ -16,7 +16,8 @@ AC_DEFUN([_AC_FUNC_REALLOC_IF],
           [[#include <stdlib.h>
           ]],
           [[void *p = realloc (0, 0);
-            int result = !p;
+            void * volatile vp = p;
+            int result = !vp;
             free (p);
             return result;]])
        ],
@@ -26,7 +27,7 @@ AC_DEFUN([_AC_FUNC_REALLOC_IF],
           # Guess yes on platforms where we know the result.
           *-gnu* | freebsd* | netbsd* | openbsd* | bitrig* \
           | gnu* | *-musl* | midipix* | midnightbsd* \
-          | hpux* | solaris* | cygwin* | mingw* | msys* )
+          | hpux* | solaris* | cygwin* | mingw* | windows* | msys* )
             ac_cv_func_realloc_0_nonnull="guessing yes" ;;
           # If we don't know, obey --enable-cross-guesses.
           *) ac_cv_func_realloc_0_nonnull="$gl_cross_guess_normal" ;;
diff --git a/m4/regex.m4 b/m4/regex.m4
index 7acadc48343..3dfeabea057 100644
--- a/m4/regex.m4
+++ b/m4/regex.m4
@@ -1,6 +1,6 @@
-# serial 74
+# serial 75
 
-# Copyright (C) 1996-2001, 2003-2023 Free Software Foundation, Inc.
+# Copyright (C) 1996-2001, 2003-2024 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -327,10 +327,10 @@ AC_DEFUN([gl_REGEX],
         [gl_cv_func_re_compile_pattern_working=yes],
         [gl_cv_func_re_compile_pattern_working=no],
         [case "$host_os" in
-                   # Guess no on native Windows.
-           mingw*) gl_cv_func_re_compile_pattern_working="guessing no" ;;
-                   # Otherwise obey --enable-cross-guesses.
-           *)      
gl_cv_func_re_compile_pattern_working="$gl_cross_guess_normal" ;;
+                              # Guess no on native Windows.
+           mingw* | windows*) gl_cv_func_re_compile_pattern_working="guessing 
no" ;;
+                              # Otherwise obey --enable-cross-guesses.
+           *)                 
gl_cv_func_re_compile_pattern_working="$gl_cross_guess_normal" ;;
          esac
         ])
       ])
diff --git a/m4/sha1.m4 b/m4/sha1.m4
index 16b79c0868b..c0a87536a5c 100644
--- a/m4/sha1.m4
+++ b/m4/sha1.m4
@@ -1,5 +1,5 @@
 # sha1.m4 serial 12
-dnl Copyright (C) 2002-2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-2006, 2008-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/sha256.m4 b/m4/sha256.m4
index 4d1d1dda158..2dd754c1778 100644
--- a/m4/sha256.m4
+++ b/m4/sha256.m4
@@ -1,5 +1,5 @@
 # sha256.m4 serial 8
-dnl Copyright (C) 2005, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005, 2008-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/sha512.m4 b/m4/sha512.m4
index b66dc726d80..19d03b50271 100644
--- a/m4/sha512.m4
+++ b/m4/sha512.m4
@@ -1,5 +1,5 @@
 # sha512.m4 serial 9
-dnl Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005-2006, 2008-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/sig2str.m4 b/m4/sig2str.m4
index aee18efeefd..ab3786b8954 100644
--- a/m4/sig2str.m4
+++ b/m4/sig2str.m4
@@ -1,5 +1,5 @@
 # serial 7
-dnl Copyright (C) 2002, 2005-2006, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002, 2005-2006, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/sigdescr_np.m4 b/m4/sigdescr_np.m4
index da44b432c00..d844e2f9db7 100644
--- a/m4/sigdescr_np.m4
+++ b/m4/sigdescr_np.m4
@@ -1,5 +1,5 @@
 # sigdescr_np.m4 serial 2
-dnl Copyright (C) 2020-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2020-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/signal_h.m4 b/m4/signal_h.m4
index cdd6812f97c..6f7dcc733b4 100644
--- a/m4/signal_h.m4
+++ b/m4/signal_h.m4
@@ -1,5 +1,5 @@
 # signal_h.m4 serial 22
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/socklen.m4 b/m4/socklen.m4
index 1c63a85363e..9c46db18937 100644
--- a/m4/socklen.m4
+++ b/m4/socklen.m4
@@ -1,5 +1,5 @@
 # socklen.m4 serial 11
-dnl Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005-2007, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/ssize_t.m4 b/m4/ssize_t.m4
index 52bd77d2aeb..25b28d77e4e 100644
--- a/m4/ssize_t.m4
+++ b/m4/ssize_t.m4
@@ -1,5 +1,5 @@
 # ssize_t.m4 serial 6
-dnl Copyright (C) 2001-2003, 2006, 2010-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2001-2003, 2006, 2010-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/st_dm_mode.m4 b/m4/st_dm_mode.m4
index 819dd5677fc..fab2499e8fb 100644
--- a/m4/st_dm_mode.m4
+++ b/m4/st_dm_mode.m4
@@ -1,6 +1,6 @@
 # serial 6
 
-# Copyright (C) 1998-1999, 2001, 2009-2023 Free Software Foundation,
+# Copyright (C) 1998-1999, 2001, 2009-2024 Free Software Foundation,
 # Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
diff --git a/m4/stat-time.m4 b/m4/stat-time.m4
index 40993d5731c..8bec2f5f815 100644
--- a/m4/stat-time.m4
+++ b/m4/stat-time.m4
@@ -1,6 +1,6 @@
 # Checks for stat-related time functions.
 
-# Copyright (C) 1998-1999, 2001, 2003, 2005-2007, 2009-2023 Free Software
+# Copyright (C) 1998-1999, 2001, 2003, 2005-2007, 2009-2024 Free Software
 # Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
diff --git a/m4/std-gnu11.m4 b/m4/std-gnu11.m4
index 4179470ec94..59998c17cf7 100644
--- a/m4/std-gnu11.m4
+++ b/m4/std-gnu11.m4
@@ -9,7 +9,7 @@
 m4_version_prereq([2.70], [], [
 
 
-# Copyright (C) 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
diff --git a/m4/stdalign.m4 b/m4/stdalign.m4
index 6a39ffe7565..e3c1e609236 100644
--- a/m4/stdalign.m4
+++ b/m4/stdalign.m4
@@ -1,6 +1,6 @@
 # Check for alignas and alignof that conform to C23.
 
-dnl Copyright 2011-2023 Free Software Foundation, Inc.
+dnl Copyright 2011-2024 Free Software Foundation, Inc.
 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.
@@ -13,10 +13,10 @@ AC_DEFUN([gl_ALIGNASOF],
 [
   AC_CACHE_CHECK([for alignas and alignof],
     [gl_cv_header_working_stdalign_h],
-    [gl_save_CFLAGS=$CFLAGS
+    [gl_saved_CFLAGS=$CFLAGS
      for gl_working in "yes, keywords" "yes, <stdalign.h> macros"; do
       AS_CASE([$gl_working],
-        [*stdalign.h*], [CFLAGS="$gl_save_CFLAGS -DINCLUDE_STDALIGN_H"])
+        [*stdalign.h*], [CFLAGS="$gl_saved_CFLAGS -DINCLUDE_STDALIGN_H"])
       AC_COMPILE_IFELSE(
        [AC_LANG_PROGRAM(
           [[#include <stdint.h>
@@ -56,7 +56,7 @@ AC_DEFUN([gl_ALIGNASOF],
        [gl_cv_header_working_stdalign_h=$gl_working],
        [gl_cv_header_working_stdalign_h=no])
 
-      CFLAGS=$gl_save_CFLAGS
+      CFLAGS=$gl_saved_CFLAGS
       test "$gl_cv_header_working_stdalign_h" != no && break
      done])
 
@@ -112,7 +112,11 @@ AC_DEFUN([gl_ALIGNASOF],
 #     define _Alignof(type) alignof (type)
 #    else
       template <class __t> struct __alignof_helper { char __a; __t __b; };
-#     define _Alignof(type) offsetof (__alignof_helper<type>, __b)
+#     if (defined __GNUC__ && 4 <= __GNUC__) || defined __clang__
+#      define _Alignof(type) __builtin_offsetof (__alignof_helper<type>, __b)
+#     else
+#      define _Alignof(type) offsetof (__alignof_helper<type>, __b)
+#     endif
 #     define _GL_STDALIGN_NEEDS_STDDEF 1
 #    endif
 #   else
diff --git a/m4/stddef_h.m4 b/m4/stddef_h.m4
index aa012219fcd..1bf9eb39b66 100644
--- a/m4/stddef_h.m4
+++ b/m4/stddef_h.m4
@@ -1,5 +1,5 @@
 # stddef_h.m4 serial 14
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/stdint.m4 b/m4/stdint.m4
index b9f764d4c1c..4aa250827cc 100644
--- a/m4/stdint.m4
+++ b/m4/stdint.m4
@@ -1,5 +1,5 @@
-# stdint.m4 serial 62
-dnl Copyright (C) 2001-2023 Free Software Foundation, Inc.
+# stdint.m4 serial 63
+dnl Copyright (C) 2001-2024 Free Software Foundation, Inc.
 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.
@@ -286,10 +286,10 @@ static const char *macro_values[] =
               [gl_cv_header_working_stdint_h=yes],
               [],
               [case "$host_os" in
-                         # Guess yes on native Windows.
-                 mingw*) gl_cv_header_working_stdint_h="guessing yes" ;;
-                         # In general, assume it works.
-                 *)      gl_cv_header_working_stdint_h="guessing yes" ;;
+                                    # Guess yes on native Windows.
+                 mingw* | windows*) gl_cv_header_working_stdint_h="guessing 
yes" ;;
+                                    # In general, assume it works.
+                 *)                 gl_cv_header_working_stdint_h="guessing 
yes" ;;
                esac
               ])
          ])
diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4
index dbfa0d5d61b..c19feefe717 100644
--- a/m4/stdio_h.m4
+++ b/m4/stdio_h.m4
@@ -1,5 +1,5 @@
 # stdio_h.m4 serial 63
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/stdlib_h.m4 b/m4/stdlib_h.m4
index f47c1eb37b3..92e67a74bb5 100644
--- a/m4/stdlib_h.m4
+++ b/m4/stdlib_h.m4
@@ -1,5 +1,5 @@
-# stdlib_h.m4 serial 75
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+# stdlib_h.m4 serial 76
+dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
 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.
@@ -134,6 +134,7 @@ AC_DEFUN([gl_STDLIB_H_REQUIRE_DEFAULTS],
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_PTSNAME_R])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_PUTENV])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_QSORT_R])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_RAND])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_RANDOM])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_RANDOM_R])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_REALLOCARRAY])
@@ -237,6 +238,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
   REPLACE_PTSNAME_R=0;       AC_SUBST([REPLACE_PTSNAME_R])
   REPLACE_PUTENV=0;          AC_SUBST([REPLACE_PUTENV])
   REPLACE_QSORT_R=0;         AC_SUBST([REPLACE_QSORT_R])
+  REPLACE_RAND=0;            AC_SUBST([REPLACE_RAND])
   REPLACE_RANDOM=0;          AC_SUBST([REPLACE_RANDOM])
   REPLACE_RANDOM_R=0;        AC_SUBST([REPLACE_RANDOM_R])
   REPLACE_REALLOC_FOR_REALLOC_GNU=0;    
AC_SUBST([REPLACE_REALLOC_FOR_REALLOC_GNU])
diff --git a/m4/stpcpy.m4 b/m4/stpcpy.m4
index f3acbee7be9..04c8bbe4c94 100644
--- a/m4/stpcpy.m4
+++ b/m4/stpcpy.m4
@@ -1,5 +1,5 @@
 # stpcpy.m4 serial 11
-dnl Copyright (C) 2002, 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002, 2007, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/string_h.m4 b/m4/string_h.m4
index 7f51391cbff..9ea748cc774 100644
--- a/m4/string_h.m4
+++ b/m4/string_h.m4
@@ -1,11 +1,11 @@
 # Configure a GNU-like replacement for <string.h>.
 
-# Copyright (C) 2007-2023 Free Software Foundation, Inc.
+# Copyright (C) 2007-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 37
+# serial 39
 
 # Written by Paul Eggert.
 
@@ -132,6 +132,7 @@ AC_DEFUN([gl_STRING_H_DEFAULTS],
   REPLACE_MEMCHR=0;             AC_SUBST([REPLACE_MEMCHR])
   REPLACE_MEMMEM=0;             AC_SUBST([REPLACE_MEMMEM])
   REPLACE_MEMPCPY=0;            AC_SUBST([REPLACE_MEMPCPY])
+  REPLACE_MEMSET_EXPLICIT=0;    AC_SUBST([REPLACE_MEMSET_EXPLICIT])
   REPLACE_STPCPY=0;             AC_SUBST([REPLACE_STPCPY])
   REPLACE_STPNCPY=0;            AC_SUBST([REPLACE_STPNCPY])
   REPLACE_STRCHRNUL=0;          AC_SUBST([REPLACE_STRCHRNUL])
@@ -146,5 +147,6 @@ AC_DEFUN([gl_STRING_H_DEFAULTS],
   REPLACE_STRERROR_R=0;         AC_SUBST([REPLACE_STRERROR_R])
   REPLACE_STRERRORNAME_NP=0;    AC_SUBST([REPLACE_STRERRORNAME_NP])
   REPLACE_STRSIGNAL=0;          AC_SUBST([REPLACE_STRSIGNAL])
+  REPLACE_STRVERSCMP=0;         AC_SUBST([REPLACE_STRVERSCMP])
   UNDEFINE_STRTOK_R=0;          AC_SUBST([UNDEFINE_STRTOK_R])
 ])
diff --git a/m4/strnlen.m4 b/m4/strnlen.m4
index d2cac59b6f2..3eac8e629d7 100644
--- a/m4/strnlen.m4
+++ b/m4/strnlen.m4
@@ -1,5 +1,5 @@
 # strnlen.m4 serial 14
-dnl Copyright (C) 2002-2003, 2005-2007, 2009-2023 Free Software Foundation,
+dnl Copyright (C) 2002-2003, 2005-2007, 2009-2024 Free Software Foundation,
 dnl Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
diff --git a/m4/strtoimax.m4 b/m4/strtoimax.m4
index db5cfb7aa9d..b58fa48ff6e 100644
--- a/m4/strtoimax.m4
+++ b/m4/strtoimax.m4
@@ -1,5 +1,5 @@
-# strtoimax.m4 serial 16
-dnl Copyright (C) 2002-2004, 2006, 2009-2023 Free Software Foundation, Inc.
+# strtoimax.m4 serial 17
+dnl Copyright (C) 2002-2004, 2006, 2009-2024 Free Software Foundation, Inc.
 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.
@@ -61,12 +61,12 @@ int main ()
          [gl_cv_func_strtoimax=yes],
          [gl_cv_func_strtoimax=no],
          [case "$host_os" in
-                    # Guess no on AIX 5.
-            aix5*)  gl_cv_func_strtoimax="guessing no" ;;
-                    # Guess yes on native Windows.
-            mingw*) gl_cv_func_strtoimax="guessing yes" ;;
-                    # Guess yes otherwise.
-            *)      gl_cv_func_strtoimax="guessing yes" ;;
+                               # Guess no on AIX 5.
+            aix5*)             gl_cv_func_strtoimax="guessing no" ;;
+                               # Guess yes on native Windows.
+            mingw* | windows*) gl_cv_func_strtoimax="guessing yes" ;;
+                               # Guess yes otherwise.
+            *)                 gl_cv_func_strtoimax="guessing yes" ;;
           esac
          ])
       ])
diff --git a/m4/strtoll.m4 b/m4/strtoll.m4
index a0cbc805bc9..130b9094d88 100644
--- a/m4/strtoll.m4
+++ b/m4/strtoll.m4
@@ -1,5 +1,5 @@
-# strtoll.m4 serial 11
-dnl Copyright (C) 2002, 2004, 2006, 2008-2023 Free Software Foundation, Inc.
+# strtoll.m4 serial 12
+dnl Copyright (C) 2002, 2004, 2006, 2008-2024 Free Software Foundation, Inc.
 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.
@@ -44,7 +44,7 @@ AC_DEFUN([gl_FUNC_STRTOLL],
          [gl_cv_func_strtoll_works=no],
          [case "$host_os" in
                                 # Guess no on native Windows.
-            mingw*)             gl_cv_func_strtoll_works="guessing no" ;;
+            mingw* | windows*)  gl_cv_func_strtoll_works="guessing no" ;;
                                 # Guess no on glibc systems.
             *-gnu* | gnu*)      gl_cv_func_strtoll_works="guessing no" ;;
                                 # Guess no on musl systems.
diff --git a/m4/symlink.m4 b/m4/symlink.m4
index 52d6c115ca5..62062cf1499 100644
--- a/m4/symlink.m4
+++ b/m4/symlink.m4
@@ -1,7 +1,7 @@
 # serial 10
 # See if we need to provide symlink replacement.
 
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/sys_random_h.m4 b/m4/sys_random_h.m4
index 01d5feebb31..b050d079b92 100644
--- a/m4/sys_random_h.m4
+++ b/m4/sys_random_h.m4
@@ -1,5 +1,5 @@
 # sys_random_h.m4 serial 8
-dnl Copyright (C) 2020-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2020-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/sys_select_h.m4 b/m4/sys_select_h.m4
index 4ec5ed7a09f..9e279fbab8d 100644
--- a/m4/sys_select_h.m4
+++ b/m4/sys_select_h.m4
@@ -1,5 +1,5 @@
 # sys_select_h.m4 serial 23
-dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/sys_socket_h.m4 b/m4/sys_socket_h.m4
index 98a10416cae..af524849f03 100644
--- a/m4/sys_socket_h.m4
+++ b/m4/sys_socket_h.m4
@@ -1,5 +1,5 @@
 # sys_socket_h.m4 serial 29
-dnl Copyright (C) 2005-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/sys_stat_h.m4 b/m4/sys_stat_h.m4
index ca57398aebd..75018537d57 100644
--- a/m4/sys_stat_h.m4
+++ b/m4/sys_stat_h.m4
@@ -1,5 +1,5 @@
 # sys_stat_h.m4 serial 42   -*- Autoconf -*-
-dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/sys_time_h.m4 b/m4/sys_time_h.m4
index 45a1f8b0240..dc5353f3785 100644
--- a/m4/sys_time_h.m4
+++ b/m4/sys_time_h.m4
@@ -1,7 +1,7 @@
 # Configure a replacement for <sys/time.h>.
 # serial 12
 
-# Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
diff --git a/m4/sys_types_h.m4 b/m4/sys_types_h.m4
index 627671fbdf7..37d0ccad403 100644
--- a/m4/sys_types_h.m4
+++ b/m4/sys_types_h.m4
@@ -1,5 +1,5 @@
 # sys_types_h.m4 serial 13
-dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2011-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/tempname.m4 b/m4/tempname.m4
index abed7991dab..31d35c83eb5 100644
--- a/m4/tempname.m4
+++ b/m4/tempname.m4
@@ -1,6 +1,6 @@
 #serial 5
 
-# Copyright (C) 2006-2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2006-2007, 2009-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
diff --git a/m4/time_h.m4 b/m4/time_h.m4
index 632d18fc071..32fade0f401 100644
--- a/m4/time_h.m4
+++ b/m4/time_h.m4
@@ -1,8 +1,8 @@
 # Configure a more-standard replacement for <time.h>.
 
-# Copyright (C) 2000-2001, 2003-2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2000-2001, 2003-2007, 2009-2024 Free Software Foundation, Inc.
 
-# serial 24
+# serial 25
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -175,5 +175,6 @@ AC_DEFUN([gl_TIME_H_DEFAULTS],
   REPLACE_TIME=0;                        AC_SUBST([REPLACE_TIME])
   REPLACE_TIMEGM=0;                      AC_SUBST([REPLACE_TIMEGM])
   REPLACE_TIMESPEC_GET=0;                AC_SUBST([REPLACE_TIMESPEC_GET])
+  REPLACE_TIMESPEC_GETRES=0;             AC_SUBST([REPLACE_TIMESPEC_GETRES])
   REPLACE_TZSET=0;                       AC_SUBST([REPLACE_TZSET])
 ])
diff --git a/m4/time_r.m4 b/m4/time_r.m4
index 4831eb26f90..4ee2175b690 100644
--- a/m4/time_r.m4
+++ b/m4/time_r.m4
@@ -1,6 +1,6 @@
 dnl Reentrant time functions: localtime_r, gmtime_r.
 
-dnl Copyright (C) 2003, 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003, 2006-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/time_rz.m4 b/m4/time_rz.m4
index d13bc06b7a0..c3b72b7603b 100644
--- a/m4/time_rz.m4
+++ b/m4/time_rz.m4
@@ -1,6 +1,6 @@
 dnl Time zone functions: tzalloc, localtime_rz, etc.
 
-dnl Copyright (C) 2015-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2015-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/timegm.m4 b/m4/timegm.m4
index 6da07807698..84336043e5d 100644
--- a/m4/timegm.m4
+++ b/m4/timegm.m4
@@ -1,5 +1,5 @@
 # timegm.m4 serial 16
-dnl Copyright (C) 2003, 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003, 2007, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/timer_time.m4 b/m4/timer_time.m4
index 437d1dc5428..10b7654d30f 100644
--- a/m4/timer_time.m4
+++ b/m4/timer_time.m4
@@ -1,5 +1,5 @@
 # timer_time.m4 serial 6
-dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2011-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/timespec.m4 b/m4/timespec.m4
index 95f475f2cc5..59a0db9966e 100644
--- a/m4/timespec.m4
+++ b/m4/timespec.m4
@@ -1,6 +1,6 @@
 #serial 15
 
-# Copyright (C) 2000-2001, 2003-2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2000-2001, 2003-2007, 2009-2024 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
diff --git a/m4/tm_gmtoff.m4 b/m4/tm_gmtoff.m4
index bc41de361cc..f2e51597fdf 100644
--- a/m4/tm_gmtoff.m4
+++ b/m4/tm_gmtoff.m4
@@ -1,5 +1,5 @@
 # tm_gmtoff.m4 serial 3
-dnl Copyright (C) 2002, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002, 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index 1c96158155a..e078bd617a7 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -1,5 +1,5 @@
-# unistd_h.m4 serial 94
-dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
+# unistd_h.m4 serial 95
+dnl Copyright (C) 2006-2024 Free Software Foundation, Inc.
 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.
@@ -234,6 +234,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   REPLACE_EXECVP=0;                  AC_SUBST([REPLACE_EXECVP])
   REPLACE_EXECVPE=0;                 AC_SUBST([REPLACE_EXECVPE])
   REPLACE_FACCESSAT=0;               AC_SUBST([REPLACE_FACCESSAT])
+  REPLACE_FCHDIR=0;                  AC_SUBST([REPLACE_FCHDIR])
   REPLACE_FCHOWNAT=0;                AC_SUBST([REPLACE_FCHOWNAT])
   REPLACE_FDATASYNC=0;               AC_SUBST([REPLACE_FDATASYNC])
   REPLACE_FTRUNCATE=0;               AC_SUBST([REPLACE_FTRUNCATE])
diff --git a/m4/unlocked-io.m4 b/m4/unlocked-io.m4
index 407c0bac832..558f57d809b 100644
--- a/m4/unlocked-io.m4
+++ b/m4/unlocked-io.m4
@@ -1,6 +1,6 @@
 # unlocked-io.m4 serial 16
 
-# Copyright (C) 1998-2006, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 1998-2006, 2009-2024 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
diff --git a/m4/utimens.m4 b/m4/utimens.m4
index 5f8606167a6..af03e6b52be 100644
--- a/m4/utimens.m4
+++ b/m4/utimens.m4
@@ -1,4 +1,4 @@
-dnl Copyright (C) 2003-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/utimensat.m4 b/m4/utimensat.m4
index 1a670bb7b78..e595b333d17 100644
--- a/m4/utimensat.m4
+++ b/m4/utimensat.m4
@@ -1,7 +1,7 @@
 # serial 11
 # See if we need to provide utimensat replacement.
 
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/utimes.m4 b/m4/utimes.m4
index 73b9a2da34e..05b23cbb736 100644
--- a/m4/utimes.m4
+++ b/m4/utimes.m4
@@ -1,7 +1,7 @@
 # Detect some bugs in glibc's implementation of utimes.
-# serial 8
+# serial 9
 
-dnl Copyright (C) 2003-2005, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003-2005, 2009-2024 Free Software Foundation, Inc.
 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.
@@ -144,11 +144,11 @@ main ()
        [gl_cv_func_working_utimes=yes],
        [gl_cv_func_working_utimes=no],
        [case "$host_os" in
-                   # Guess yes on musl systems.
-          *-musl*) gl_cv_func_working_utimes="guessing yes" ;;
-                   # Guess no on native Windows.
-          mingw*)  gl_cv_func_working_utimes="guessing no" ;;
-          *)       gl_cv_func_working_utimes="$gl_cross_guess_normal" ;;
+                             # Guess yes on musl systems.
+          *-musl*)           gl_cv_func_working_utimes="guessing yes" ;;
+                             # Guess no on native Windows.
+          mingw* | windows*) gl_cv_func_working_utimes="guessing no" ;;
+          *)                 
gl_cv_func_working_utimes="$gl_cross_guess_normal" ;;
         esac
        ])
     ])
diff --git a/m4/vararrays.m4 b/m4/vararrays.m4
index fd6230c2968..164bf0c49a9 100644
--- a/m4/vararrays.m4
+++ b/m4/vararrays.m4
@@ -4,7 +4,7 @@
 
 # From Paul Eggert
 
-# Copyright (C) 2001, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2009-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
diff --git a/m4/warnings.m4 b/m4/warnings.m4
index 9433cb523bf..d487636aa36 100644
--- a/m4/warnings.m4
+++ b/m4/warnings.m4
@@ -1,5 +1,5 @@
-# warnings.m4 serial 19
-dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
+# warnings.m4 serial 20
+dnl Copyright (C) 2008-2024 Free Software Foundation, Inc.
 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.
@@ -26,13 +26,13 @@ case $gl_positive in
 esac
 m4_pushdef([gl_Positive], [$gl_positive])])dnl
 AC_CACHE_CHECK([whether _AC_LANG compiler handles $1], [gl_Warn], [
-  gl_save_compiler_FLAGS="$gl_Flags"
+  gl_saved_compiler_FLAGS="$gl_Flags"
   AS_VAR_APPEND(m4_defn([gl_Flags]),
     [" $gl_unknown_warnings_are_errors ]m4_defn([gl_Positive])["])
   AC_LINK_IFELSE([m4_default([$4], [AC_LANG_PROGRAM([[]])])],
                  [AS_VAR_SET([gl_Warn], [yes])],
                  [AS_VAR_SET([gl_Warn], [no])])
-  gl_Flags="$gl_save_compiler_FLAGS"
+  gl_Flags="$gl_saved_compiler_FLAGS"
 ])
 AS_VAR_IF(gl_Warn, [yes], [$2], [$3])
 m4_popdef([gl_Positive])dnl
diff --git a/m4/wchar_t.m4 b/m4/wchar_t.m4
index 50bde08aecb..94353571b00 100644
--- a/m4/wchar_t.m4
+++ b/m4/wchar_t.m4
@@ -1,5 +1,5 @@
 # wchar_t.m4 serial 4 (gettext-0.18.2)
-dnl Copyright (C) 2002-2003, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-2003, 2008-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/xattr.m4 b/m4/xattr.m4
index 70bf0db4419..7f72a81eeab 100644
--- a/m4/xattr.m4
+++ b/m4/xattr.m4
@@ -1,7 +1,7 @@
 # xattr.m4 - check for Extended Attributes (Linux)
 # serial 7
 
-# Copyright (C) 2003-2023 Free Software Foundation, Inc.
+# Copyright (C) 2003-2024 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
diff --git a/m4/year2038.m4 b/m4/year2038.m4
index 78b267a088e..189a218bbb9 100644
--- a/m4/year2038.m4
+++ b/m4/year2038.m4
@@ -1,5 +1,5 @@
 # year2038.m4 serial 8
-dnl Copyright (C) 2017-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2017-2024 Free Software Foundation, Inc.
 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.
diff --git a/m4/zzgnulib.m4 b/m4/zzgnulib.m4
index 362102b6069..eed5ecbfe1e 100644
--- a/m4/zzgnulib.m4
+++ b/m4/zzgnulib.m4
@@ -1,5 +1,5 @@
 # zzgnulib.m4 serial 1
-dnl Copyright (C) 2020-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2020-2024 Free Software Foundation, Inc.
 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.
diff --git a/make-dist b/make-dist
index 2c4b6a79500..c8b0fcf4f24 100755
--- a/make-dist
+++ b/make-dist
@@ -1,7 +1,7 @@
 #!/bin/sh
 ### make-dist: create an Emacs distribution tar file from current srcdir
 
-## Copyright (C) 1995, 1997-1998, 2000-2023 Free Software Foundation,
+## Copyright (C) 1995, 1997-1998, 2000-2024 Free Software Foundation,
 ## Inc.
 
 ## This file is part of GNU Emacs.
@@ -358,6 +358,8 @@ possibly_non_vc_files="
   admin/charsets/jisx2131-filter
   src/config.in
   exec/configure exec/config.h.in
+  exec/config.sub exec/config.guess
+  exec/install-sh
   leim/small-ja-dic-option
 "$(
   find admin doc etc lisp \
diff --git a/modules/modhelp.py b/modules/modhelp.py
index 3ed75dbf628..80ebc79367a 100755
--- a/modules/modhelp.py
+++ b/modules/modhelp.py
@@ -2,7 +2,7 @@
 
 # Module helper script.
 
-# Copyright 2015-2023 Free Software Foundation, Inc.
+# Copyright 2015-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/msdos/ChangeLog.1 b/msdos/ChangeLog.1
index c58ff771084..8880336767c 100644
--- a/msdos/ChangeLog.1
+++ b/msdos/ChangeLog.1
@@ -1550,7 +1550,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1994-1999, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1994-1999, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/msdos/INSTALL b/msdos/INSTALL
index 4baf2b15ab1..9e379d7d235 100644
--- a/msdos/INSTALL
+++ b/msdos/INSTALL
@@ -1,6 +1,6 @@
 GNU Emacs Installation Guide for the DJGPP (a.k.a. MS-DOS) port
 
-Copyright (C) 1992, 1994, 1996-1997, 2000-2023 Free Software Foundation,
+Copyright (C) 1992, 1994, 1996-1997, 2000-2024 Free Software Foundation,
 Inc.
 See the end of the file for license conditions.
 
diff --git a/msdos/README b/msdos/README
index fb321273083..e9b7b62b498 100644
--- a/msdos/README
+++ b/msdos/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
@@ -10,7 +10,7 @@ The files emacs.ico and emacs.pif are for using the DJGPP 
version on
 Windows 3.X.  Since these are binary files, their copyright notice is
 reproduced here:
 
-# Copyright (C) 1993, 2002-2022 Free Software Foundation, Inc.
+# Copyright (C) 1993, 2002-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/msdos/autogen/Makefile.in b/msdos/autogen/Makefile.in
index df9b7797989..18403250875 100644
--- a/msdos/autogen/Makefile.in
+++ b/msdos/autogen/Makefile.in
@@ -1,7 +1,7 @@
 # Makefile.in generated by automake 1.11.1 from Makefile.am.
 # @configure_input@
 
-# Copyright (C) 1994-2009, 2013-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994-2009, 2013-2024 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
diff --git a/msdos/autogen/config.in b/msdos/autogen/config.in
index 88728cb309c..f6c83bdb4b8 100644
--- a/msdos/autogen/config.in
+++ b/msdos/autogen/config.in
@@ -2,7 +2,7 @@
 
 /* GNU Emacs site configuration template file.
 
-Copyright (C) 1988, 1993-1994, 1999-2002, 2004-2023 Free Software
+Copyright (C) 1988, 1993-1994, 1999-2002, 2004-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/msdos/depfiles.bat b/msdos/depfiles.bat
index 269a5d07181..17a7faee147 100644
--- a/msdos/depfiles.bat
+++ b/msdos/depfiles.bat
@@ -1,7 +1,7 @@
 @echo off
 rem   ----------------------------------------------------------------------
 rem   Auxiliary script for MSDOS, run by ../config.bat
-rem   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+rem   Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 rem   This file is part of GNU Emacs.
 
diff --git a/msdos/inttypes.h b/msdos/inttypes.h
index ef646eef415..e33bdbafb87 100644
--- a/msdos/inttypes.h
+++ b/msdos/inttypes.h
@@ -1,6 +1,6 @@
 /* Replacement inttypes.h file for building GNU Emacs on MS-DOS with DJGPP.
 
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/msdos/langinfo.h b/msdos/langinfo.h
index 018497af437..67b0976bf46 100644
--- a/msdos/langinfo.h
+++ b/msdos/langinfo.h
@@ -1,6 +1,6 @@
 /* Replacement langinfo.h file for building GNU Emacs on MS-DOS with DJGPP.
 
-Copyright (C) 2021-2023 Free Software Foundation, Inc.
+Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/msdos/mainmake.v2 b/msdos/mainmake.v2
index 4a1e10b336f..b8bb7a332f0 100644
--- a/msdos/mainmake.v2
+++ b/msdos/mainmake.v2
@@ -1,6 +1,6 @@
 # Top-level Makefile for Emacs under MS-DOS/DJGPP v2.0 or higher. 
-*-makefile-*-
 
-# Copyright (C) 1996-2023 Free Software Foundation, Inc.
+# Copyright (C) 1996-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/msdos/sed1v2.inp b/msdos/sed1v2.inp
index d299ec17574..632c45a16b6 100644
--- a/msdos/sed1v2.inp
+++ b/msdos/sed1v2.inp
@@ -2,7 +2,7 @@
 # Configuration script for src/Makefile under DJGPP v2.x
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 1996-1997, 1999-2023 Free Software Foundation, Inc.
+# Copyright (C) 1996-1997, 1999-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/msdos/sed1x.inp b/msdos/sed1x.inp
index 1a8e362f951..721eaa447f3 100644
--- a/msdos/sed1x.inp
+++ b/msdos/sed1x.inp
@@ -2,7 +2,7 @@
 # Extra configuration script for src/makefile for DesqView/X
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 1994-1997, 1999-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994-1997, 1999-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/msdos/sed2v2.inp b/msdos/sed2v2.inp
index 58c1663dda0..9f8bca1a987 100644
--- a/msdos/sed2v2.inp
+++ b/msdos/sed2v2.inp
@@ -2,7 +2,7 @@
 # Configuration script for src/config.h under DJGPP v2.x
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 1993-1997, 1999-2000, 2002-2023 Free Software
+# Copyright (C) 1993-1997, 1999-2000, 2002-2024 Free Software
 # Foundation, Inc.
 #
 # This file is part of GNU Emacs.
@@ -27,7 +27,7 @@
 #ifndef MSDOS\
 #define MSDOS\
 #endif
-/^#undef COPYRIGHT *$/s/^.*$/#define COPYRIGHT "Copyright (C) 2023 Free 
Software Foundation, Inc."/
+/^#undef COPYRIGHT *$/s/^.*$/#define COPYRIGHT "Copyright (C) 2024 Free 
Software Foundation, Inc."/
 /^#undef DIRECTORY_SEP *$/s!^.*$!#define DIRECTORY_SEP '/'!
 /^#undef DOS_NT *$/s/^.*$/#define DOS_NT/
 /^#undef FLOAT_CHECK_DOMAIN *$/s/^.*$/#define FLOAT_CHECK_DOMAIN/
diff --git a/msdos/sed2x.inp b/msdos/sed2x.inp
index 4c38952b11c..bcbed8fd0c7 100644
--- a/msdos/sed2x.inp
+++ b/msdos/sed2x.inp
@@ -2,7 +2,7 @@
 # Extra configuration script for src/config.h for DesqView/X
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/msdos/sed3v2.inp b/msdos/sed3v2.inp
index 0699fb68b02..9982a5e638f 100644
--- a/msdos/sed3v2.inp
+++ b/msdos/sed3v2.inp
@@ -2,7 +2,7 @@
 # Configuration script for lib-src/makefile under DJGPP v2
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 1996, 1998, 2000-2023 Free Software Foundation, Inc.
+# Copyright (C) 1996, 1998, 2000-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/msdos/sed4.inp b/msdos/sed4.inp
index 1a579b78773..ca0d370b23a 100644
--- a/msdos/sed4.inp
+++ b/msdos/sed4.inp
@@ -2,7 +2,7 @@
 # Configuration script for src/paths.h
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/msdos/sed5x.inp b/msdos/sed5x.inp
index 250ac9b4adb..db32a74c43a 100644
--- a/msdos/sed5x.inp
+++ b/msdos/sed5x.inp
@@ -2,7 +2,7 @@
 # Configuration script for oldxmenu/makefile for DesqView/X
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/msdos/sed6.inp b/msdos/sed6.inp
index ec04b8f0af7..43c4ed8bf75 100644
--- a/msdos/sed6.inp
+++ b/msdos/sed6.inp
@@ -3,7 +3,7 @@
 # doc/lispintro/Makefile, and doc/misc/Makefile under DJGPP v2.x
 # ---------------------------------------------------------------------------
 #
-# Copyright (C) 1997, 2000-2023 Free Software Foundation, Inc.
+# Copyright (C) 1997, 2000-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/msdos/sedadmin.inp b/msdos/sedadmin.inp
index a2d652ac8a3..185b34c35b3 100644
--- a/msdos/sedadmin.inp
+++ b/msdos/sedadmin.inp
@@ -2,7 +2,7 @@
 # Configuration script for admin/unidata/Makefile under DJGPP v2.x
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 2014-2023 Free Software Foundation, Inc.
+# Copyright (C) 2014-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/msdos/sedalloc.inp b/msdos/sedalloc.inp
index 716bc6c0e8e..f058f8b6e5e 100644
--- a/msdos/sedalloc.inp
+++ b/msdos/sedalloc.inp
@@ -2,7 +2,7 @@
 # Configuration script for SYSTEM_MALLOC/REL_ALLOC in src/config.h
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 2008-2023 Free Software Foundation, Inc.
+# Copyright (C) 2008-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/msdos/sedleim.inp b/msdos/sedleim.inp
index d759fc40714..d43fbef4672 100644
--- a/msdos/sedleim.inp
+++ b/msdos/sedleim.inp
@@ -2,7 +2,7 @@
 # Configuration script for leim/Makefile under DJGPP v2.x
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 1999-2023 Free Software Foundation, Inc.
+# Copyright (C) 1999-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
@@ -41,3 +41,7 @@ RUN_EMACS = ${EMACS} -batch --no-site-file --no-site-lisp
 /^MKDIR_P *=/s,@MKDIR_P@,gmkdir -p,
 
 /^\${leimdir}\/quail \${leimdir}\/ja-dic: *$/s|\${leimdir}/|$(rel_leimdir)\\|
+
+# Should an option to enable this be provided by config.bat?
+/^SMALL_JA_DIC *=/s/@SMALL_JA_DIC@//
+/^small-ja-dic-option: /s|../config.status||
diff --git a/msdos/sedlibcf.inp b/msdos/sedlibcf.inp
index 8966e799a38..8f7aa33f823 100644
--- a/msdos/sedlibcf.inp
+++ b/msdos/sedlibcf.inp
@@ -5,7 +5,7 @@
 # files whose names are invalid on DOS 8+3 filesystems.
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 2011-2023 Free Software Foundation, Inc.
+# Copyright (C) 2011-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/msdos/sedlibmk.inp b/msdos/sedlibmk.inp
index 664bfaf693c..1d8ae778168 100644
--- a/msdos/sedlibmk.inp
+++ b/msdos/sedlibmk.inp
@@ -2,7 +2,7 @@
 # Configuration script for lib/Makefile under DJGPP v2.x
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 2011-2023 Free Software Foundation, Inc.
+# Copyright (C) 2011-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/msdos/sedlisp.inp b/msdos/sedlisp.inp
index 89d11fb44e3..e9033098ce1 100644
--- a/msdos/sedlisp.inp
+++ b/msdos/sedlisp.inp
@@ -2,7 +2,7 @@
 # Configuration script for lisp/Makefile under DJGPP v2.x
 # ----------------------------------------------------------------------
 #
-# Copyright (C) 2000-2023 Free Software Foundation, Inc.
+# Copyright (C) 2000-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/nextstep/ChangeLog.1 b/nextstep/ChangeLog.1
index cd6bfbfbbbe..34de7b77b4c 100644
--- a/nextstep/ChangeLog.1
+++ b/nextstep/ChangeLog.1
@@ -312,7 +312,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2008-2023 Free Software Foundation, Inc.
+  Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/nextstep/INSTALL b/nextstep/INSTALL
index cce19a41ed8..174c7e105e2 100644
--- a/nextstep/INSTALL
+++ b/nextstep/INSTALL
@@ -1,4 +1,4 @@
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/nextstep/Makefile.in b/nextstep/Makefile.in
index 89318a1efa8..5811bf87342 100644
--- a/nextstep/Makefile.in
+++ b/nextstep/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-## Copyright (C) 2012-2023 Free Software Foundation, Inc.
+## Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ## This file is part of GNU Emacs.
 
@@ -46,11 +46,7 @@ ns_check_file = @ns_appdir@/@ns_check_file@
 
 .PHONY: all
 
-ifeq ($(DUMPING),pdumper)
-ns_pdmp_target = ${ns_applibexecdir}/Emacs.pdmp
-endif
-
-all: ${ns_appdir} ${ns_appbindir}/Emacs ${ns_pdmp_target}
+all: ${ns_appdir} ${ns_appbindir}/Emacs
 
 ${ns_check_file}: ${ns_appdir}
 
@@ -71,12 +67,6 @@ ${ns_appbindir}/Emacs: ${ns_appdir} ${ns_check_file} 
../src/emacs${EXEEXT}
        ${MKDIR_P} ${ns_appbindir}
        cp -f ../src/emacs${EXEEXT} $@
 
-${ns_applibexecdir}/Emacs.pdmp: ${ns_appdir} ${ns_check_file} 
../src/emacs${EXEEXT}.pdmp
-       ${MKDIR_P} ${ns_applibexecdir}
-ifeq (${ns_self_contained},no)
-       cp -f ../src/emacs${EXEEXT}.pdmp $@
-endif
-
 .PHONY: FORCE
 
 ../src/emacs${EXEEXT}: FORCE
diff --git a/nextstep/README b/nextstep/README
index 3fe1b9421f7..9bf3e6ffbc0 100644
--- a/nextstep/README
+++ b/nextstep/README
@@ -105,7 +105,7 @@ future development.
 
 
 ----------------------------------------------------------------------
-Copyright 2008-2023 Free Software Foundation, Inc.
+Copyright 2008-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nextstep/templates/Info.plist.in b/nextstep/templates/Info.plist.in
index 0f95bcebb24..beddbf4a893 100644
--- a/nextstep/templates/Info.plist.in
+++ b/nextstep/templates/Info.plist.in
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/ChangeLog.1 b/nt/ChangeLog.1
index 1e54afd7a1d..0a3f96c01eb 100644
--- a/nt/ChangeLog.1
+++ b/nt/ChangeLog.1
@@ -3548,7 +3548,7 @@
 ;; add-log-time-zone-rule: t
 ;; End:
 
-  Copyright (C) 1995-1999, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1995-1999, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/nt/INSTALL b/nt/INSTALL
index 3b465ba494c..77626f8a343 100644
--- a/nt/INSTALL
+++ b/nt/INSTALL
@@ -1,7 +1,7 @@
                    Building and Installing Emacs on MS-Windows
                           using the MSYS and MinGW tools
 
-  Copyright (C) 2013-2023 Free Software Foundation, Inc.
+  Copyright (C) 2013-2024 Free Software Foundation, Inc.
   See the end of the file for license conditions.
 
 The MSYS/MinGW build described here is supported on versions of
diff --git a/nt/INSTALL.W64 b/nt/INSTALL.W64
index fe5f74e3209..2aa05ea0062 100644
--- a/nt/INSTALL.W64
+++ b/nt/INSTALL.W64
@@ -1,7 +1,7 @@
          Building and Installing Emacs on 64-bit MS-Windows
                      using MSYS2 and MinGW-w64
 
-  Copyright (c) 2015-2023 Free Software Foundation, Inc.
+  Copyright (c) 2015-2024 Free Software Foundation, Inc.
   See the end of the file for license conditions.
 
 This document describes how to compile a 64-bit GNU Emacs using MSYS2
diff --git a/nt/Makefile.in b/nt/Makefile.in
index 0c3192a63e6..865e3d807e8 100644
--- a/nt/Makefile.in
+++ b/nt/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 2013-2023 Free Software Foundation, Inc.
+# Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/nt/README b/nt/README
index 118ead25fce..694e8854446 100644
--- a/nt/README
+++ b/nt/README
@@ -1,6 +1,6 @@
             Emacs for Windows NT/2000 and Windows 95/98/ME
 
-  Copyright (C) 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 2001-2024 Free Software Foundation, Inc.
   See the end of the file for license conditions.
 
   This directory contains support for compiling and running GNU Emacs on
diff --git a/nt/README.W32 b/nt/README.W32
index da1ede1ea4d..98657246f67 100644
--- a/nt/README.W32
+++ b/nt/README.W32
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
                Emacs version 30.0.50 for MS-Windows
diff --git a/nt/addpm.c b/nt/addpm.c
index 1f137144aac..6aee45d8149 100644
--- a/nt/addpm.c
+++ b/nt/addpm.c
@@ -1,5 +1,5 @@
 /* Add entries to the GNU Emacs Program Manager folder.
-   Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/cmdproxy.c b/nt/cmdproxy.c
index d669fa1a391..0500b653bb2 100644
--- a/nt/cmdproxy.c
+++ b/nt/cmdproxy.c
@@ -1,5 +1,5 @@
 /* Proxy shell designed for use with Emacs on Windows 95 and NT.
-   Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 
    Accepts subset of Unix sh(1) command-line options, for compatibility
    with elisp code written for Unix.  When possible, executes external
diff --git a/msdos/depfiles.bat b/nt/configure.bat
old mode 100644
new mode 100755
similarity index 62%
copy from msdos/depfiles.bat
copy to nt/configure.bat
index 269a5d07181..6e2ebe5357e
--- a/msdos/depfiles.bat
+++ b/nt/configure.bat
@@ -1,7 +1,7 @@
 @echo off
 rem   ----------------------------------------------------------------------
-rem   Auxiliary script for MSDOS, run by ../config.bat
-rem   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+rem   This was the old configuration script for MS Windows operating systems
+rem   Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 rem   This file is part of GNU Emacs.
 
@@ -19,7 +19,8 @@ rem   You should have received a copy of the GNU General 
Public License
 rem   along with GNU Emacs.  If not, see https://www.gnu.org/licenses/.
 
 rem   ----------------------------------------------------------------------
-
-echo %1 | sed -e "s,\(.*\)\.c,@if not exist deps\\\1.d echo # dummy > 
deps\\\1.d," > tdepfile.bat
-call tdepfile
-del tdepfile.bat
+echo ****************************************************************
+echo *** THIS METHOD OF BUILDING EMACS IS NO LONGER SUPPORTED.     **
+echo *** INSTEAD, FOLLOW THE INSTRUCTIONS IN THE FILE INSTALL.     **
+echo *** IN THE SAME DIRECTORY AS THIS BATCH FILE.                 **
+echo ****************************************************************
diff --git a/nt/ddeclient.c b/nt/ddeclient.c
index 1fbd2da4c13..2862cb30d71 100644
--- a/nt/ddeclient.c
+++ b/nt/ddeclient.c
@@ -1,5 +1,5 @@
 /* Simple client interface to DDE servers.
-   Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/epaths.nt b/nt/epaths.nt
index 6069004cd13..143b6110a1c 100644
--- a/nt/epaths.nt
+++ b/nt/epaths.nt
@@ -12,7 +12,7 @@
    the host system (e.g., i686-pc-mingw32), and @SRC@ by the root of
    the Emacs source tree used to build Emacs.  */
 /*
-Copyright (C) 1993, 1995, 1997, 1999, 2001-2023 Free Software
+Copyright (C) 1993, 1995, 1997, 1999, 2001-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/nt/gnulib-cfg.mk b/nt/gnulib-cfg.mk
index fe29e942d80..5b1c2c88ba5 100644
--- a/nt/gnulib-cfg.mk
+++ b/nt/gnulib-cfg.mk
@@ -1,6 +1,6 @@
 # Configurations for ../lib/gnulib.mk.
 #
-# Copyright 2017-2023 Free Software Foundation, Inc.
+# Copyright 2017-2024 Free Software Foundation, Inc.
 #
 # 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
diff --git a/nt/icons/README b/nt/icons/README
index dbb28fcfee1..9787d8b6017 100644
--- a/nt/icons/README
+++ b/nt/icons/README
@@ -2,13 +2,13 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
 
 File: emacs.ico
 Author: Kentaro Ohkouchi <nanasess@fsm.ne.jp>
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later
 
 
 File: emacs22.ico
 Author: Andrew Zhilin
-Copyright (C) 2005-2023 Free Software Foundation, Inc.
+Copyright (C) 2005-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
 
 
@@ -17,7 +17,7 @@ Files: gnu2a32.ico gnu2a32t.ico gnu2b48.ico gnu2b48t.ico
        gnu5w32.ico gnu5w32t.ico gnu6w48.ico gnu6w48t.ico
        gnu7.ico    gnu8.ico     gnu9.ico
 Author: Rob Davenport <rgd at bigfoot.com>
-Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
 License: GNU General Public License version 3 or later (see COPYING)
 
   <http://users.adelphia.net/~rob.davenport/gnuicons.html>
diff --git a/nt/inc/grp.h b/nt/inc/grp.h
index 1a5f0276ca1..695d28b4292 100644
--- a/nt/inc/grp.h
+++ b/nt/inc/grp.h
@@ -1,6 +1,6 @@
 /* Replacement grp.h file for building GNU Emacs on Windows.
 
-Copyright (C) 2003-2023 Free Software Foundation, Inc.
+Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/inc/inttypes.h b/nt/inc/inttypes.h
index 657bd960758..a8552b99b18 100644
--- a/nt/inc/inttypes.h
+++ b/nt/inc/inttypes.h
@@ -1,6 +1,6 @@
 /* Replacement inttypes.h file for building GNU Emacs on Windows with MSVC.
 
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/inc/langinfo.h b/nt/inc/langinfo.h
index 86d925bd13f..0315e52d576 100644
--- a/nt/inc/langinfo.h
+++ b/nt/inc/langinfo.h
@@ -1,6 +1,6 @@
 /* Replacement langinfo.h file for building GNU Emacs on Windows.
 
-Copyright (C) 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h
index c57549c96e7..cea0b072723 100644
--- a/nt/inc/ms-w32.h
+++ b/nt/inc/ms-w32.h
@@ -1,6 +1,6 @@
 /* System description file for Windows NT.
 
-Copyright (C) 1993-1995, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1995, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/inc/nl_types.h b/nt/inc/nl_types.h
index 17debcc5b64..541a82c5cc1 100644
--- a/nt/inc/nl_types.h
+++ b/nt/inc/nl_types.h
@@ -1,6 +1,6 @@
 /* Replacement nl_types.h file for building GNU Emacs on Windows.
 
-Copyright (C) 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/inc/stdint.h b/nt/inc/stdint.h
index c9b667f5759..194d6104fdb 100644
--- a/nt/inc/stdint.h
+++ b/nt/inc/stdint.h
@@ -1,6 +1,6 @@
 /* Replacement stdint.h file for building GNU Emacs on Windows.
 
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/inc/sys/resource.h b/nt/inc/sys/resource.h
index 72d855e6a82..b64f95ee660 100644
--- a/nt/inc/sys/resource.h
+++ b/nt/inc/sys/resource.h
@@ -1,6 +1,6 @@
 /* A limited emulation of sys/resource.h.
 
-Copyright (C) 2016-2023 Free Software Foundation, Inc.
+Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/inc/sys/socket.h b/nt/inc/sys/socket.h
index 43a24797b4c..5ecec24d04b 100644
--- a/nt/inc/sys/socket.h
+++ b/nt/inc/sys/socket.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/inc/sys/stat.h b/nt/inc/sys/stat.h
index 0eb178dc0c9..cdd19ceeff4 100644
--- a/nt/inc/sys/stat.h
+++ b/nt/inc/sys/stat.h
@@ -1,7 +1,7 @@
 /* sys/stat.h supplied with MSVCRT uses too narrow data types for
    inode and user/group id, so we replace them with our own.
 
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/inc/sys/wait.h b/nt/inc/sys/wait.h
index 6f49c055fb7..23d17444bbc 100644
--- a/nt/inc/sys/wait.h
+++ b/nt/inc/sys/wait.h
@@ -1,6 +1,6 @@
 /* A limited emulation of sys/wait.h on Posix systems.
 
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/nt/preprep.c b/nt/preprep.c
new file mode 100644
index 00000000000..d1c4f2136cc
--- /dev/null
+++ b/nt/preprep.c
@@ -0,0 +1,830 @@
+/* Pre-process emacs.exe for profiling by MSVC.
+   Copyright (C) 1999, 2001-2024 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/>.
+
+
+   Andrew Innes <andrewi@harlequin.co.uk>       16-Jan-1999
+     based on code from addsection.c
+*/
+
+#define DEFER_MS_W32_H
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#if defined(__GNUC__) && !defined(MINGW_W64)
+#define _ANONYMOUS_UNION
+#define _ANONYMOUS_STRUCT
+#endif
+#include <windows.h>
+
+/* Include relevant definitions from IMAGEHLP.H, which can be found
+   in \\win32sdk\mstools\samples\image\include\imagehlp.h. */
+
+PIMAGE_NT_HEADERS (__stdcall * pfnCheckSumMappedFile) (LPVOID BaseAddress,
+                                                      DWORD_PTR FileLength,
+                                                      PDWORD_PTR HeaderSum,
+                                                      PDWORD_PTR CheckSum);
+
+#undef min
+#undef max
+#define min(x, y) (((x) < (y)) ? (x) : (y))
+#define max(x, y) (((x) > (y)) ? (x) : (y))
+
+
+/* File handling.  */
+
+typedef struct file_data {
+  const char    *name;
+  unsigned long  size;
+  HANDLE         file;
+  HANDLE         file_mapping;
+  unsigned char *file_base;
+} file_data;
+
+int
+open_input_file (file_data *p_file, const char *filename)
+{
+  HANDLE file;
+  HANDLE file_mapping;
+  void  *file_base;
+  unsigned long size, upper_size;
+
+  file = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL,
+                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+  if (file == INVALID_HANDLE_VALUE)
+    return FALSE;
+
+  size = GetFileSize (file, &upper_size);
+  file_mapping = CreateFileMapping (file, NULL, PAGE_READONLY,
+                                   0, size, NULL);
+  if (!file_mapping)
+    return FALSE;
+
+  file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size);
+  if (file_base == 0)
+    return FALSE;
+
+  p_file->name = filename;
+  p_file->size = size;
+  p_file->file = file;
+  p_file->file_mapping = file_mapping;
+  p_file->file_base = file_base;
+
+  return TRUE;
+}
+
+int
+open_output_file (file_data *p_file, const char *filename, unsigned long size)
+{
+  HANDLE file;
+  HANDLE file_mapping;
+  void  *file_base;
+
+  file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+                    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+  if (file == INVALID_HANDLE_VALUE)
+    return FALSE;
+
+  file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE,
+                                   0, size, NULL);
+  if (!file_mapping)
+    return FALSE;
+
+  file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size);
+  if (file_base == 0)
+    return FALSE;
+
+  p_file->name = filename;
+  p_file->size = size;
+  p_file->file = file;
+  p_file->file_mapping = file_mapping;
+  p_file->file_base = file_base;
+
+  return TRUE;
+}
+
+int
+open_inout_file (file_data *p_file, const char *filename)
+{
+  HANDLE file;
+  HANDLE file_mapping;
+  void  *file_base;
+  unsigned long size, upper_size;
+
+  file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+  if (file == INVALID_HANDLE_VALUE)
+    return FALSE;
+
+  size = GetFileSize (file, &upper_size);
+  file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE,
+                                   0, size, NULL);
+  if (!file_mapping)
+    return FALSE;
+
+  file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size);
+  if (file_base == 0)
+    return FALSE;
+
+  p_file->name = filename;
+  p_file->size = size;
+  p_file->file = file;
+  p_file->file_mapping = file_mapping;
+  p_file->file_base = file_base;
+
+  return TRUE;
+}
+
+/* Close the system structures associated with the given file.  */
+void
+close_file_data (file_data *p_file)
+{
+  UnmapViewOfFile (p_file->file_base);
+  CloseHandle (p_file->file_mapping);
+  /* For the case of output files, set final size.  */
+  SetFilePointer (p_file->file, p_file->size, NULL, FILE_BEGIN);
+  SetEndOfFile (p_file->file);
+  CloseHandle (p_file->file);
+}
+
+
+/* Routines to manipulate NT executable file sections.  */
+
+unsigned long
+get_unrounded_section_size (PIMAGE_SECTION_HEADER p_section)
+{
+  /* The true section size, before rounding, for an initialized data or
+     code section.  (Supposedly some linkers swap the meaning of these
+     two values.)  */
+  return min (p_section->SizeOfRawData,
+             p_section->Misc.VirtualSize);
+}
+
+/* Return pointer to section header for named section. */
+IMAGE_SECTION_HEADER *
+find_section (const char *name, IMAGE_NT_HEADERS *nt_header)
+{
+  PIMAGE_SECTION_HEADER section;
+  int i;
+
+  section = IMAGE_FIRST_SECTION (nt_header);
+
+  for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
+    {
+      if (strcmp (section->Name, name) == 0)
+       return section;
+      section++;
+    }
+  return NULL;
+}
+
+/* Return pointer to section header for section containing the given
+   relative virtual address. */
+IMAGE_SECTION_HEADER *
+rva_to_section (DWORD_PTR rva, IMAGE_NT_HEADERS * nt_header)
+{
+  PIMAGE_SECTION_HEADER section;
+  int i;
+
+  section = IMAGE_FIRST_SECTION (nt_header);
+
+  for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
+    {
+      /* Some linkers (eg. the NT SDK linker I believe) swapped the
+        meaning of these two values - or rather, they ignored
+        VirtualSize entirely and always set it to zero.  This affects
+        some very old exes (eg. gzip dated Dec 1993).  Since
+        w32_executable_type relies on this function to work reliably,
+        we need to cope with this.  */
+      DWORD_PTR real_size = max (section->SizeOfRawData,
+                            section->Misc.VirtualSize);
+      if (rva >= section->VirtualAddress
+         && rva < section->VirtualAddress + real_size)
+       return section;
+      section++;
+    }
+  return NULL;
+}
+
+/* Return pointer to section header for section containing the given
+   offset in its raw data area. */
+IMAGE_SECTION_HEADER *
+offset_to_section (DWORD_PTR offset, IMAGE_NT_HEADERS * nt_header)
+{
+  PIMAGE_SECTION_HEADER section;
+  int i;
+
+  section = IMAGE_FIRST_SECTION (nt_header);
+
+  for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
+    {
+      if (offset >= section->PointerToRawData
+         && offset < section->PointerToRawData + section->SizeOfRawData)
+       return section;
+      section++;
+    }
+  return NULL;
+}
+
+/* Return offset to an object in dst, given offset in src.  We assume
+   there is at least one section in both src and dst images, and that
+   the some sections may have been added to dst (after sections in src).  */
+static DWORD_PTR
+relocate_offset (DWORD_PTR offset,
+                IMAGE_NT_HEADERS * src_nt_header,
+                IMAGE_NT_HEADERS * dst_nt_header)
+{
+  PIMAGE_SECTION_HEADER src_section = IMAGE_FIRST_SECTION (src_nt_header);
+  PIMAGE_SECTION_HEADER dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
+  int i = 0;
+
+  while (offset >= src_section->PointerToRawData)
+    {
+      if (offset < src_section->PointerToRawData + src_section->SizeOfRawData)
+       break;
+      i++;
+      if (i == src_nt_header->FileHeader.NumberOfSections)
+       {
+         /* Handle offsets after the last section.  */
+         dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
+         dst_section += dst_nt_header->FileHeader.NumberOfSections - 1;
+         while (dst_section->PointerToRawData == 0)
+           dst_section--;
+         while (src_section->PointerToRawData == 0)
+           src_section--;
+         return offset
+           + (dst_section->PointerToRawData + dst_section->SizeOfRawData)
+           - (src_section->PointerToRawData + src_section->SizeOfRawData);
+       }
+      src_section++;
+      dst_section++;
+    }
+  return offset +
+    (dst_section->PointerToRawData - src_section->PointerToRawData);
+}
+
+#define OFFSET_TO_RVA(offset, section) \
+  ((section)->VirtualAddress + ((DWORD_PTR)(offset) - 
(section)->PointerToRawData))
+
+#define RVA_TO_OFFSET(rva, section) \
+  ((section)->PointerToRawData + ((DWORD_PTR)(rva) - 
(section)->VirtualAddress))
+
+#define RVA_TO_SECTION_OFFSET(rva, section) \
+  ((DWORD_PTR)(rva) - (section)->VirtualAddress)
+
+#define RVA_TO_PTR(var,section,filedata) \
+  ((void *)((unsigned char *)(RVA_TO_OFFSET(var,section) + 
(filedata)->file_base)))
+
+/* Convert address in executing image to RVA.  */
+#define PTR_TO_RVA(ptr) ((DWORD_PTR)(ptr) - (DWORD_PTR) GetModuleHandle (NULL))
+
+#define PTR_TO_OFFSET(ptr, pfile_data) \
+          ((unsigned const char *)(ptr) - (pfile_data)->file_base)
+
+#define OFFSET_TO_PTR(offset, pfile_data) \
+          ((pfile_data)->file_base + (DWORD_PTR)(offset))
+
+#define ROUND_UP(p, align) \
+         (((DWORD_PTR)(p) + (align)-1) & ~((DWORD_PTR)(align)-1))
+#define ROUND_DOWN(p, align) ((DWORD_PTR)(p) & ~((DWORD_PTR)(align)-1))
+
+
+/* The MSVC prep program generates a ._xe file from .exe, where relevant
+   function calls etc have been patched to go through thunks (generated
+   by prep) that record timing/call information.  Because the thunks
+   need to make references to functions imported from profile.dll, the
+   import table must be expanded; the end result is that all the
+   sections following .rdata are relocated to higher RVAs (add a final
+   code section is added holding all the thunks).  The .reloc section is
+   also expanded, so that the thunks themselves are relocatable.
+
+   It is this relocation which kills emacs._xe, because the dumped heap
+   pointers aren't relocated, because there is no relocation data for
+   either the relevant global/static variables or the heap section
+   itself, both of which contain pointers into the heap.  [Note that
+   static variables which aren't initialized during linking may become
+   initialized with heap pointers, or even pointers to other static
+   variables, because of dumping.]
+
+   We could potentially generate the relocation data ourselves by making
+   two versions of temacs, one with an extra dummy section before
+   EMHEAP to offset it, and then compare the dumped executables from
+   both.  That is a lot of work though, and it doesn't solve the problem
+   of dumped pointers to static variables, which also can be relocated.
+
+   A better solution is to pre-process emacs.exe so that the .rdata and
+   .reloc sections are moved to the end of the section table, and thus
+   prep won't relocate anything else.  (Of course, we leave "dead"
+   copies of these two sections in place, so that the virtual address of
+   everything else is unaffected.)  Relocating the .reloc data is
+   trivial - we just update the IMAGE_BASE_RELOCATION address in the
+   header (the data itself doesn't change).  Relocating the import table
+   is more complicated though, because the calls to imported functions
+   must be patched up.  That requires us to selectively apply the base
+   relocations when we encounter references to imported functions (or
+   variables) in other sections, but at least the base relocations are
+   easy to parse.  */
+
+static void
+copy_executable_and_move_sections (file_data *p_infile,
+                                  file_data *p_outfile)
+{
+  unsigned char *dst;
+  PIMAGE_DOS_HEADER dos_header;
+  PIMAGE_NT_HEADERS nt_header;
+  PIMAGE_NT_HEADERS dst_nt_header;
+  PIMAGE_SECTION_HEADER section;
+  PIMAGE_SECTION_HEADER dst_section;
+  PIMAGE_SECTION_HEADER import_section;
+  PIMAGE_SECTION_HEADER reloc_section;
+  PIMAGE_DATA_DIRECTORY import_dir;
+  PIMAGE_DATA_DIRECTORY reloc_dir;
+  DWORD_PTR import_delta_rva;
+  DWORD_PTR reloc_delta_rva;
+  DWORD_PTR offset;
+  int i;
+
+#define COPY_CHUNK(message, src, size)                                         
\
+  do {                                                                         
\
+    unsigned const char *s = (void *)(src);                                    
\
+    unsigned long count = (size);                                              
\
+    printf ("%s\n", (message));                                                
        \
+    printf ("\t0x%08x Offset in input file.\n", s - p_infile->file_base);      
\
+    printf ("\t0x%08x Offset in output file.\n", dst - p_outfile->file_base);  
\
+    printf ("\t0x%08x Size in bytes.\n", count);                               
\
+    memcpy (dst, s, count);                                                    
\
+    dst += count;                                                              
\
+  } while (0)
+
+#define DST_TO_OFFSET()  PTR_TO_OFFSET (dst, p_outfile)
+#define ROUND_UP_DST_AND_ZERO(align)                                           
\
+  do {                                                                         
\
+    unsigned char *newdst = p_outfile->file_base                               
\
+      + ROUND_UP (DST_TO_OFFSET (), (align));                                  
\
+    /* Zero the alignment slop; it may actually initialize real data.  */      
\
+    memset (dst, 0, newdst - dst);                                             
\
+    dst = newdst;                                                              
\
+  } while (0)
+
+  /* Copy the source image sequentially, ie. section by section after
+     copying the headers and section table, to simplify the process of
+     relocating the .rdata and .reloc section table entries (which might
+     force the raw section data to be relocated).
+
+     Note that dst is updated implicitly by each COPY_CHUNK.  */
+
+  dos_header = (PIMAGE_DOS_HEADER) p_infile->file_base;
+  nt_header = (PIMAGE_NT_HEADERS) (((unsigned char *) dos_header) +
+                                  dos_header->e_lfanew);
+  section = IMAGE_FIRST_SECTION (nt_header);
+
+  import_dir = 
&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+  import_section = rva_to_section (import_dir->VirtualAddress, nt_header);
+
+  reloc_dir = 
&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+  reloc_section = rva_to_section (reloc_dir->VirtualAddress, nt_header);
+  if (!reloc_section)
+    {
+      printf ("No relocation data, cannot prepare for profile prepping.\n");
+      exit (1);
+    }
+
+  dst = (unsigned char *) p_outfile->file_base;
+
+  COPY_CHUNK ("Copying DOS header...", dos_header,
+             (DWORD_PTR) nt_header - (DWORD_PTR) dos_header);
+  dst_nt_header = (PIMAGE_NT_HEADERS) dst;
+  COPY_CHUNK ("Copying NT header...", nt_header,
+             (DWORD_PTR) section - (DWORD_PTR) nt_header);
+  dst_section = (PIMAGE_SECTION_HEADER) dst;
+  COPY_CHUNK ("Copying section table...", section,
+             nt_header->FileHeader.NumberOfSections * sizeof (*section));
+
+  /* Leave room for extra section table entries; filled in below.  */
+  dst += 2 * sizeof (*section);
+
+  /* Align the first section's raw data area, and set the header size
+     field accordingly.  */
+  ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
+  dst_nt_header->OptionalHeader.SizeOfHeaders = DST_TO_OFFSET ();
+
+  for (i = 0; i < nt_header->FileHeader.NumberOfSections;
+       i++, section++, dst_section++)
+    {
+      char msg[100];
+      sprintf (msg, "Copying raw data for %s...", section->Name);
+
+      /* "Blank out" the two sections being relocated.  */
+      if (section == import_section || section == reloc_section)
+       {
+         dst_section->Name[0] = 'X';
+         dst_section->Misc.VirtualSize =
+           ROUND_UP (dst_section->Misc.VirtualSize,
+                     dst_nt_header->OptionalHeader.SectionAlignment);
+         dst_section->PointerToRawData = 0;
+         dst_section->SizeOfRawData = 0;
+         dst_section->Characteristics &= ~IMAGE_SCN_CNT_INITIALIZED_DATA;
+         dst_section->Characteristics |= IMAGE_SCN_CNT_UNINITIALIZED_DATA;
+         dst_section->Characteristics &= ~IMAGE_SCN_MEM_WRITE;
+         continue;
+       }
+
+      /* Update the file-relative offset for this section's raw data (if
+         it has any) in case things have been relocated; we will update
+         the other offsets below once we know where everything is.  */
+      if (dst_section->PointerToRawData)
+       dst_section->PointerToRawData = DST_TO_OFFSET ();
+
+      /* Copy the original raw data.  */
+      COPY_CHUNK
+       (msg, OFFSET_TO_PTR (section->PointerToRawData, p_infile),
+        section->SizeOfRawData);
+
+      /* Round up the raw data size to the new alignment.  */
+      dst_section->SizeOfRawData =
+       ROUND_UP (dst_section->SizeOfRawData,
+                 dst_nt_header->OptionalHeader.FileAlignment);
+
+      /* Align the next section's raw data area.  */
+      ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
+    }
+
+  /* Add the extra section entries, copying the raw data we skipped
+     earlier.  We'll patch up the data itself below.  */
+  if (import_section != NULL)
+    {
+      dst_nt_header->FileHeader.NumberOfSections++;
+      dst_nt_header->OptionalHeader.SizeOfImage +=
+       ROUND_UP (import_section->Misc.VirtualSize,
+                 dst_nt_header->OptionalHeader.SectionAlignment);
+      *dst_section = *import_section;
+      dst_section->VirtualAddress =
+       dst_section[-1].VirtualAddress
+       + ROUND_UP (dst_section[-1].Misc.VirtualSize,
+                   dst_nt_header->OptionalHeader.SectionAlignment);
+      dst_section->PointerToRawData = DST_TO_OFFSET ();
+      /* Remember delta applied to import section.  */
+      import_delta_rva = dst_section->VirtualAddress - 
import_section->VirtualAddress;
+      COPY_CHUNK
+       ("Relocating import directory",
+        OFFSET_TO_PTR (import_section->PointerToRawData, p_infile),
+        import_section->SizeOfRawData);
+      ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
+      dst_section++;
+    }
+  if (reloc_section != NULL)
+    {
+      dst_nt_header->FileHeader.NumberOfSections++;
+      dst_nt_header->OptionalHeader.SizeOfImage +=
+       ROUND_UP (reloc_section->Misc.VirtualSize,
+                 dst_nt_header->OptionalHeader.SectionAlignment);
+      *dst_section = *reloc_section;
+      dst_section->VirtualAddress =
+       dst_section[-1].VirtualAddress
+       + ROUND_UP (dst_section[-1].Misc.VirtualSize,
+                   dst_nt_header->OptionalHeader.SectionAlignment);
+      dst_section->PointerToRawData = DST_TO_OFFSET ();
+      /* Remember delta applied to reloc section.  */
+      reloc_delta_rva = dst_section->VirtualAddress - 
reloc_section->VirtualAddress;
+      COPY_CHUNK
+       ("Relocating base relocations directory",
+        OFFSET_TO_PTR (reloc_section->PointerToRawData, p_infile),
+        reloc_section->SizeOfRawData);
+      ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
+      reloc_dir = 
&dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+      reloc_dir->VirtualAddress += reloc_delta_rva;
+      dst_section++;
+    }
+
+  /* Copy remainder of source image.  */
+  section--;
+  offset = ROUND_UP (section->PointerToRawData + section->SizeOfRawData,
+                    nt_header->OptionalHeader.FileAlignment);
+  COPY_CHUNK
+    ("Copying remainder of executable...",
+     OFFSET_TO_PTR (offset, p_infile),
+     p_infile->size - offset);
+
+  /* Final size for new image.  */
+  p_outfile->size = DST_TO_OFFSET ();
+
+  /* Now patch up remaining file-relative offsets.  */
+  printf ("Patching up raw data offsets...\n");
+
+  section = IMAGE_FIRST_SECTION (nt_header);
+  dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
+
+#define ADJUST_OFFSET(var)                                             \
+  do {                                                                 \
+    if ((var) != 0)                                                    \
+      (var) = relocate_offset ((var), nt_header, dst_nt_header);       \
+  } while (0)
+
+#define ADJUST_IMPORT_RVA(var)                 \
+  do {                                         \
+    if ((var) != 0)                            \
+      *((DWORD_PTR *)&(var)) += import_delta_rva;      \
+  } while (0)
+
+  dst_nt_header->OptionalHeader.SizeOfInitializedData = 0;
+  dst_nt_header->OptionalHeader.SizeOfUninitializedData = 0;
+  for (i = 0; i < dst_nt_header->FileHeader.NumberOfSections; i++)
+    {
+      /* Recompute data sizes for completeness.  */
+      if (dst_section[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
+       dst_nt_header->OptionalHeader.SizeOfInitializedData +=
+         ROUND_UP (dst_section[i].Misc.VirtualSize, 
dst_nt_header->OptionalHeader.FileAlignment);
+      else if (dst_section[i].Characteristics & 
IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+       dst_nt_header->OptionalHeader.SizeOfUninitializedData +=
+         ROUND_UP (dst_section[i].Misc.VirtualSize, 
dst_nt_header->OptionalHeader.FileAlignment);
+
+      ADJUST_OFFSET (dst_section[i].PointerToLinenumbers);
+    }
+
+  ADJUST_OFFSET (dst_nt_header->FileHeader.PointerToSymbolTable);
+
+  /* Update offsets in debug directory entries.  Note that the debug
+     directory may be in the same section as the import table, so its
+     RVA may need to be adjusted too.  */
+  {
+    PIMAGE_DATA_DIRECTORY debug_dir =
+      
&dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
+    PIMAGE_DEBUG_DIRECTORY debug_entry;
+
+    /* Update debug_dir if part of import_section.  */
+    if (rva_to_section (debug_dir->VirtualAddress, nt_header) == 
import_section)
+      debug_dir->VirtualAddress += import_delta_rva;
+
+    section = rva_to_section (debug_dir->VirtualAddress, dst_nt_header);
+    if (section)
+      {
+       int size;
+
+       debug_entry = RVA_TO_PTR (debug_dir->VirtualAddress, section, 
p_outfile);
+       size = debug_dir->Size / sizeof (IMAGE_DEBUG_DIRECTORY);
+
+       for (i = 0; i < size; i++, debug_entry++)
+         {
+           /* The debug data itself is normally not part of any
+              section, but stored after all the raw section data.  So
+              let relocate_offset do the work.  */
+           ADJUST_OFFSET (debug_entry->PointerToRawData);
+           ADJUST_IMPORT_RVA (debug_entry->AddressOfRawData);
+         }
+      }
+  }
+
+  /* Update RVAs in import directory entries.  */
+  {
+    PIMAGE_IMPORT_DESCRIPTOR imports;
+    PIMAGE_THUNK_DATA import_thunks;
+
+    import_dir = 
&dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+    import_dir->VirtualAddress += import_delta_rva;
+
+    section = rva_to_section (import_dir->VirtualAddress, dst_nt_header);
+    imports = RVA_TO_PTR (import_dir->VirtualAddress, section, p_outfile);
+
+    for ( ; imports->Name != 0; imports++)
+      {
+       ADJUST_IMPORT_RVA (imports->OriginalFirstThunk);
+       ADJUST_IMPORT_RVA (imports->FirstThunk);
+       ADJUST_IMPORT_RVA (imports->Name);
+
+       for (import_thunks = RVA_TO_PTR (imports->OriginalFirstThunk, section, 
p_outfile);
+            import_thunks->u1.Function != 0;
+            import_thunks++)
+         if ((import_thunks->u1.Ordinal >> 31) == 0)
+           ADJUST_IMPORT_RVA (import_thunks->u1.Ordinal);
+
+       for (import_thunks = RVA_TO_PTR (imports->FirstThunk, section, 
p_outfile);
+            import_thunks->u1.Function != 0;
+            import_thunks++)
+         if ((import_thunks->u1.Ordinal >> 31) == 0)
+           ADJUST_IMPORT_RVA (import_thunks->u1.Ordinal);
+      }
+
+    import_dir = 
&dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT];
+    import_dir->VirtualAddress += import_delta_rva;
+  }
+
+  /* Fix up references to the import section.  */
+  printf ("Applying fixups to import references...\n");
+
+  {
+    IMAGE_BASE_RELOCATION *relocs, *block, *start_block, *end_block;
+    DWORD_PTR import_start = import_section->VirtualAddress + 
dst_nt_header->OptionalHeader.ImageBase;
+    DWORD_PTR import_end = import_start + import_section->Misc.VirtualSize;
+    DWORD_PTR len_import_relocs;
+    DWORD_PTR len_remaining_relocs;
+    int seen_high = 0;
+    WORD * high_word;
+    void * holder;
+
+    reloc_dir = 
&dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+    reloc_section = rva_to_section (reloc_dir->VirtualAddress, dst_nt_header);
+    relocs = RVA_TO_PTR (reloc_dir->VirtualAddress, reloc_section, p_outfile);
+
+    /* Move the base relocations for the import section, if there are
+       any; the profiler needs to be able to patch RVAs in the import
+       section itself.  */
+    for (block = relocs, start_block = 0;
+        (DWORD_PTR) block - (DWORD_PTR) relocs < reloc_dir->Size;
+        block = (void *)((DWORD_PTR) block + block->SizeOfBlock))
+      {
+       if (block->VirtualAddress >= import_section->VirtualAddress + 
import_section->Misc.VirtualSize)
+         {
+           end_block = block;
+           break;
+         }
+       if (block->VirtualAddress >= import_section->VirtualAddress)
+         {
+           if (start_block == 0)
+             start_block = block;
+           block->VirtualAddress += import_delta_rva;
+         }
+      }
+    if (start_block)
+      {
+       len_import_relocs = (DWORD_PTR) end_block - (DWORD_PTR) start_block;
+       len_remaining_relocs = (DWORD_PTR) relocs + reloc_dir->Size - 
(DWORD_PTR) end_block;
+       holder = malloc (len_import_relocs);
+       if (holder == 0)
+         abort ();
+       memcpy (holder, start_block, len_import_relocs);
+       memcpy (start_block, end_block, len_remaining_relocs);
+       memcpy ((char *) start_block + len_remaining_relocs, holder, 
len_import_relocs);
+       free (holder);
+      }
+
+    /* Walk up the list of base relocations, checking for references
+       to the old import section location, and patching them to
+       reference the new location.  */
+    for (block = relocs;
+        (DWORD_PTR) block - (DWORD_PTR) relocs < reloc_dir->Size;
+        block = (void *)((DWORD_PTR) block + block->SizeOfBlock))
+      {
+       DWORD_PTR page_rva = block->VirtualAddress;
+       DWORD_PTR page_offset;
+       union {
+         WORD word;
+         DWORD_PTR dword;
+       } * ploc;
+       WORD *fixup;
+
+       section = rva_to_section (page_rva, dst_nt_header);
+       /* Don't apply fixups to the blanked sections.  */
+       if (section->Name[0] == 'X')
+         continue;
+
+       for (fixup = (WORD *) &block[1];
+            (DWORD_PTR) fixup - (DWORD_PTR) block < block->SizeOfBlock;
+            fixup++)
+         {
+           page_offset = (*fixup) & 0xfff;
+           ploc = RVA_TO_PTR (page_rva + page_offset, section, p_outfile);
+
+           /* Unless our assumption is wrong, all low word fixups
+              should immediately follow a high fixup.  */
+           if (seen_high && ((*fixup) >> 12) != IMAGE_REL_BASED_LOW)
+             abort ();
+
+           switch ((*fixup) >> 12)
+             {
+             case IMAGE_REL_BASED_ABSOLUTE:
+               break;
+             case IMAGE_REL_BASED_HIGH:
+               /* We must assume that high and low fixups occur in
+                   pairs, specifically a low fixup immediately follows a
+                   high fixup (normally separated by two bytes).  We
+                   have to process the two fixups together, to find out
+                   the full pointer value and decide whether to apply
+                   the fixup.  */
+               seen_high = 1;
+               high_word = &ploc->word;
+               break;
+             case IMAGE_REL_BASED_LOW:
+               offset = (*high_word << 16) + ploc->word;
+               if (offset >= import_start && offset < import_end)
+                 {
+                   (*high_word) += import_delta_rva >> 16;
+                   ploc->dword += import_delta_rva & 0xffff;
+                 }
+               seen_high = 0;
+               break;
+             case IMAGE_REL_BASED_HIGHLOW:
+               /* Docs imply two words in big-endian order, so perhaps
+                   this is only used on big-endian platforms, in which
+                   case the obvious code will work.  */
+               if (ploc->dword >= import_start && ploc->dword < import_end)
+                 ploc->dword += import_delta_rva;
+               break;
+             case IMAGE_REL_BASED_HIGHADJ:
+               /* Docs don't say, but I guess this is the equivalent
+                   for little-endian platforms.  */
+               if (ploc->dword >= import_start && ploc->dword < import_end)
+                 ploc->dword += import_delta_rva;
+               break;
+             case IMAGE_REL_BASED_MIPS_JMPADDR:
+               /* Don't know how to handle this; MIPS support has been
+                   dropped from NT4 anyway.  */
+               abort ();
+               break;
+#ifdef IMAGE_REL_BASED_SECTION
+             case IMAGE_REL_BASED_SECTION:
+             case IMAGE_REL_BASED_REL32:
+               /* Docs don't say what these values mean.  */
+#endif
+             default:
+               abort ();
+             }
+         }
+      }
+  }
+}
+
+
+int
+main (int argc, char **argv)
+{
+  PIMAGE_DOS_HEADER dos_header;
+  PIMAGE_NT_HEADERS nt_header;
+  file_data in_file, out_file;
+  char out_filename[MAX_PATH], in_filename[MAX_PATH];
+
+  strcpy (in_filename, argv[1]);
+  strcpy (out_filename, argv[2]);
+
+  printf ("Preparing %s for profile prepping\n", out_filename);
+
+  /* Open the original (dumped) executable file for reference.  */
+  if (!open_input_file (&in_file, in_filename))
+    {
+      printf ("Failed to open %s (%d)...bailing.\n",
+             in_filename, GetLastError ());
+      exit (1);
+    }
+
+  /* Create a new image that can be prepped; we don't expect the size to
+     change because we are only adding two new section table entries,
+     which should fit in the alignment slop.  */
+  if (!open_output_file (&out_file, out_filename, in_file.size))
+    {
+      printf ("Failed to open %s (%d)...bailing.\n",
+             out_filename, GetLastError ());
+      exit (1);
+    }
+
+  copy_executable_and_move_sections (&in_file, &out_file);
+
+  /* Patch up header fields; profiler is picky about this. */
+  {
+    HANDLE hImagehelp = LoadLibrary ("imagehlp.dll");
+    DWORD_PTR  headersum;
+    DWORD_PTR  checksum;
+
+    dos_header = (PIMAGE_DOS_HEADER) out_file.file_base;
+    nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + 
dos_header->e_lfanew);
+
+    nt_header->OptionalHeader.CheckSum = 0;
+//    nt_header->FileHeader.TimeDateStamp = time (NULL);
+//    dos_header->e_cp = size / 512;
+//    nt_header->OptionalHeader.SizeOfImage = size;
+
+    pfnCheckSumMappedFile = (void *) GetProcAddress (hImagehelp, 
"CheckSumMappedFile");
+    if (pfnCheckSumMappedFile)
+      {
+//     nt_header->FileHeader.TimeDateStamp = time (NULL);
+       pfnCheckSumMappedFile (out_file.file_base,
+                              out_file.size,
+                              &headersum,
+                              &checksum);
+       nt_header->OptionalHeader.CheckSum = checksum;
+      }
+    FreeLibrary (hImagehelp);
+  }
+
+  close_file_data (&out_file);
+  close_file_data (&in_file);
+
+  return 0;
+}
+
+/* eof */
diff --git a/nt/runemacs.c b/nt/runemacs.c
index 9226bb50745..4188a1fa9a4 100644
--- a/nt/runemacs.c
+++ b/nt/runemacs.c
@@ -1,6 +1,6 @@
 /* runemacs --- Simple program to start Emacs with its console window hidden.
 
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/oldXMenu/Activate.c b/oldXMenu/Activate.c
index 0bfa70900f0..ffc5d5ecef1 100644
--- a/oldXMenu/Activate.c
+++ b/oldXMenu/Activate.c
@@ -21,7 +21,7 @@ without express or implied warranty.
 
 
 /*
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
diff --git a/oldXMenu/ChangeLog.1 b/oldXMenu/ChangeLog.1
index 0e0d0ea4ce5..629ac2e2b65 100644
--- a/oldXMenu/ChangeLog.1
+++ b/oldXMenu/ChangeLog.1
@@ -712,7 +712,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1993-1999, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1993-1999, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/oldXMenu/Create.c b/oldXMenu/Create.c
index 9518b2833a2..c602d984168 100644
--- a/oldXMenu/Create.c
+++ b/oldXMenu/Create.c
@@ -21,7 +21,7 @@ without express or implied warranty.
 
 
 /*
-Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
diff --git a/oldXMenu/FindSel.c b/oldXMenu/FindSel.c
index 0153af1b02f..4e68d167ade 100644
--- a/oldXMenu/FindSel.c
+++ b/oldXMenu/FindSel.c
@@ -21,7 +21,7 @@ without express or implied warranty.
 
 
 /*
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
diff --git a/oldXMenu/Internal.c b/oldXMenu/Internal.c
index cf4960cd113..db13f7ac736 100644
--- a/oldXMenu/Internal.c
+++ b/oldXMenu/Internal.c
@@ -21,7 +21,7 @@ without express or implied warranty.
 
 
 /*
-Copyright (C) 1993, 1996, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993, 1996, 2001-2024 Free Software Foundation, Inc.
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
diff --git a/oldXMenu/Makefile.in b/oldXMenu/Makefile.in
index 602d05fb621..cdafe83b7a2 100644
--- a/oldXMenu/Makefile.in
+++ b/oldXMenu/Makefile.in
@@ -15,7 +15,7 @@
 ## without express or implied warranty.
 
 
-## Copyright (C) 2001-2023 Free Software Foundation, Inc.
+## Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
diff --git a/oldXMenu/deps.mk b/oldXMenu/deps.mk
index cf85047d971..b223fce75d4 100644
--- a/oldXMenu/deps.mk
+++ b/oldXMenu/deps.mk
@@ -15,7 +15,7 @@
 ## without express or implied warranty.
 
 
-## Copyright (C) 2001-2023 Free Software Foundation, Inc.
+## Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
diff --git a/oldXMenu/insque.c b/oldXMenu/insque.c
index 3d7c3b3086c..78d99d2b4ea 100644
--- a/oldXMenu/insque.c
+++ b/oldXMenu/insque.c
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 1993-1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1998, 2001-2024 Free Software Foundation, Inc.
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
diff --git a/src/.gdbinit b/src/.gdbinit
index c97e78559f1..6c4dda67f06 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -1,4 +1,4 @@
-# Copyright (C) 1992-1998, 2000-2023 Free Software Foundation, Inc.
+# Copyright (C) 1992-1998, 2000-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
@@ -15,6 +15,10 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 
+# If you don't want messages from GDB to interfere with ordinary editing
+# whenever it creates a subprocess, uncomment the following line.
+### set print inferior-events off
+
 # Force loading of symbols, enough to give us VALBITS etc.
 set $dummy = main + 8
 # With some compilers, we need this to give us struct Lisp_Symbol etc.:
diff --git a/src/.lldbinit b/src/.lldbinit
index a5789f49122..e958c1b832c 100644
--- a/src/.lldbinit
+++ b/src/.lldbinit
@@ -1,5 +1,5 @@
 # -*- mode: shell-script -*-
-# Copyright (C) 2022-2023 Free Software Foundation, Inc.
+# Copyright (C) 2022-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/src/ChangeLog.1 b/src/ChangeLog.1
index 37d6d6bd897..adeccfa9a6d 100644
--- a/src/ChangeLog.1
+++ b/src/ChangeLog.1
@@ -3521,7 +3521,7 @@
        * minibuf.c: Don't allow entry to minibuffer
        while minibuffer is selected.
 
-    Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+    Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/ChangeLog.10 b/src/ChangeLog.10
index 949e4507f4c..cb6502e915c 100644
--- a/src/ChangeLog.10
+++ b/src/ChangeLog.10
@@ -27912,7 +27912,7 @@ See ChangeLog.9 for earlier changes.
 ;; add-log-time-zone-rule: t
 ;; End:
 
-    Copyright (C) 2001-2023 Free Software Foundation, Inc.
+    Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/ChangeLog.11 b/src/ChangeLog.11
index b1e476e56fd..abea7688c87 100644
--- a/src/ChangeLog.11
+++ b/src/ChangeLog.11
@@ -2029,7 +2029,7 @@
        (update_frame_tool_bar): Calculate tool-bar style once per call.
        Instead of hiding text labels, omit them.  Don't use
        xg_show_toolbar_item; create new GtkToolItems from scratch if
-       necessary, instead of trying to re-use them.  This avoids an
+       necessary, instead of trying to reuse them.  This avoids an
        annoying animation when changing tool-bars.
 
 2010-12-31  Jan Djärv  <jan.h.d@swipnet.se>
@@ -2048,7 +2048,7 @@
        (ns_set_name): Call ns_set_name_internal.
        (x_explicitly_set_name): Remove call to ns_set_name_iconic.
        (x_implicitly_set_name): Ditto.
-       (x_set_title): Remove commet about EXPLICIT.  Call ns_set_name_internal.
+       (x_set_title): Remove comment about EXPLICIT.  Call 
ns_set_name_internal.
        (ns_set_name_as_filename): Encode name with ENCODE_UTF_8 (Bug#7517).
 
 2010-12-29  Štěpán Němec  <stepnem@gmail.com>  (tiny change)
@@ -9435,7 +9435,7 @@
        continuation line, and start looking for a suitable row from
        there.
 
-       * term.c (append_glyph): Reverse glyphs by pre-pending them,
+       * term.c (append_glyph): Reverse glyphs by prepending them,
        rather than appending, if the glyph_row's reversed_p flag is set.
        Set the resolved_level and bidi_type members of each glyph.
 
@@ -31385,7 +31385,7 @@ See ChangeLog.10 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2007-2023 Free Software Foundation, Inc.
+  Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/ChangeLog.12 b/src/ChangeLog.12
index fdb7a2e659b..7792bd88c01 100644
--- a/src/ChangeLog.12
+++ b/src/ChangeLog.12
@@ -22936,7 +22936,7 @@ See ChangeLog.11 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2011-2023 Free Software Foundation, Inc.
+  Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/ChangeLog.13 b/src/ChangeLog.13
index d9736479a04..312909f462f 100644
--- a/src/ChangeLog.13
+++ b/src/ChangeLog.13
@@ -5464,7 +5464,7 @@
        (set_horizontal_scroll_bar): New function.
        (redisplay_window): Set ignore_mouse_drag_p when tool bar has
        more than one line.  Handle horizontal scroll bars.
-       (note_mouse_highlight): Handle horizontal scrol bars.
+       (note_mouse_highlight): Handle horizontal scroll bars.
        (expose_frame): Set dimensions of XRectangle from frame's text
        sizes.
        (Vvoid_text_area_pointer): Update doc-string.
@@ -8437,7 +8437,7 @@
 
        * xdisp.c (syms_of_xdisp): Doc clarification (bug#15657).
 
-       * keyboard.c (Frecursive_edit): Say more precicely how throwing
+       * keyboard.c (Frecursive_edit): Say more precisely how throwing
        `exit' works (bug#15865).
 
 2014-02-07  Martin Rudalics  <rudalics@gmx.at>
@@ -16678,7 +16678,7 @@
 
 2013-05-27  Eli Zaretskii  <eliz@gnu.org>
 
-       * xdisp.c (pos_visible_p): When CHARPOS is displayed frrom a
+       * xdisp.c (pos_visible_p): When CHARPOS is displayed from a
        display vector, and we backtrack, handle the case that the
        previous character position is also displayed from a display
        vector or covered by a display string or image.  (Bug#14476)
@@ -17905,7 +17905,7 @@ See ChangeLog.12 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2011-2023 Free Software Foundation, Inc.
+  Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/ChangeLog.2 b/src/ChangeLog.2
index d518c759642..6f4e79e71f5 100644
--- a/src/ChangeLog.2
+++ b/src/ChangeLog.2
@@ -4771,7 +4771,7 @@
 
 See ChangeLog.1 for earlier changes.
 
-    Copyright (C) 1986-1988, 2001-2023 Free Software Foundation, Inc.
+    Copyright (C) 1986-1988, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/ChangeLog.3 b/src/ChangeLog.3
index fbfb36fdb2a..e9fa000aff4 100644
--- a/src/ChangeLog.3
+++ b/src/ChangeLog.3
@@ -16503,7 +16503,7 @@ See ChangeLog.2 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/ChangeLog.4 b/src/ChangeLog.4
index 8d4b3594eaf..711e142232c 100644
--- a/src/ChangeLog.4
+++ b/src/ChangeLog.4
@@ -6906,7 +6906,7 @@ See ChangeLog.3 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/ChangeLog.5 b/src/ChangeLog.5
index 3ea0acafff0..df1de5efe6b 100644
--- a/src/ChangeLog.5
+++ b/src/ChangeLog.5
@@ -7148,7 +7148,7 @@ See ChangeLog.4 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1994-1995, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1994-1995, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/ChangeLog.6 b/src/ChangeLog.6
index f9ea372c55d..6838f16ad41 100644
--- a/src/ChangeLog.6
+++ b/src/ChangeLog.6
@@ -5358,7 +5358,7 @@ See ChangeLog.5 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1995-1996, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/ChangeLog.7 b/src/ChangeLog.7
index dfa41bec8f7..61892b54bf5 100644
--- a/src/ChangeLog.7
+++ b/src/ChangeLog.7
@@ -11091,7 +11091,7 @@ See ChangeLog.6 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/ChangeLog.8 b/src/ChangeLog.8
index 1f479a89ed8..e91448e32e2 100644
--- a/src/ChangeLog.8
+++ b/src/ChangeLog.8
@@ -10802,7 +10802,7 @@
        (display_mode_element): Ditto.
        (echo_area_display): Don't display if frame has no pools yet.
        (echo_area_display): Work with window matrix for mini window.
-       (redisplay_window): Use window marix for mini window.
+       (redisplay_window): Use window matrix for mini window.
        (display_text_line): Assume HPOS and VPOS are window relative and
        use that for DISPLAY_STRING.
 
@@ -13979,7 +13979,7 @@
 
 See ChangeLog.7 for earlier changes.
 
-  Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/ChangeLog.9 b/src/ChangeLog.9
index d005b51604b..8331d09a128 100644
--- a/src/ChangeLog.9
+++ b/src/ChangeLog.9
@@ -11622,7 +11622,7 @@
        (set_font_frame_param): If `font' is specified in lface, use it.
        (Finternal_get_lisp_face_attribute): Handle `font' slot in lface.
        (lface_same_font_attributes_p): Likewise.
-       (make_realized_face): Arguent changed.  Caller changed.  Set
+       (make_realized_face): Argument changed.  Caller changed.  Set
        face->ascii_face to face itself.
        (free_realized_face): Free face->fontset if face is for ASCII.
        (face_suitable_for_iso8859_1_p, face_suitable_for_charset_p)
@@ -13294,7 +13294,7 @@ See ChangeLog.8 for earlier changes.
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2001-2023 Free Software Foundation, Inc.
+  Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/src/Makefile.in b/src/Makefile.in
index d3d71e78abb..de45b2290f1 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 1985, 1987-1988, 1993-1995, 1999-2023 Free Software
+# Copyright (C) 1985, 1987-1988, 1993-1995, 1999-2024 Free Software
 # Foundation, Inc.
 
 # This file is part of GNU Emacs.
diff --git a/src/README b/src/README
index 7d4427b8610..a8ddf830b72 100644
--- a/src/README
+++ b/src/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 
diff --git a/src/alloc.c b/src/alloc.c
index 5b106bf2690..539e7ca0af4 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -1,6 +1,6 @@
 /* Storage allocation and gc for GNU Emacs Lisp interpreter.
 
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -34,7 +34,6 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include "dispextern.h"
 #include "intervals.h"
 #include "puresize.h"
-#include "sheap.h"
 #include "sysstdio.h"
 #include "systime.h"
 #include "character.h"
@@ -360,8 +359,16 @@ static struct gcstat
   object_ct total_floats, total_free_floats;
   object_ct total_intervals, total_free_intervals;
   object_ct total_buffers;
+
+  /* Size of the ancillary arrays of live hash-table objects.
+     The objects themselves are not included (counted as vectors above).  */
+  byte_ct total_hash_table_bytes;
 } gcstat;
 
+/* Total size of ancillary arrays of all allocated hash-table objects,
+   both dead and alive.  This number is always kept up-to-date.  */
+static ptrdiff_t hash_table_allocated_bytes = 0;
+
 /* Points to memory space allocated as "spare", to be freed if we run
    out of memory.  We keep one large block, four cons-blocks, and
    two string blocks.  */
@@ -413,31 +420,6 @@ static EMACS_INT gc_threshold;
 
 const char *pending_malloc_warning;
 
-/* Pointer sanity only on request.  FIXME: Code depending on
-   SUSPICIOUS_OBJECT_CHECKING is obsolete; remove it entirely.  */
-#ifdef ENABLE_CHECKING
-#define SUSPICIOUS_OBJECT_CHECKING 1
-#endif
-
-#ifdef SUSPICIOUS_OBJECT_CHECKING
-struct suspicious_free_record
-{
-  void *suspicious_object;
-  void *backtrace[128];
-};
-static void *suspicious_objects[32];
-static int suspicious_object_index;
-struct suspicious_free_record suspicious_free_history[64] EXTERNALLY_VISIBLE;
-static int suspicious_free_history_index;
-/* Find the first currently-monitored suspicious pointer in range
-   [begin,end) or NULL if no such pointer exists.  */
-static void *find_suspicious_object_in_range (void *begin, void *end);
-static void detect_suspicious_free (void *ptr);
-#else
-# define find_suspicious_object_in_range(begin, end) ((void *) NULL)
-# define detect_suspicious_free(ptr) ((void) 0)
-#endif
-
 /* Maximum amount of C stack to save when a GC happens.  */
 
 #ifndef MAX_SAVE_STACK
@@ -1484,9 +1466,9 @@ static INTERVAL interval_free_list;
   __asan_unpoison_memory_region ((b)->intervals, \
                                 sizeof ((b)->intervals))
 # define ASAN_POISON_INTERVAL(i) \
-  __asan_poison_memory_region ((i), sizeof (*(i)))
+  __asan_poison_memory_region (i, sizeof *(i))
 # define ASAN_UNPOISON_INTERVAL(i) \
-  __asan_unpoison_memory_region ((i), sizeof (*(i)))
+  __asan_unpoison_memory_region (i, sizeof *(i))
 #else
 # define ASAN_POISON_INTERVAL_BLOCK(b) ((void) 0)
 # define ASAN_UNPOISON_INTERVAL_BLOCK(b) ((void) 0)
@@ -1770,25 +1752,25 @@ init_strings (void)
  */
 # define ASAN_PREPARE_DEAD_SDATA(s, size)                          \
   do {                                                             \
-    __asan_poison_memory_region ((s), sdata_size ((size)));        \
-    __asan_unpoison_memory_region (&(((s))->string),                 \
+    __asan_poison_memory_region (s, sdata_size (size));                   \
+    __asan_unpoison_memory_region (&(s)->string,                  \
                                   sizeof (struct Lisp_String *)); \
-    __asan_unpoison_memory_region (&SDATA_NBYTES ((s)),            \
-                                  sizeof (SDATA_NBYTES ((s))));   \
+    __asan_unpoison_memory_region (&SDATA_NBYTES (s),             \
+                                  sizeof SDATA_NBYTES (s));       \
    } while (false)
 /* Prepare s for storing string data for NBYTES bytes.  */
 # define ASAN_PREPARE_LIVE_SDATA(s, nbytes) \
-  __asan_unpoison_memory_region ((s), sdata_size ((nbytes)))
+  __asan_unpoison_memory_region (s, sdata_size (nbytes))
 # define ASAN_POISON_SBLOCK_DATA(b, size) \
-  __asan_poison_memory_region ((b)->data, (size))
+  __asan_poison_memory_region ((b)->data, size)
 # define ASAN_POISON_STRING_BLOCK(b) \
   __asan_poison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
 # define ASAN_UNPOISON_STRING_BLOCK(b) \
   __asan_unpoison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
 # define ASAN_POISON_STRING(s) \
-  __asan_poison_memory_region ((s), sizeof (*(s)))
+  __asan_poison_memory_region (s, sizeof *(s))
 # define ASAN_UNPOISON_STRING(s) \
-  __asan_unpoison_memory_region ((s), sizeof (*(s)))
+  __asan_unpoison_memory_region (s, sizeof *(s))
 #else
 # define ASAN_PREPARE_DEAD_SDATA(s, size) ((void) 0)
 # define ASAN_PREPARE_LIVE_SDATA(s, nbytes) ((void) 0)
@@ -2709,13 +2691,13 @@ struct float_block
 };
 
 #define XFLOAT_MARKED_P(fptr) \
-  GETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
+  GETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX (fptr))
 
 #define XFLOAT_MARK(fptr) \
-  SETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
+  SETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX (fptr))
 
 #define XFLOAT_UNMARK(fptr) \
-  UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
+  UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX (fptr))
 
 #if GC_ASAN_POISON_OBJECTS
 # define ASAN_POISON_FLOAT_BLOCK(fblk)         \
@@ -2725,9 +2707,9 @@ struct float_block
   __asan_unpoison_memory_region ((fblk)->floats, \
                                 sizeof ((fblk)->floats))
 # define ASAN_POISON_FLOAT(p) \
-  __asan_poison_memory_region ((p), sizeof (struct Lisp_Float))
+  __asan_poison_memory_region (p, sizeof (struct Lisp_Float))
 # define ASAN_UNPOISON_FLOAT(p) \
-  __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Float))
+  __asan_unpoison_memory_region (p, sizeof (struct Lisp_Float))
 #else
 # define ASAN_POISON_FLOAT_BLOCK(fblk) ((void) 0)
 # define ASAN_UNPOISON_FLOAT_BLOCK(fblk) ((void) 0)
@@ -2821,13 +2803,13 @@ struct cons_block
 };
 
 #define XCONS_MARKED_P(fptr) \
-  GETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
+  GETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX (fptr))
 
 #define XMARK_CONS(fptr) \
-  SETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
+  SETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX (fptr))
 
 #define XUNMARK_CONS(fptr) \
-  UNSETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
+  UNSETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX (fptr))
 
 /* Minimum number of bytes of consing since GC before next GC,
    when memory is full.  */
@@ -2850,9 +2832,9 @@ static struct Lisp_Cons *cons_free_list;
 # define ASAN_POISON_CONS_BLOCK(b) \
   __asan_poison_memory_region ((b)->conses, sizeof ((b)->conses))
 # define ASAN_POISON_CONS(p) \
-  __asan_poison_memory_region ((p), sizeof (struct Lisp_Cons))
+  __asan_poison_memory_region (p, sizeof (struct Lisp_Cons))
 # define ASAN_UNPOISON_CONS(p) \
-  __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Cons))
+  __asan_unpoison_memory_region (p, sizeof (struct Lisp_Cons))
 #else
 # define ASAN_POISON_CONS_BLOCK(b) ((void) 0)
 # define ASAN_POISON_CONS(p) ((void) 0)
@@ -3170,11 +3152,11 @@ Lisp_Object zero_vector;
 
 #if GC_ASAN_POISON_OBJECTS
 # define ASAN_POISON_VECTOR_CONTENTS(v, bytes) \
-  __asan_poison_memory_region ((v)->contents, (bytes))
+  __asan_poison_memory_region ((v)->contents, bytes)
 # define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) \
-  __asan_unpoison_memory_region ((v)->contents, (bytes))
+  __asan_unpoison_memory_region ((v)->contents, bytes)
 # define ASAN_UNPOISON_VECTOR_BLOCK(b) \
-  __asan_unpoison_memory_region ((b)->data, sizeof ((b)->data))
+  __asan_unpoison_memory_region ((b)->data, sizeof (b)->data)
 #else
 # define ASAN_POISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
 # define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
@@ -3352,7 +3334,6 @@ vectorlike_nbytes (const union vectorlike_header *hdr)
 static void
 cleanup_vector (struct Lisp_Vector *vector)
 {
-  detect_suspicious_free (vector);
   if ((vector->header.size & PSEUDOVECTOR_FLAG) == 0)
     return;  /* nothing more to do for plain vectors */
   switch (PSEUDOVECTOR_TYPE (vector))
@@ -3457,6 +3438,23 @@ cleanup_vector (struct Lisp_Vector *vector)
       }
 #endif
       break;
+    case PVEC_HASH_TABLE:
+      {
+       struct Lisp_Hash_Table *h = PSEUDOVEC_STRUCT (vector, Lisp_Hash_Table);
+       if (h->table_size > 0)
+         {
+           eassert (h->index_size > 1);
+           xfree (h->index);
+           xfree (h->key_and_value);
+           xfree (h->next);
+           xfree (h->hash);
+           ptrdiff_t bytes = (h->table_size * (2 * sizeof *h->key_and_value
+                                               + sizeof *h->hash
+                                               + sizeof *h->next)
+                              + h->index_size * sizeof *h->index);
+           hash_table_allocated_bytes -= bytes;
+         }
+      }
     /* Keep the switch exhaustive.  */
     case PVEC_NORMAL_VECTOR:
     case PVEC_FREE:
@@ -3467,7 +3465,6 @@ cleanup_vector (struct Lisp_Vector *vector)
     case PVEC_WINDOW:
     case PVEC_BOOL_VECTOR:
     case PVEC_BUFFER:
-    case PVEC_HASH_TABLE:
     case PVEC_TERMINAL:
     case PVEC_WINDOW_CONFIGURATION:
     case PVEC_OTHER:
@@ -3581,6 +3578,8 @@ sweep_vectors (void)
          lisp_free (lv);
        }
     }
+
+  gcstat.total_hash_table_bytes = hash_table_allocated_bytes;
 }
 
 /* Maximum number of elements in a vector.  This is a macro so that it
@@ -3630,9 +3629,6 @@ allocate_vectorlike (ptrdiff_t len, bool clearit)
     mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
 #endif
 
-  if (find_suspicious_object_in_range (p, (char *) p + nbytes))
-    emacs_abort ();
-
   tally_consing (nbytes);
   vector_cells_consed += len;
 
@@ -3893,9 +3889,9 @@ struct symbol_block
 # define ASAN_UNPOISON_SYMBOL_BLOCK(s) \
   __asan_unpoison_memory_region ((s)->symbols, sizeof ((s)->symbols))
 # define ASAN_POISON_SYMBOL(sym) \
-  __asan_poison_memory_region ((sym), sizeof (*(sym)))
+  __asan_poison_memory_region (sym, sizeof *(sym))
 # define ASAN_UNPOISON_SYMBOL(sym) \
-  __asan_unpoison_memory_region ((sym), sizeof (*(sym)))
+  __asan_unpoison_memory_region (sym, sizeof *(sym))
 
 #else
 # define ASAN_POISON_SYMBOL_BLOCK(s) ((void) 0)
@@ -5639,6 +5635,28 @@ valid_lisp_object_p (Lisp_Object obj)
   return 0;
 }
 
+/* Like xmalloc, but makes allocation count toward the total consing.
+   Return NULL for a zero-sized allocation.  */
+void *
+hash_table_alloc_bytes (ptrdiff_t nbytes)
+{
+  if (nbytes == 0)
+    return NULL;
+  tally_consing (nbytes);
+  hash_table_allocated_bytes += nbytes;
+  return xmalloc (nbytes);
+}
+
+/* Like xfree, but makes allocation count toward the total consing.  */
+void
+hash_table_free_bytes (void *p, ptrdiff_t nbytes)
+{
+  tally_consing (-nbytes);
+  hash_table_allocated_bytes -= nbytes;
+  xfree (p);
+}
+
+
 /***********************************************************************
                       Pure Storage Management
  ***********************************************************************/
@@ -5920,30 +5938,34 @@ make_pure_vector (ptrdiff_t len)
 static struct Lisp_Hash_Table *
 purecopy_hash_table (struct Lisp_Hash_Table *table)
 {
-  eassert (NILP (table->weak));
+  eassert (table->weakness == Weak_None);
   eassert (table->purecopy);
 
   struct Lisp_Hash_Table *pure = pure_alloc (sizeof *pure, Lisp_Vectorlike);
-  struct hash_table_test pure_test = table->test;
-
-  /* Purecopy the hash table test.  */
-  pure_test.name = purecopy (table->test.name);
-  pure_test.user_hash_function = purecopy (table->test.user_hash_function);
-  pure_test.user_cmp_function = purecopy (table->test.user_cmp_function);
-
-  pure->header = table->header;
-  pure->weak = purecopy (Qnil);
-  pure->hash = purecopy (table->hash);
-  pure->next = purecopy (table->next);
-  pure->index = purecopy (table->index);
-  pure->count = table->count;
-  pure->next_free = table->next_free;
-  pure->purecopy = table->purecopy;
-  eassert (!pure->mutable);
-  pure->rehash_threshold = table->rehash_threshold;
-  pure->rehash_size = table->rehash_size;
-  pure->key_and_value = purecopy (table->key_and_value);
-  pure->test = pure_test;
+  *pure = *table;
+  pure->mutable = false;
+
+  if (table->table_size > 0)
+    {
+      ptrdiff_t hash_bytes = table->table_size * sizeof *table->hash;
+      pure->hash = pure_alloc (hash_bytes, -(int)sizeof *table->hash);
+      memcpy (pure->hash, table->hash, hash_bytes);
+
+      ptrdiff_t next_bytes = table->table_size * sizeof *table->next;
+      pure->next = pure_alloc (next_bytes, -(int)sizeof *table->next);
+      memcpy (pure->next, table->next, next_bytes);
+
+      ptrdiff_t nvalues = table->table_size * 2;
+      ptrdiff_t kv_bytes = nvalues * sizeof *table->key_and_value;
+      pure->key_and_value = pure_alloc (kv_bytes,
+                                       -(int)sizeof *table->key_and_value);
+      for (ptrdiff_t i = 0; i < nvalues; i++)
+       pure->key_and_value[i] = purecopy (table->key_and_value[i]);
+
+      ptrdiff_t index_bytes = table->index_size * sizeof *table->index;
+      pure->index = pure_alloc (index_bytes, -(int)sizeof *table->index);
+      memcpy (pure->index, table->index, index_bytes);
+    }
 
   return pure;
 }
@@ -6003,7 +6025,7 @@ purecopy (Lisp_Object obj)
       /* Do not purify hash tables which haven't been defined with
          :purecopy as non-nil or are weak - they aren't guaranteed to
          not change.  */
-      if (!NILP (table->weak) || !table->purecopy)
+      if (table->weakness != Weak_None || !table->purecopy)
         {
           /* Instead, add the hash table to the list of pinned objects,
              so that it will be marked during GC.  */
@@ -6127,6 +6149,7 @@ total_bytes_of_live_objects (void)
   tot += object_bytes (gcstat.total_floats, sizeof (struct Lisp_Float));
   tot += object_bytes (gcstat.total_intervals, sizeof (struct interval));
   tot += object_bytes (gcstat.total_strings, sizeof (struct Lisp_String));
+  tot += gcstat.total_hash_table_bytes;
   return tot;
 }
 
@@ -6271,11 +6294,10 @@ android_make_lisp_symbol (struct Lisp_Symbol *sym)
   intptr_t symoffset;
 
   symoffset = (intptr_t) sym;
-  INT_SUBTRACT_WRAPV (symoffset, (intptr_t) &lispsym,
-                     &symoffset);
+  ckd_sub (&symoffset, symoffset, (intptr_t) &lispsym);
 
   {
-    Lisp_Object a = TAG_PTR (Lisp_Symbol, symoffset);
+    Lisp_Object a = TAG_PTR_INITIALLY (Lisp_Symbol, symoffset);
     return a;
   }
 }
@@ -6574,6 +6596,9 @@ garbage_collect (void)
   mark_terminals ();
   mark_kboards ();
   mark_threads ();
+  mark_charset ();
+  mark_composite ();
+  mark_profiler ();
 #ifdef HAVE_PGTK
   mark_pgtkterm ();
 #endif
@@ -6605,10 +6630,11 @@ garbage_collect (void)
 #ifdef HAVE_NS
   mark_nsterm ();
 #endif
+  mark_fns ();
 
   /* Everything is now marked, except for the data in font caches,
      undo lists, and finalizers.  The first two are compacted by
-     removing an items which aren't reachable otherwise.  */
+     removing any items which aren't reachable otherwise.  */
 
   compact_font_caches ();
 
@@ -7269,22 +7295,20 @@ process_mark_stack (ptrdiff_t base_sp)
              case PVEC_HASH_TABLE:
                {
                  struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *)ptr;
-                 ptrdiff_t size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
                  set_vector_marked (ptr);
-                 mark_stack_push_values (ptr->contents, size);
-                 mark_stack_push_value (h->test.name);
-                 mark_stack_push_value (h->test.user_hash_function);
-                 mark_stack_push_value (h->test.user_cmp_function);
-                 if (NILP (h->weak))
-                   mark_stack_push_value (h->key_and_value);
+                 if (h->weakness == Weak_None)
+                   /* The values pushed here may include
+                      HASH_UNUSED_ENTRY_KEY, which this function must
+                      cope with.  */
+                   mark_stack_push_values (h->key_and_value,
+                                           2 * h->table_size);
                  else
                    {
-                     /* For weak tables, mark only the vector and not its
+                     /* For weak tables, don't mark the
                         contents --- that's what makes it weak.  */
                      eassert (h->next_weak == NULL);
                      h->next_weak = weak_hash_tables;
                      weak_hash_tables = h;
-                     set_vector_marked (XVECTOR (h->key_and_value));
                    }
                  break;
                }
@@ -7420,14 +7444,19 @@ process_mark_stack (ptrdiff_t base_sp)
          }
 
        case Lisp_Float:
-         CHECK_ALLOCATED_AND_LIVE (live_float_p, MEM_TYPE_FLOAT);
-         /* Do not mark floats stored in a dump image: these floats are
-            "cold" and do not have mark bits.  */
-         if (pdumper_object_p (XFLOAT (obj)))
-           eassert (pdumper_cold_object_p (XFLOAT (obj)));
-         else if (!XFLOAT_MARKED_P (XFLOAT (obj)))
-           XFLOAT_MARK (XFLOAT (obj));
-         break;
+         {
+           struct Lisp_Float *f = XFLOAT (obj);
+           if (!f)
+             break;            /* for HASH_UNUSED_ENTRY_KEY */
+           CHECK_ALLOCATED_AND_LIVE (live_float_p, MEM_TYPE_FLOAT);
+           /* Do not mark floats stored in a dump image: these floats are
+              "cold" and do not have mark bits.  */
+           if (pdumper_object_p (f))
+             eassert (pdumper_cold_object_p (f));
+           else if (!XFLOAT_MARKED_P (f))
+             XFLOAT_MARK (f);
+           break;
+         }
 
        case_Lisp_Int:
          break;
@@ -8023,78 +8052,6 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max)
    return unbind_to (gc_count, found);
 }
 
-#ifdef SUSPICIOUS_OBJECT_CHECKING
-
-static void *
-find_suspicious_object_in_range (void *begin, void *end)
-{
-  char *begin_a = begin;
-  char *end_a = end;
-  int i;
-
-  for (i = 0; i < ARRAYELTS (suspicious_objects); ++i)
-    {
-      char *suspicious_object = suspicious_objects[i];
-      if (begin_a <= suspicious_object && suspicious_object < end_a)
-       return suspicious_object;
-    }
-
-  return NULL;
-}
-
-static void
-note_suspicious_free (void *ptr)
-{
-  struct suspicious_free_record *rec;
-
-  rec = &suspicious_free_history[suspicious_free_history_index++];
-  if (suspicious_free_history_index ==
-      ARRAYELTS (suspicious_free_history))
-    {
-      suspicious_free_history_index = 0;
-    }
-
-  memset (rec, 0, sizeof (*rec));
-  rec->suspicious_object = ptr;
-  backtrace (&rec->backtrace[0], ARRAYELTS (rec->backtrace));
-}
-
-static void
-detect_suspicious_free (void *ptr)
-{
-  int i;
-
-  eassert (ptr != NULL);
-
-  for (i = 0; i < ARRAYELTS (suspicious_objects); ++i)
-    if (suspicious_objects[i] == ptr)
-      {
-        note_suspicious_free (ptr);
-        suspicious_objects[i] = NULL;
-      }
-}
-
-#endif /* SUSPICIOUS_OBJECT_CHECKING */
-
-DEFUN ("suspicious-object", Fsuspicious_object, Ssuspicious_object, 1, 1, 0,
-       doc: /* Return OBJ, maybe marking it for extra scrutiny.
-If Emacs is compiled with suspicious object checking, capture
-a stack trace when OBJ is freed in order to help track down
-garbage collection bugs.  Otherwise, do nothing and return OBJ.   */)
-   (Lisp_Object obj)
-{
-#ifdef SUSPICIOUS_OBJECT_CHECKING
-  /* Right now, we care only about vectors.  */
-  if (VECTORLIKEP (obj))
-    {
-      suspicious_objects[suspicious_object_index++] = XVECTOR (obj);
-      if (suspicious_object_index == ARRAYELTS (suspicious_objects))
-       suspicious_object_index = 0;
-    }
-#endif
-  return obj;
-}
-
 #ifdef ENABLE_CHECKING
 
 bool suppress_checking;
@@ -8326,7 +8283,6 @@ N should be nonnegative.  */);
 #ifdef HAVE_MALLOC_TRIM
   defsubr (&Smalloc_trim);
 #endif
-  defsubr (&Ssuspicious_object);
 
   Lisp_Object watcher;
 
diff --git a/src/android-asset.h b/src/android-asset.h
index d7cf0f0cfed..a6b5aa3366c 100644
--- a/src/android-asset.h
+++ b/src/android-asset.h
@@ -1,6 +1,6 @@
 /* Android initialization for GNU Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/android-emacs.c b/src/android-emacs.c
index 2c405795860..5a43445612a 100644
--- a/src/android-emacs.c
+++ b/src/android-emacs.c
@@ -1,6 +1,6 @@
 /* Android initialization for GNU Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/android.c b/src/android.c
index 7ca5eab817c..4a74f5b2af4 100644
--- a/src/android.c
+++ b/src/android.c
@@ -1,6 +1,6 @@
 /* Android initialization for GNU Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -111,6 +111,7 @@ struct android_emacs_window
   jmethodID set_dont_focus_on_map;
   jmethodID define_cursor;
   jmethodID damage_rect;
+  jmethodID recreate_activity;
 };
 
 struct android_emacs_cursor
@@ -744,6 +745,19 @@ android_select (int nfds, fd_set *readfds, fd_set 
*writefds,
 
   if (event_queue.num_events)
     {
+      /* Zero READFDS, WRITEFDS and EXCEPTFDS, lest the caller
+        mistakenly interpret this return value as indicating that an
+        inotify file descriptor is readable, and try to poll an
+        unready one.  */
+
+      if (readfds)
+       FD_ZERO (readfds);
+
+      if (writefds)
+       FD_ZERO (writefds);
+
+      if (exceptfds)
+       FD_ZERO (exceptfds);
       pthread_mutex_unlock (&event_queue.mutex);
       return 1;
     }
@@ -1455,6 +1469,18 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject 
object,
      the possibility of Java locating libemacs later.  */
   setenv ("EMACS_LD_LIBRARY_PATH", android_lib_dir, 1);
 
+  /* If the system is Android 5.0 or later, set LANG to en_US.utf8,
+     which is understood by the C library.  In other instances set it
+     to C, a meaningless value, for good measure.  */
+
+  if (emacs_service_object)
+    {
+      if (api_level >= 21)
+       setenv ("LANG", "en_US.utf8", 1);
+      else
+       setenv ("LANG", "C", 1);
+    }
+
   /* Make a reference to the Emacs service.  */
 
   if (emacs_service_object)
@@ -1777,12 +1803,12 @@ android_init_emacs_window (void)
   FIND_METHOD (set_dont_accept_focus, "setDontAcceptFocus", "(Z)V");
   FIND_METHOD (define_cursor, "defineCursor",
               "(Lorg/gnu/emacs/EmacsCursor;)V");
-
   /* In spite of the declaration of this function being located within
      EmacsDrawable, the ID of the `damage_rect' method is retrieved
      from EmacsWindow, which avoids virtual function dispatch within
      android_damage_window.  */
   FIND_METHOD (damage_rect, "damageRect", "(IIII)V");
+  FIND_METHOD (recreate_activity, "recreateActivity", "()V");
 #undef FIND_METHOD
 }
 
@@ -2767,7 +2793,7 @@ android_destroy_handle (android_handle handle)
 
   /* Just clear any exception thrown.  If destroying the handle
      fails from an out-of-memory error, then Emacs loses some
-     resources, but that is not as big deal as signalling.  */
+     resources, but that is not as big deal as signaling.  */
   (*android_java_env)->ExceptionClear (android_java_env);
 
   /* Delete the global reference regardless of any error.  */
@@ -3937,10 +3963,10 @@ android_blit_copy (int src_x, int src_y, int width, int 
height,
 
          /* Turn both into offsets.  */
 
-         if (INT_MULTIPLY_WRAPV (temp, pixel, &offset)
-             || INT_MULTIPLY_WRAPV (i, mask_info->stride, &offset1)
-             || INT_ADD_WRAPV (offset, offset1, &offset)
-             || INT_ADD_WRAPV ((uintptr_t) mask, offset, &start))
+         if (ckd_mul (&offset, temp, pixel)
+             || ckd_mul (&offset1, i, mask_info->stride)
+             || ckd_add (&offset, offset, offset1)
+             || ckd_add (&start, (uintptr_t) mask, offset))
            return;
 
          if (height <= 0)
@@ -4245,10 +4271,10 @@ android_blit_xor (int src_x, int src_y, int width, int 
height,
 
          /* Turn both into offsets.  */
 
-         if (INT_MULTIPLY_WRAPV (temp, pixel, &offset)
-             || INT_MULTIPLY_WRAPV (i, mask_info->stride, &offset1)
-             || INT_ADD_WRAPV (offset, offset1, &offset)
-             || INT_ADD_WRAPV ((uintptr_t) mask, offset, &start))
+         if (ckd_mul (&offset, temp, pixel)
+             || ckd_mul (&offset1, i, mask_info->stride)
+             || ckd_add (&offset, offset, offset1)
+             || ckd_add (&start, (uintptr_t) mask, offset))
            return;
 
          mask = mask_current = (unsigned char *) start;
@@ -4873,9 +4899,9 @@ android_get_image (android_drawable handle,
 
   if (bitmap_info.format != ANDROID_BITMAP_FORMAT_A_8)
     {
-      if (INT_MULTIPLY_WRAPV ((size_t) bitmap_info.stride,
-                             (size_t) bitmap_info.height,
-                             &byte_size))
+      if (ckd_mul (&byte_size,
+                  (size_t) bitmap_info.stride,
+                  (size_t) bitmap_info.height))
        {
          ANDROID_DELETE_LOCAL_REF (bitmap);
          memory_full (0);
@@ -5785,7 +5811,7 @@ android_check_string (Lisp_Object text)
    better represent the UCS-16 based Java String format, and to let
    strings contain NULL characters while remaining valid C strings:
    NULL bytes are encoded as two-byte sequences, and Unicode surrogate
-   pairs encoded as two-byte sequences are prefered to four-byte
+   pairs encoded as two-byte sequences are preferred to four-byte
    sequences when encoding characters above the BMP.  */
 
 int
@@ -5983,7 +6009,7 @@ android_build_jstring (const char *text)
    is created.  */
 
 #if __GNUC__ >= 3
-#define likely(cond)   __builtin_expect ((cond), 1)
+#define likely(cond)   __builtin_expect (cond, 1)
 #else /* __GNUC__ < 3 */
 #define likely(cond)   (cond)
 #endif /* __GNUC__ >= 3 */
@@ -6613,6 +6639,24 @@ android_request_storage_access (void)
   android_exception_check ();
 }
 
+/* Recreate the activity to which WINDOW is attached to debug graphics
+   code executed in response to window attachment.  */
+
+void
+android_recreate_activity (android_window window)
+{
+  jobject object;
+  jmethodID method;
+
+  object = android_resolve_handle (window, ANDROID_HANDLE_WINDOW);
+  method = window_class.recreate_activity;
+
+  (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, object,
+                                                window_class.class,
+                                                method);
+  android_exception_check ();
+}
+
 
 
 /* The thread from which a query against a thread is currently being
diff --git a/src/android.h b/src/android.h
index 12f9472836f..2f5f32037c5 100644
--- a/src/android.h
+++ b/src/android.h
@@ -1,6 +1,6 @@
 /* Android initialization for GNU Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -309,7 +309,7 @@ extern struct timespec emacs_installation_time;
 
 #define ANDROID_DELETE_LOCAL_REF(ref)                          \
   ((*android_java_env)->DeleteLocalRef (android_java_env,      \
-                                       (ref)))
+                                       ref))
 
 #define NATIVE_NAME(name) Java_org_gnu_emacs_EmacsNative_##name
 
diff --git a/src/androidfns.c b/src/androidfns.c
index 31a4924e34d..eaecb78338b 100644
--- a/src/androidfns.c
+++ b/src/androidfns.c
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -27,6 +27,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include "keyboard.h"
 #include "buffer.h"
 #include "androidgui.h"
+#include "pdumper.h"
 
 #ifndef ANDROID_STUBIFY
 
@@ -1930,9 +1931,6 @@ android_create_tip_frame (struct android_display_info 
*dpyinfo,
 
   image_cache_refcount
     = FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
-#ifdef GLYPH_DEBUG
-  dpyinfo_refcount = dpyinfo->reference_count;
-#endif /* GLYPH_DEBUG */
 
   gui_default_parameter (f, parms, Qfont_backend, Qnil,
                          "fontBackend", "FontBackend", RES_TYPE_STRING);
@@ -3166,10 +3164,213 @@ android_set_preeditarea (struct window *w, int x, int 
y)
                                     y + w->phys_cursor_height);
 }
 
+
+
+/* Debugging.  */
+
+DEFUN ("android-recreate-activity", Fandroid_recreate_activity,
+       Sandroid_recreate_activity, 0, 0, "",
+       doc: /* Recreate the activity attached to the current frame.
+This function exists for debugging purposes and is of no interest to
+users.  */)
+  (void)
+{
+  struct frame *f;
+
+  f = decode_window_system_frame (Qnil);
+  android_recreate_activity (FRAME_ANDROID_WINDOW (f));
+  return Qnil;
+}
+
 #endif /* !ANDROID_STUBIFY */
 
 
 
+#ifndef ANDROID_STUBIFY
+
+static void
+syms_of_androidfns_for_pdumper (void)
+{
+  jclass locale;
+  jmethodID method;
+  jobject object;
+  jstring string;
+  Lisp_Object language, country, script, variant;
+  const char *data;
+
+  /* Find the Locale class.  */
+
+  locale = (*android_java_env)->FindClass (android_java_env,
+                                          "java/util/Locale");
+  if (!locale)
+    emacs_abort ();
+
+  /* And the method from which the default locale can be
+     extracted.  */
+
+  method = (*android_java_env)->GetStaticMethodID (android_java_env,
+                                                  locale,
+                                                  "getDefault",
+                                                  "()Ljava/util/Locale;");
+  if (!method)
+    emacs_abort ();
+
+  /* Retrieve the default locale.  */
+
+  object = (*android_java_env)->CallStaticObjectMethod (android_java_env,
+                                                       locale, method);
+  android_exception_check_1 (locale);
+
+  if (!object)
+    emacs_abort ();
+
+  /* Retrieve its language field.  Each of these methods is liable to
+     return the empty string, though if language is empty, the locale
+     is malformed.  */
+
+  method = (*android_java_env)->GetMethodID (android_java_env, locale,
+                                            "getLanguage",
+                                            "()Ljava/lang/String;");
+  if (!method)
+    emacs_abort ();
+
+  string = (*android_java_env)->CallObjectMethod (android_java_env, object,
+                                                 method);
+  android_exception_check_2 (object, locale);
+
+  if (!string)
+    language = empty_unibyte_string;
+  else
+    {
+      data = (*android_java_env)->GetStringUTFChars (android_java_env,
+                                                    string, NULL);
+      android_exception_check_3 (object, locale, string);
+
+      if (!data)
+       language = empty_unibyte_string;
+      else
+       {
+         language = build_unibyte_string (data);
+         (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+                                                     string, data);
+       }
+    }
+
+  /* Delete the reference to this string.  */
+  ANDROID_DELETE_LOCAL_REF (string);
+
+  /* Proceed to retrieve the country code.  */
+
+  method = (*android_java_env)->GetMethodID (android_java_env, locale,
+                                            "getCountry",
+                                            "()Ljava/lang/String;");
+  if (!method)
+    emacs_abort ();
+
+  string = (*android_java_env)->CallObjectMethod (android_java_env, object,
+                                                 method);
+  android_exception_check_2 (object, locale);
+
+  if (!string)
+    country = empty_unibyte_string;
+  else
+    {
+      data = (*android_java_env)->GetStringUTFChars (android_java_env,
+                                                    string, NULL);
+      android_exception_check_3 (object, locale, string);
+
+      if (!data)
+       country = empty_unibyte_string;
+      else
+       {
+         country = build_unibyte_string (data);
+         (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+                                                     string, data);
+       }
+    }
+
+  ANDROID_DELETE_LOCAL_REF (string);
+
+  /* Proceed to retrieve the script.  */
+
+  if (android_get_current_api_level () < 21)
+    script = empty_unibyte_string;
+  else
+    {
+      method = (*android_java_env)->GetMethodID (android_java_env, locale,
+                                                "getScript",
+                                                "()Ljava/lang/String;");
+      if (!method)
+       emacs_abort ();
+
+      string = (*android_java_env)->CallObjectMethod (android_java_env,
+                                                     object, method);
+      android_exception_check_2 (object, locale);
+
+      if (!string)
+       script = empty_unibyte_string;
+      else
+       {
+         data = (*android_java_env)->GetStringUTFChars (android_java_env,
+                                                        string, NULL);
+         android_exception_check_3 (object, locale, string);
+
+         if (!data)
+           script = empty_unibyte_string;
+         else
+           {
+             script = build_unibyte_string (data);
+             (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+                                                         string, data);
+           }
+       }
+    }
+
+  ANDROID_DELETE_LOCAL_REF (string);
+
+  /* And variant.  */
+
+  method = (*android_java_env)->GetMethodID (android_java_env, locale,
+                                            "getVariant",
+                                            "()Ljava/lang/String;");
+  if (!method)
+    emacs_abort ();
+
+  string = (*android_java_env)->CallObjectMethod (android_java_env, object,
+                                                 method);
+  android_exception_check_2 (object, locale);
+
+  if (!string)
+    variant = empty_unibyte_string;
+  else
+    {
+      data = (*android_java_env)->GetStringUTFChars (android_java_env,
+                                                    string, NULL);
+      android_exception_check_3 (object, locale, string);
+
+      if (!data)
+        variant = empty_unibyte_string;
+      else
+       {
+         variant = build_unibyte_string (data);
+         (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+                                                     string, data);
+       }
+    }
+
+  /* Delete the reference to this string.  */
+  ANDROID_DELETE_LOCAL_REF (string);
+
+  /* And other remaining local references.  */
+  ANDROID_DELETE_LOCAL_REF (object);
+  ANDROID_DELETE_LOCAL_REF (locale);
+
+  /* Set Vandroid_os_language.  */
+  Vandroid_os_language = list4 (language, country, script, variant);
+}
+
+#endif /* ANDROID_STUBIFY */
+
 void
 syms_of_androidfns (void)
 {
@@ -3313,6 +3514,25 @@ element that is activated for a given number of 
milliseconds upon the
 bell being rung.  */);
   android_keyboard_bell_duration = 50;
 
+  DEFVAR_LISP ("android-os-language", Vandroid_os_language,
+    doc: /* A list representing the configured system language on Android.
+This list has four elements: LANGUAGE, COUNTRY, SCRIPT and VARIANT, where:
+
+LANGUAGE and COUNTRY are ISO language and country codes identical to
+those found in POSIX locale specifications.
+
+SCRIPT is an ISO 15924 script tag, representing the script used
+if available, or if required to disambiguate between distinct
+writing systems for the same combination of language and country.
+
+VARIANT is an arbitrary string representing the variant of the
+LANGUAGE or SCRIPT.
+
+Each of these fields might be empty or nil, but the locale is invalid
+if LANGUAGE is empty.  Users of this variable should consider the
+language to be US English if LANGUAGE is empty.  */);
+  Vandroid_os_language = Qnil;
+
   /* Functions defined.  */
   defsubr (&Sx_create_frame);
   defsubr (&Sxw_color_defined_p);
@@ -3348,6 +3568,7 @@ bell being rung.  */);
   defsubr (&Sandroid_request_directory_access);
   defsubr (&Sandroid_external_storage_available_p);
   defsubr (&Sandroid_request_storage_access);
+  defsubr (&Sandroid_recreate_activity);
 
   tip_timer = Qnil;
   staticpro (&tip_timer);
@@ -3363,5 +3584,7 @@ bell being rung.  */);
   staticpro (&tip_dx);
   tip_dy = Qnil;
   staticpro (&tip_dy);
+
+  pdumper_do_now_and_after_load (syms_of_androidfns_for_pdumper);
 #endif /* !ANDROID_STUBIFY */
 }
diff --git a/src/androidfont.c b/src/androidfont.c
index 9a1bf5652fc..5fd3018b6d4 100644
--- a/src/androidfont.c
+++ b/src/androidfont.c
@@ -1,6 +1,6 @@
 /* Android fallback font driver.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/androidgui.h b/src/androidgui.h
index 5fab5023ba4..89317581191 100644
--- a/src/androidgui.h
+++ b/src/androidgui.h
@@ -1,5 +1,5 @@
 /* Android window system support.
-   Copyright (C) 2023 Free Software Foundation, Inc.
+   Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -708,6 +708,7 @@ extern void android_translate_coordinates (android_window, 
int,
 extern int android_wc_lookup_string (android_key_pressed_event *,
                                     wchar_t *, int, int *,
                                     enum android_lookup_status *);
+extern void android_recreate_activity (android_window);
 extern void android_update_ic (android_window, ptrdiff_t, ptrdiff_t,
                               ptrdiff_t, ptrdiff_t);
 extern void android_reset_ic (android_window, enum android_ic_mode);
diff --git a/src/androidmenu.c b/src/androidmenu.c
index 1f4d91b527d..362d500ac1a 100644
--- a/src/androidmenu.c
+++ b/src/androidmenu.c
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -437,7 +437,7 @@ android_menu_show (struct frame *f, int x, int y, int 
menuflags,
              /* Compute the item ID.  This is the index of value.
                 Make sure it doesn't overflow.  */
 
-             if (!INT_ADD_OK (0, i + MENU_ITEMS_ITEM_VALUE, &item_id))
+             if (ckd_add (&item_id, i + MENU_ITEMS_ITEM_VALUE, 0))
                memory_full (i + MENU_ITEMS_ITEM_VALUE * sizeof (Lisp_Object));
 
              /* Add this menu item with the appropriate state.  */
diff --git a/src/androidselect.c b/src/androidselect.c
index f7988db0520..5b23c559d2c 100644
--- a/src/androidselect.c
+++ b/src/androidselect.c
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -299,7 +299,7 @@ data type available from the clipboard.  */)
                                                bytes_array);
   for (i = 0; i < length; ++i)
     {
-      /* Retireve the MIME type.  */
+      /* Retrieve the MIME type.  */
       bytes
        = (*android_java_env)->GetObjectArrayElement (android_java_env,
                                                      bytes_array, i);
@@ -446,7 +446,7 @@ does not have any corresponding data.  In that case, use
     {
       rc = emacs_read_quit (fd, start, BUFSIZ);
 
-      if (!INT_ADD_OK (rc, length, &length)
+      if (ckd_add (&length, length, rc)
          || PTRDIFF_MAX - length < BUFSIZ)
        memory_full (PTRDIFF_MAX);
 
@@ -588,7 +588,7 @@ android_notifications_notify_1 (Lisp_Object title, 
Lisp_Object body,
   if (NILP (replaces_id))
     {
       /* Generate a new identifier.  */
-      INT_ADD_WRAPV (counter, 1, &counter);
+      ckd_add (&counter, counter, 1);
       id = counter;
     }
   else
diff --git a/src/androidterm.c b/src/androidterm.c
index cfb64cd69a0..d4612bb20fa 100644
--- a/src/androidterm.c
+++ b/src/androidterm.c
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -619,7 +619,7 @@ android_decode_utf16 (unsigned short *utf16, size_t n)
   struct coding_system coding;
   ptrdiff_t size;
 
-  if (INT_MULTIPLY_WRAPV (n, sizeof *utf16, &size))
+  if (ckd_mul (&size, n, sizeof *utf16))
     return Qnil;
 
   /* Set up the coding system.  Decoding a UTF-16 string (with no BOM)
@@ -938,9 +938,9 @@ handle_one_android_event (struct android_display_info 
*dpyinfo,
           sure it is processed before any subsequent edits.  */
        textconv_barrier (f, event->xkey.counter);
 
-      wchar_t copy_buffer[129];
+      wchar_t copy_buffer[512];
       wchar_t *copy_bufptr = copy_buffer;
-      int copy_bufsiz = 128 * sizeof (wchar_t);
+      int copy_bufsiz = 512;
 
       event->xkey.state
        |= android_emacs_to_android_modifiers (dpyinfo,
@@ -5010,7 +5010,7 @@ android_text_to_string (JNIEnv *env, char *buffer, 
ptrdiff_t n,
     {
       /* This buffer holds no multibyte characters.  */
 
-      if (INT_MULTIPLY_WRAPV (n, sizeof *utf16, &size))
+      if (ckd_mul (&size, n, sizeof *utf16))
        return NULL;
 
       utf16 = malloc (size);
@@ -5033,7 +5033,7 @@ android_text_to_string (JNIEnv *env, char *buffer, 
ptrdiff_t n,
 
   /* Allocate enough to hold N characters.  */
 
-  if (INT_MULTIPLY_WRAPV (n, sizeof *utf16, &size))
+  if (ckd_mul (&size, n, sizeof *utf16))
     return NULL;
 
   utf16 = malloc (size);
@@ -6101,7 +6101,7 @@ android_update_selection (struct frame *f, struct window 
*w)
   else
     start = -1, end = -1;
 
-  /* Now constrain START and END to the maximium size of a Java
+  /* Now constrain START and END to the maximum size of a Java
      integer.  */
   start = min (start, TYPE_MAXIMUM (jint));
   end = min (end, TYPE_MAXIMUM (jint));
@@ -6238,7 +6238,7 @@ android_reset_conversion (struct frame *f)
 
   android_reset_ic (FRAME_ANDROID_WINDOW (f), mode);
 
-  /* Clear extracted text flags.  Since the IM has been reinitialised,
+  /* Clear extracted text flags.  Since the IM has been reinitialized,
      it should no longer be displaying extracted text.  */
   FRAME_ANDROID_OUTPUT (f)->extracted_text_flags = 0;
 
diff --git a/src/androidterm.h b/src/androidterm.h
index e75d46b1dfb..41c93067e82 100644
--- a/src/androidterm.h
+++ b/src/androidterm.h
@@ -1,6 +1,6 @@
 /* Communication module for Android terminals.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -262,7 +262,7 @@ struct android_output
      text''.  */
   int extracted_text_flags;
 
-  /* Token asssociated with that request.  */
+  /* Token associated with that request.  */
   int extracted_text_token;
 
   /* The number of characters of extracted text wanted by the IM.  */
@@ -298,8 +298,8 @@ enum
    code after any drawing command, but code can be run whenever
    someone asks for the handle necessary to draw.  */
 #define FRAME_ANDROID_DRAWABLE(f)                      \
-  (((f))->output_data.android->need_buffer_flip = true, \
-   FRAME_ANDROID_WINDOW ((f)))
+  ((f)->output_data.android->need_buffer_flip = true, \
+   FRAME_ANDROID_WINDOW (f))
 
 /* Return whether or not the frame F has been completely drawn.  Used
    while handling async input.  */
diff --git a/src/androidvfs.c b/src/androidvfs.c
index 51558d2a375..78f6b6da6a8 100644
--- a/src/androidvfs.c
+++ b/src/androidvfs.c
@@ -1,6 +1,6 @@
 /* Android virtual file-system support for GNU Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -407,7 +407,7 @@ android_init_fd_class (JNIEnv *env)
    values are prohibitively slow, but smaller values can't face up to
    some long file names within several nested layers of directories.
 
-   Buffers holding components or other similar file name constitutents
+   Buffers holding components or other similar file name constituents
    which don't represent SAF files must continue to use PATH_MAX, for
    that is the restriction imposed by the Unix file system.  */
 
@@ -2388,8 +2388,8 @@ android_afs_opendir (struct android_vnode *vnode)
      and as such can be exactly one byte past directory_tree.  */
   if (dir->asset_limit > directory_tree + directory_tree_size)
     {
-      xfree (dir);
       xfree (dir->asset_file);
+      xfree (dir);
       errno = EACCES;
       return NULL;
     }
@@ -4179,7 +4179,7 @@ android_saf_stat (const char *uri_name, const char 
*id_name,
 }
 
 /* Detect if Emacs has access to the document designated by the the
-   documen ID ID_NAME within the tree URI_NAME.  If ID_NAME is NULL,
+   document ID ID_NAME within the tree URI_NAME.  If ID_NAME is NULL,
    use the document ID in URI_NAME itself.
 
    If WRITABLE, also check that the file is writable, which is true
@@ -5547,8 +5547,8 @@ android_saf_tree_opendir (struct android_vnode *vnode)
 
   if (!cursor)
     {
-      xfree (dir);
       xfree (dir->name);
+      xfree (dir);
       return NULL;
     }
 
@@ -6427,7 +6427,7 @@ android_root_name (struct android_vnode *vnode, char 
*name,
   if (!component_end)
     component_end = name + length;
   else
-    /* Move past the spearator character.  */
+    /* Move past the separator character.  */
     component_end++;
 
   /* Now, find out if the first component is a special vnode; if so,
@@ -7172,7 +7172,7 @@ android_readlinkat (int dirfd, const char *restrict 
pathname,
    while file streams also require ownership over file descriptors
    they are created on behalf of.
 
-   Detaching the parcel file descriptor linked to FD consequentially
+   Detaching the parcel file descriptor linked to FD consequently
    prevents the owner from being notified when it is eventually
    closed, but for now that hasn't been demonstrated to be problematic
    yet, as Emacs doesn't write to file streams.  */
diff --git a/src/atimer.c b/src/atimer.c
index d07cdb82b7a..8253ae3a166 100644
--- a/src/atimer.c
+++ b/src/atimer.c
@@ -1,5 +1,5 @@
 /* Asynchronous timers.
-   Copyright (C) 2000-2023 Free Software Foundation, Inc.
+   Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/atimer.h b/src/atimer.h
index 551c186d24e..51de226b82e 100644
--- a/src/atimer.h
+++ b/src/atimer.h
@@ -1,5 +1,5 @@
 /* Asynchronous timers.
-   Copyright (C) 2000-2023 Free Software Foundation, Inc.
+   Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/bidi.c b/src/bidi.c
index 3c26ae19322..a2b5054cb60 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -1,6 +1,6 @@
 /* Low-level bidirectional buffer/string-scanning functions for GNU Emacs.
 
-Copyright (C) 2000-2001, 2004-2005, 2009-2023 Free Software Foundation,
+Copyright (C) 2000-2001, 2004-2005, 2009-2024 Free Software Foundation,
 Inc.
 
 Author: Eli Zaretskii <eliz@gnu.org>
@@ -420,7 +420,7 @@ bidi_paired_bracket_type (int c)
 static void
 bidi_set_sos_type (struct bidi_it *bidi_it, int level_before, int level_after)
 {
-  int higher_level = (level_before > level_after ? level_before : level_after);
+  int higher_level = max (level_before, level_after);
 
   /* FIXME: should the default sos direction be user selectable?  */
   bidi_it->sos = ((higher_level & 1) != 0 ? R2L : L2R); /* X10 */
diff --git a/src/bignum.c b/src/bignum.c
index 22ed171533f..1fe195d78ea 100644
--- a/src/bignum.c
+++ b/src/bignum.c
@@ -1,6 +1,6 @@
 /* Big numbers for Emacs.
 
-Copyright 2018-2023 Free Software Foundation, Inc.
+Copyright 2018-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/bignum.h b/src/bignum.h
index b9957a642d1..2749f8370d0 100644
--- a/src/bignum.h
+++ b/src/bignum.h
@@ -1,6 +1,6 @@
 /* Big numbers for Emacs.
 
-Copyright 2018-2023 Free Software Foundation, Inc.
+Copyright 2018-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/blockinput.h b/src/blockinput.h
index 5fd63c2575c..88a1f68849e 100644
--- a/src/blockinput.h
+++ b/src/blockinput.h
@@ -1,5 +1,5 @@
 /* blockinput.h - interface to blocking complicated interrupt-driven input.
-   Copyright (C) 1989, 1993, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1989, 1993, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/buffer.c b/src/buffer.c
index a7299f4a49e..352aca8ddfd 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1,6 +1,6 @@
 /* Buffer manipulation primitives for GNU Emacs.
 
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -210,11 +210,6 @@ bset_buffer_file_coding_system (struct buffer *b, 
Lisp_Object val)
   b->buffer_file_coding_system_ = val;
 }
 static void
-bset_case_fold_search (struct buffer *b, Lisp_Object val)
-{
-  b->case_fold_search_ = val;
-}
-static void
 bset_ctl_arrow (struct buffer *b, Lisp_Object val)
 {
   b->ctl_arrow_ = val;
@@ -519,8 +514,11 @@ See also `find-buffer-visiting'.  */)
   return Qnil;
 }
 
-Lisp_Object
-get_truename_buffer (register Lisp_Object filename)
+DEFUN ("get-truename-buffer", Fget_truename_buffer, Sget_truename_buffer, 1, 
1, 0,
+       doc: /* Return the buffer with `file-truename' equal to FILENAME (a 
string).
+If there is no such live buffer, return nil.
+See also `find-buffer-visiting'.  */)
+  (register Lisp_Object filename)
 {
   register Lisp_Object tail, buf;
 
@@ -533,6 +531,22 @@ get_truename_buffer (register Lisp_Object filename)
   return Qnil;
 }
 
+DEFUN ("find-buffer", Ffind_buffer, Sfind_buffer, 2, 2, 0,
+       doc: /* Return the buffer with buffer-local VARIABLE `equal' to VALUE.
+If there is no such live buffer, return nil.
+See also `find-buffer-visiting'.  */)
+  (Lisp_Object variable, Lisp_Object value)
+{
+  register Lisp_Object tail, buf;
+
+  FOR_EACH_LIVE_BUFFER (tail, buf)
+    {
+      if (!NILP (Fequal (value, Fbuffer_local_value (variable, buf))))
+       return buf;
+    }
+  return Qnil;
+}
+
 /* Run buffer-list-update-hook if Vrun_hooks is non-nil and BUF does
    not have buffer hooks inhibited.  */
 
@@ -1739,7 +1753,7 @@ exists, return the buffer `*scratch*' (creating it if 
necessary).  */)
   if (!NILP (notsogood))
     return notsogood;
   else
-    return safe_call (1, Qget_scratch_buffer_create);
+    return safe_calln (Qget_scratch_buffer_create);
 }
 
 /* The following function is a safe variant of Fother_buffer: It doesn't
@@ -1760,7 +1774,7 @@ other_buffer_safely (Lisp_Object buffer)
      becoming dead under our feet.  safe_call below could return nil
      if recreating *scratch* in Lisp, which does some fancy stuff,
      signals an error in some weird use case.  */
-  buf = safe_call (1, Qget_scratch_buffer_create);
+  buf = safe_calln (Qget_scratch_buffer_create);
   if (NILP (buf))
     {
       AUTO_STRING (scratch, "*scratch*");
@@ -4673,7 +4687,6 @@ init_buffer_once (void)
   XSETFASTINT (BVAR (&buffer_local_flags, mode_line_format), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, abbrev_mode), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, overwrite_mode), idx); ++idx;
-  XSETFASTINT (BVAR (&buffer_local_flags, case_fold_search), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, auto_fill_function), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, selective_display), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, selective_display_ellipses), idx); 
++idx;
@@ -4766,7 +4779,6 @@ init_buffer_once (void)
   bset_tab_line_format (&buffer_defaults, Qnil);
   bset_abbrev_mode (&buffer_defaults, Qnil);
   bset_overwrite_mode (&buffer_defaults, Qnil);
-  bset_case_fold_search (&buffer_defaults, Qt);
   bset_auto_fill_function (&buffer_defaults, Qnil);
   bset_selective_display (&buffer_defaults, Qnil);
   bset_selective_display_ellipses (&buffer_defaults, Qt);
@@ -5196,10 +5208,6 @@ Format with `format-mode-line' to produce a string 
value.  */);
                     doc: /*  Non-nil if Abbrev mode is enabled.
 Use the command `abbrev-mode' to change this variable.  */);
 
-  DEFVAR_PER_BUFFER ("case-fold-search", &BVAR (current_buffer, 
case_fold_search),
-                    Qnil,
-                    doc: /* Non-nil if searches and matches should ignore 
case.  */);
-
   DEFVAR_PER_BUFFER ("fill-column", &BVAR (current_buffer, fill_column),
                     Qintegerp,
                     doc: /* Column beyond which automatic line-wrapping should 
happen.
@@ -5359,8 +5367,8 @@ visual lines rather than logical lines.  See the 
documentation of
                     Qstringp,
                     doc: /* Name of default directory of current buffer.
 It should be an absolute directory name; on GNU and Unix systems,
-these names start with `/' or `~' and end with `/'.
-To interactively change the default directory, use command `cd'. */);
+these names start with "/" or "~" and end with "/".
+To interactively change the default directory, use the command `cd'. */);
 
   DEFVAR_PER_BUFFER ("auto-fill-function", &BVAR (current_buffer, 
auto_fill_function),
                     Qnil,
@@ -5932,6 +5940,12 @@ If `delete-auto-save-files' is nil, any autosave 
deletion is inhibited.  */);
 This is the default.  If nil, auto-save file deletion is inhibited.  */);
   delete_auto_save_files = 1;
 
+  DEFVAR_LISP ("case-fold-search", Vcase_fold_search,
+              doc: /* Non-nil if searches and matches should ignore case.  */);
+  Vcase_fold_search = Qt;
+  DEFSYM (Qcase_fold_search, "case-fold-search");
+  Fmake_variable_buffer_local (Qcase_fold_search);
+
   DEFVAR_LISP ("clone-indirect-buffer-hook", Vclone_indirect_buffer_hook,
               doc: /* Normal hook to run in the new buffer at the end of 
`make-indirect-buffer'.
 
@@ -6010,6 +6024,8 @@ There is no reason to change that value except for 
debugging purposes.  */);
   defsubr (&Sbuffer_list);
   defsubr (&Sget_buffer);
   defsubr (&Sget_file_buffer);
+  defsubr (&Sget_truename_buffer);
+  defsubr (&Sfind_buffer);
   defsubr (&Sget_buffer_create);
   defsubr (&Smake_indirect_buffer);
   defsubr (&Sgenerate_new_buffer_name);
diff --git a/src/buffer.h b/src/buffer.h
index b2bd15657dc..9e0982f5da7 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -1,6 +1,6 @@
 /* Header file for the buffer manipulation primitives.
 
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -216,7 +216,7 @@ extern ptrdiff_t advance_to_char_boundary (ptrdiff_t 
byte_pos);
 /* Return the byte at byte position N.
    Do not check that the position is in range.  */
 
-#define FETCH_BYTE(n) *(BYTE_POS_ADDR ((n)))
+#define FETCH_BYTE(n) (*BYTE_POS_ADDR (n))
 
 /* Define the actual buffer data structures.  */
 
@@ -379,7 +379,6 @@ struct buffer
   /* Values of several buffer-local variables.  */
   /* tab-width is buffer-local so that redisplay can find it
      in buffers that are not current.  */
-  Lisp_Object case_fold_search_;
   Lisp_Object tab_width_;
   Lisp_Object fill_column_;
   Lisp_Object left_margin_;
diff --git a/src/bytecode.c b/src/bytecode.c
index c53ef678edd..dd805cbd97a 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -1,5 +1,5 @@
 /* Execution of byte code produced by bytecomp.el.
-   Copyright (C) 1985-1988, 1993, 2000-2023 Free Software Foundation,
+   Copyright (C) 1985-1988, 1993, 2000-2024 Free Software Foundation,
    Inc.
 
 This file is part of GNU Emacs.
@@ -625,9 +625,10 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
        varref:
          {
            Lisp_Object v1 = vectorp[op], v2;
-           if (!SYMBOLP (v1)
-               || XSYMBOL (v1)->u.s.redirect != SYMBOL_PLAINVAL
-               || (v2 = SYMBOL_VAL (XSYMBOL (v1)), BASE_EQ (v2, Qunbound)))
+           if (!BARE_SYMBOL_P (v1)
+               || XBARE_SYMBOL (v1)->u.s.redirect != SYMBOL_PLAINVAL
+               || (v2 = XBARE_SYMBOL (v1)->u.s.val.value,
+                   BASE_EQ (v2, Qunbound)))
              v2 = Fsymbol_value (v1);
            PUSH (v2);
            NEXT;
@@ -699,11 +700,11 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
            Lisp_Object val = POP;
 
            /* Inline the most common case.  */
-           if (SYMBOLP (sym)
+           if (BARE_SYMBOL_P (sym)
                && !BASE_EQ (val, Qunbound)
-               && XSYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL
-               && !SYMBOL_TRAPPED_WRITE_P (sym))
-             SET_SYMBOL_VAL (XSYMBOL (sym), val);
+               && XBARE_SYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL
+               && !XBARE_SYMBOL (sym)->u.s.trapped_write)
+             SET_SYMBOL_VAL (XBARE_SYMBOL (sym), val);
            else
               set_internal (sym, val, Qnil, SET_INTERNAL_SET);
          }
@@ -790,24 +791,22 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
              do_debug_on_call (Qlambda, count1);
 
            Lisp_Object original_fun = call_fun;
-           if (SYMBOLP (call_fun))
-             call_fun = XSYMBOL (call_fun)->u.s.function;
-           Lisp_Object template;
-           Lisp_Object bytecode;
-           if (COMPILEDP (call_fun)
-               /* Lexical binding only.  */
-               && (template = AREF (call_fun, COMPILED_ARGLIST),
-                   FIXNUMP (template))
-               /* No autoloads.  */
-               && (bytecode = AREF (call_fun, COMPILED_BYTECODE),
-                   !CONSP (bytecode)))
+           /* Calls to symbols-with-pos don't need to be on the fast path.  */
+           if (BARE_SYMBOL_P (call_fun))
+             call_fun = XBARE_SYMBOL (call_fun)->u.s.function;
+           if (COMPILEDP (call_fun))
              {
-               fun = call_fun;
-               bytestr = bytecode;
-               args_template = XFIXNUM (template);
-               nargs = call_nargs;
-               args = call_args;
-               goto setup_frame;
+               Lisp_Object template = AREF (call_fun, COMPILED_ARGLIST);
+               if (FIXNUMP (template))
+                 {
+                   /* Fast path for lexbound functions.  */
+                   fun = call_fun;
+                   bytestr = AREF (call_fun, COMPILED_BYTECODE),
+                   args_template = XFIXNUM (template);
+                   nargs = call_nargs;
+                   args = call_args;
+                   goto setup_frame;
+                 }
              }
 
            Lisp_Object val;
@@ -1743,7 +1742,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
 
             /* h->count is a faster approximation for HASH_TABLE_SIZE (h)
                here. */
-            if (h->count <= 5 && !h->test.cmpfn)
+            if (h->count <= 5 && !h->test->cmpfn)
               { /* Do a linear search if there are not many cases
                    FIXME: 5 is arbitrarily chosen.  */
                for (i = h->count; 0 <= --i; )
@@ -1751,7 +1750,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
                    break;
               }
             else
-              i = hash_lookup (h, v1, NULL);
+              i = hash_lookup (h, v1);
 
            if (i >= 0)
              {
diff --git a/src/callint.c b/src/callint.c
index 00e9a080654..b31faba8704 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -1,5 +1,5 @@
 /* Call a Lisp function interactively.
-   Copyright (C) 1985-1986, 1993-1995, 1997, 2000-2023 Free Software
+   Copyright (C) 1985-1986, 1993-1995, 1997, 2000-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/callproc.c b/src/callproc.c
index 96db52402c8..db36ef569e6 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -1,6 +1,6 @@
 /* Synchronous subprocess invocation for GNU Emacs.
 
-Copyright (C) 1985-1988, 1993-1995, 1999-2023 Free Software Foundation,
+Copyright (C) 1985-1988, 1993-1995, 1999-2024 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/casefiddle.c b/src/casefiddle.c
index 3afb131c50e..b252f07ae13 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -1,7 +1,7 @@
 /* -*- coding: utf-8 -*- */
 /* GNU Emacs case conversion functions.
 
-Copyright (C) 1985, 1994, 1997-1999, 2001-2023 Free Software Foundation,
+Copyright (C) 1985, 1994, 1997-1999, 2001-2024 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/casetab.c b/src/casetab.c
index f844022395a..41e9004e10f 100644
--- a/src/casetab.c
+++ b/src/casetab.c
@@ -1,5 +1,5 @@
 /* GNU Emacs routines to deal with case tables.
-   Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 Author: Howard Gayle
 
diff --git a/src/category.c b/src/category.c
index dac5c78b5af..498b6a2a1c9 100644
--- a/src/category.c
+++ b/src/category.c
@@ -1,6 +1,6 @@
 /* GNU Emacs routines to deal with category tables.
 
-Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
   2005, 2006, 2007, 2008, 2009, 2010, 2011
   National Institute of Advanced Industrial Science and Technology (AIST)
@@ -51,12 +51,10 @@ hash_get_category_set (Lisp_Object table, Lisp_Object 
category_set)
   if (NILP (XCHAR_TABLE (table)->extras[1]))
     set_char_table_extras
       (table, 1,
-       make_hash_table (hashtest_equal, DEFAULT_HASH_SIZE,
-                       DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
-                       Qnil, false));
+       make_hash_table (&hashtest_equal, DEFAULT_HASH_SIZE, Weak_None, false));
   struct Lisp_Hash_Table *h = XHASH_TABLE (XCHAR_TABLE (table)->extras[1]);
-  Lisp_Object hash;
-  ptrdiff_t i = hash_lookup (h, category_set, &hash);
+  hash_hash_t hash;
+  ptrdiff_t i = hash_lookup_get_hash (h, category_set, &hash);
   if (i >= 0)
     return HASH_KEY (h, i);
   hash_put (h, category_set, Qnil, hash);
diff --git a/src/ccl.c b/src/ccl.c
index 67f2a275841..a3a03a5b7b1 100644
--- a/src/ccl.c
+++ b/src/ccl.c
@@ -1,5 +1,5 @@
 /* CCL (Code Conversion Language) interpreter.
-   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
      2005, 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
@@ -51,7 +51,7 @@ static Lisp_Object Vccl_program_table;
 
 /* Return a hash table of id number ID.  */
 #define GET_HASH_TABLE(id) \
-  (XHASH_TABLE (XCDR (AREF (Vtranslation_hash_table_vector, (id)))))
+  XHASH_TABLE (XCDR (AREF (Vtranslation_hash_table_vector, id)))
 
 /* CCL (Code Conversion Language) is a simple language which has
    operations on one input buffer, one output buffer, and 7 registers.
@@ -627,7 +627,7 @@ do                                                          
\
   {                                                            \
     struct ccl_program called_ccl;                             \
     if (stack_idx >= 256                                       \
-       || ! setup_ccl_program (&called_ccl, (symbol)))         \
+       || ! setup_ccl_program (&called_ccl, symbol))           \
       {                                                                \
        if (stack_idx > 0)                                      \
          {                                                     \
@@ -818,7 +818,7 @@ while (0)
 
 #define CCL_DECODE_CHAR(id, code)      \
   ((id) == 0 ? (code)                  \
-   : (charset = CHARSET_FROM_ID ((id)), DECODE_CHAR (charset, (code))))
+   : (charset = CHARSET_FROM_ID (id), DECODE_CHAR (charset, code)))
 
 /* Encode character C by some of charsets in CHARSET_LIST.  Set ID to
    the id of the used charset, ENCODED to the result of encoding.
@@ -828,9 +828,9 @@ while (0)
   do {                                                         \
     unsigned ncode;                                            \
                                                                \
-    charset = char_charset ((c), (charset_list), &ncode);      \
+    charset = char_charset (c, charset_list, &ncode);          \
     if (! charset && ! NILP (charset_list))                    \
-      charset = char_charset ((c), Qnil, &ncode);              \
+      charset = char_charset (c, Qnil, &ncode);                        \
     if (charset)                                               \
       {                                                                \
        (id) = CHARSET_ID (charset);                            \
@@ -873,7 +873,7 @@ static struct ccl_prog_stack ccl_prog_stack_struct[256];
 static inline Lisp_Object
 GET_TRANSLATION_TABLE (int id)
 {
-  return XCDR (XVECTOR (Vtranslation_table_vector)->contents[id]);
+  return XCDR (AREF (Vtranslation_table_vector, id));
 }
 
 void
@@ -1380,7 +1380,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int 
*destination, int src_size
 
                eop = (FIXNUM_OVERFLOW_P (reg[RRR])
                       ? -1
-                      : hash_lookup (h, make_fixnum (reg[RRR]), NULL));
+                      : hash_lookup (h, make_fixnum (reg[RRR])));
                if (eop >= 0)
                  {
                    Lisp_Object opl;
@@ -1409,7 +1409,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int 
*destination, int src_size
 
                eop = (FIXNUM_OVERFLOW_P (i)
                       ? -1
-                      : hash_lookup (h, make_fixnum (i), NULL));
+                      : hash_lookup (h, make_fixnum (i)));
                if (eop >= 0)
                  {
                    Lisp_Object opl;
diff --git a/src/ccl.h b/src/ccl.h
index 8eb9d7eb2e8..b8bdcad4c32 100644
--- a/src/ccl.h
+++ b/src/ccl.h
@@ -82,7 +82,7 @@ extern void ccl_driver (struct ccl_program *, int *, int *, 
int, int,
 #define CHECK_CCL_PROGRAM(x)                   \
   do {                                         \
     if (NILP (Fccl_program_p (x)))             \
-      wrong_type_argument (Qcclp, (x));        \
+      wrong_type_argument (Qcclp, x);          \
   } while (false);
 
 #endif /* EMACS_CCL_H */
diff --git a/src/character.c b/src/character.c
index 2118b20a7c7..dcad8f83793 100644
--- a/src/character.c
+++ b/src/character.c
@@ -1,6 +1,6 @@
 /* Basic character support.
 
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 Copyright (C) 1995, 1997, 1998, 2001 Electrotechnical Laboratory, JAPAN.
   Licensed to the Free Software Foundation.
 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
diff --git a/src/charset.c b/src/charset.c
index d5e42d038df..4bacc011e85 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -1,6 +1,6 @@
 /* Basic character set support.
 
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
   2005, 2006, 2007, 2008, 2009, 2010, 2011
@@ -850,7 +850,6 @@ usage: (define-charset-internal ...)  */)
   /* Charset attr vector.  */
   Lisp_Object attrs;
   Lisp_Object val;
-  Lisp_Object hash_code;
   struct Lisp_Hash_Table *hash_table = XHASH_TABLE (Vcharset_hash_table);
   int i, j;
   struct charset charset;
@@ -1108,18 +1107,19 @@ usage: (define-charset-internal ...)  */)
   CHECK_LIST (args[charset_arg_plist]);
   ASET (attrs, charset_plist, args[charset_arg_plist]);
 
-  charset.hash_index = hash_lookup (hash_table, args[charset_arg_name],
-                                   &hash_code);
-  if (charset.hash_index >= 0)
+  hash_hash_t hash_code;
+  ptrdiff_t hash_index
+    = hash_lookup_get_hash (hash_table, args[charset_arg_name],
+                           &hash_code);
+  if (hash_index >= 0)
     {
-      new_definition_p = 0;
+      new_definition_p = false;
       id = XFIXNAT (CHARSET_SYMBOL_ID (args[charset_arg_name]));
-      set_hash_value_slot (hash_table, charset.hash_index, attrs);
+      set_hash_value_slot (hash_table, hash_index, attrs);
     }
   else
     {
-      charset.hash_index = hash_put (hash_table, args[charset_arg_name], attrs,
-                                    hash_code);
+      hash_put (hash_table, args[charset_arg_name], attrs, hash_code);
       if (charset_table_used == charset_table_size)
        {
          /* Ensure that charset IDs fit into 'int' as well as into the
@@ -1150,6 +1150,7 @@ usage: (define-charset-internal ...)  */)
 
   ASET (attrs, charset_id, make_fixnum (id));
   charset.id = id;
+  charset.attributes = attrs;
   charset_table[id] = charset;
 
   if (charset.method == CHARSET_METHOD_MAP)
@@ -1790,7 +1791,7 @@ encode_char (struct charset *charset, int c)
       return CHARSET_INVALID_CODE (charset);
     }
 
-  if (! CHARSET_FAST_MAP_REF ((c), charset->fast_map)
+  if (! CHARSET_FAST_MAP_REF (c, charset->fast_map)
       || c < CHARSET_MIN_CHAR (charset) || c > CHARSET_MAX_CHAR (charset))
     return CHARSET_INVALID_CODE (charset);
 
@@ -2269,6 +2270,15 @@ See also `charset-priority-list' and 
`set-charset-priority'.  */)
   return charsets;
 }
 
+/* Not strictly necessary, because all charset attributes are also
+   reachable from `Vcharset_hash_table`.  */
+void
+mark_charset (void)
+{
+  for (int i = 0; i < charset_table_used; i++)
+    mark_object (charset_table[i].attributes);
+}
+
 
 void
 init_charset (void)
diff --git a/src/charset.h b/src/charset.h
index 6d115fa3596..1edb4a248ac 100644
--- a/src/charset.h
+++ b/src/charset.h
@@ -1,5 +1,5 @@
 /* Header for charset handler.
-   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
      2005, 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
@@ -150,8 +150,7 @@ struct charset
   /* Index to charset_table.  */
   int id;
 
-  /* Index to Vcharset_hash_table.  */
-  ptrdiff_t hash_index;
+  Lisp_Object attributes;
 
   /* Dimension of the charset: 1, 2, 3, or 4.  */
   int dimension;
@@ -267,18 +266,18 @@ extern int emacs_mule_charset[256];
 
 /* Return the attribute vector of charset whose symbol is SYMBOL.  */
 #define CHARSET_SYMBOL_ATTRIBUTES(symbol)      \
-  Fgethash ((symbol), Vcharset_hash_table, Qnil)
-
-#define CHARSET_ATTR_ID(attrs)         AREF ((attrs), charset_id)
-#define CHARSET_ATTR_NAME(attrs)       AREF ((attrs), charset_name)
-#define CHARSET_ATTR_PLIST(attrs)      AREF ((attrs), charset_plist)
-#define CHARSET_ATTR_MAP(attrs)                AREF ((attrs), charset_map)
-#define CHARSET_ATTR_DECODER(attrs)    AREF ((attrs), charset_decoder)
-#define CHARSET_ATTR_ENCODER(attrs)    AREF ((attrs), charset_encoder)
-#define CHARSET_ATTR_SUBSET(attrs)     AREF ((attrs), charset_subset)
-#define CHARSET_ATTR_SUPERSET(attrs)   AREF ((attrs), charset_superset)
-#define CHARSET_ATTR_UNIFY_MAP(attrs)  AREF ((attrs), charset_unify_map)
-#define CHARSET_ATTR_DEUNIFIER(attrs)  AREF ((attrs), charset_deunifier)
+  Fgethash (symbol, Vcharset_hash_table, Qnil)
+
+#define CHARSET_ATTR_ID(attrs)         AREF (attrs, charset_id)
+#define CHARSET_ATTR_NAME(attrs)       AREF (attrs, charset_name)
+#define CHARSET_ATTR_PLIST(attrs)      AREF (attrs, charset_plist)
+#define CHARSET_ATTR_MAP(attrs)                AREF (attrs, charset_map)
+#define CHARSET_ATTR_DECODER(attrs)    AREF (attrs, charset_decoder)
+#define CHARSET_ATTR_ENCODER(attrs)    AREF (attrs, charset_encoder)
+#define CHARSET_ATTR_SUBSET(attrs)     AREF (attrs, charset_subset)
+#define CHARSET_ATTR_SUPERSET(attrs)   AREF (attrs, charset_superset)
+#define CHARSET_ATTR_UNIFY_MAP(attrs)  AREF (attrs, charset_unify_map)
+#define CHARSET_ATTR_DEUNIFIER(attrs)  AREF (attrs, charset_deunifier)
 
 #define CHARSET_SYMBOL_ID(symbol)      \
   CHARSET_ATTR_ID (CHARSET_SYMBOL_ATTRIBUTES (symbol))
@@ -286,14 +285,12 @@ extern int emacs_mule_charset[256];
 /* Return an index to Vcharset_hash_table of the charset whose symbol
    is SYMBOL.  */
 #define CHARSET_SYMBOL_HASH_INDEX(symbol)      \
-  hash_lookup (XHASH_TABLE (Vcharset_hash_table), symbol, NULL)
+  hash_lookup (XHASH_TABLE (Vcharset_hash_table), symbol)
 
 /* Return the attribute vector of CHARSET.  */
-#define CHARSET_ATTRIBUTES(charset)    \
-  (HASH_VALUE (XHASH_TABLE (Vcharset_hash_table), (charset)->hash_index))
+#define CHARSET_ATTRIBUTES(charset) (charset)->attributes
 
 #define CHARSET_ID(charset)            ((charset)->id)
-#define CHARSET_HASH_INDEX(charset)    ((charset)->hash_index)
 #define CHARSET_DIMENSION(charset)     ((charset)->dimension)
 #define CHARSET_CODE_SPACE(charset)    ((charset)->code_space)
 #define CHARSET_CODE_LINEAR_P(charset) ((charset)->code_linear_p)
@@ -314,21 +311,21 @@ extern int emacs_mule_charset[256];
 #define CHARSET_UNIFIED_P(charset)     ((charset)->unified_p)
 
 #define CHARSET_NAME(charset)          \
-  (CHARSET_ATTR_NAME (CHARSET_ATTRIBUTES (charset)))
+  CHARSET_ATTR_NAME (CHARSET_ATTRIBUTES (charset))
 #define CHARSET_MAP(charset)   \
-  (CHARSET_ATTR_MAP (CHARSET_ATTRIBUTES (charset)))
+  CHARSET_ATTR_MAP (CHARSET_ATTRIBUTES (charset))
 #define CHARSET_DECODER(charset)       \
-  (CHARSET_ATTR_DECODER (CHARSET_ATTRIBUTES (charset)))
+  CHARSET_ATTR_DECODER (CHARSET_ATTRIBUTES (charset))
 #define CHARSET_ENCODER(charset)       \
-  (CHARSET_ATTR_ENCODER (CHARSET_ATTRIBUTES (charset)))
+  CHARSET_ATTR_ENCODER (CHARSET_ATTRIBUTES (charset))
 #define CHARSET_SUBSET(charset)        \
-  (CHARSET_ATTR_SUBSET (CHARSET_ATTRIBUTES (charset)))
+  CHARSET_ATTR_SUBSET (CHARSET_ATTRIBUTES (charset))
 #define CHARSET_SUPERSET(charset)      \
-  (CHARSET_ATTR_SUPERSET (CHARSET_ATTRIBUTES (charset)))
+  CHARSET_ATTR_SUPERSET (CHARSET_ATTRIBUTES (charset))
 #define CHARSET_UNIFY_MAP(charset)     \
-  (CHARSET_ATTR_UNIFY_MAP (CHARSET_ATTRIBUTES (charset)))
+  CHARSET_ATTR_UNIFY_MAP (CHARSET_ATTRIBUTES (charset))
 #define CHARSET_DEUNIFIER(charset)     \
-  (CHARSET_ATTR_DEUNIFIER (CHARSET_ATTRIBUTES (charset)))
+  CHARSET_ATTR_DEUNIFIER (CHARSET_ATTRIBUTES (charset))
 
 INLINE void
 set_charset_attr (struct charset *charset, enum charset_attr_index idx,
@@ -345,7 +342,7 @@ set_charset_attr (struct charset *charset, enum 
charset_attr_index idx,
 #define CHECK_CHARSET(x)                                       \
   do {                                                         \
     if (! SYMBOLP (x) || CHARSET_SYMBOL_HASH_INDEX (x) < 0)    \
-      wrong_type_argument (Qcharsetp, (x));                    \
+      wrong_type_argument (Qcharsetp, x);                      \
   } while (false)
 
 
@@ -356,7 +353,7 @@ set_charset_attr (struct charset *charset, enum 
charset_attr_index idx,
     ptrdiff_t idx;                                                     \
                                                                        \
     if (! SYMBOLP (x) || (idx = CHARSET_SYMBOL_HASH_INDEX (x)) < 0)    \
-      wrong_type_argument (Qcharsetp, (x));                            \
+      wrong_type_argument (Qcharsetp, x);                              \
     id = XFIXNUM (AREF (HASH_VALUE (XHASH_TABLE (Vcharset_hash_table), idx), \
                     charset_id));                                      \
   } while (false)
@@ -367,7 +364,7 @@ set_charset_attr (struct charset *charset, enum 
charset_attr_index idx,
 #define CHECK_CHARSET_GET_ATTR(x, attr)                                \
   do {                                                                 \
     if (!SYMBOLP (x) || NILP (attr = CHARSET_SYMBOL_ATTRIBUTES (x)))   \
-      wrong_type_argument (Qcharsetp, (x));                            \
+      wrong_type_argument (Qcharsetp, x);                              \
   } while (false)
 
 
@@ -383,7 +380,7 @@ set_charset_attr (struct charset *charset, enum 
charset_attr_index idx,
    contains the character C.  */
 #define CHAR_CHARSET(c)                                \
   ((c) < 0x80 ? CHARSET_FROM_ID (charset_ascii)        \
-   : char_charset ((c), Qnil, NULL))
+   : char_charset (c, Qnil, NULL))
 
 #if false
 /* Char-table of charset-sets.  Each element is a bool vector indexed
@@ -410,18 +407,18 @@ extern Lisp_Object Vchar_charset_set;
    : ((code) < (charset)->min_code || (code) > (charset)->max_code)    \
    ? -1                                                                        
\
    : (charset)->unified_p                                              \
-   ? decode_char ((charset), (code))                                   \
+   ? decode_char (charset, code)                                       \
    : (charset)->method == CHARSET_METHOD_OFFSET                                
\
    ? ((charset)->code_linear_p                                         \
       ? (int) ((code) - (charset)->min_code) + (charset)->code_offset  \
-      : decode_char ((charset), (code)))                               \
+      : decode_char (charset, code))                                   \
    : (charset)->method == CHARSET_METHOD_MAP                           \
    ? (((charset)->code_linear_p                                                
\
        && VECTORP (CHARSET_DECODER (charset)))                         \
       ? XFIXNUM (AREF (CHARSET_DECODER (charset),                              
\
                    (code) - (charset)->min_code))                      \
-      : decode_char ((charset), (code)))                               \
-   : decode_char ((charset), (code)))
+      : decode_char (charset, code))                                   \
+   : decode_char (charset, code))
 
 extern Lisp_Object charset_work;
 
@@ -462,7 +459,7 @@ extern bool charset_map_loaded;
 /* Set CHARSET to the charset highest priority of C, CODE to the
    code-point of C in CHARSET.  */
 #define SPLIT_CHAR(c, charset, code)   \
-  ((charset) = char_charset ((c), Qnil, &(code)))
+  ((charset) = char_charset (c, Qnil, &(code)))
 
 
 #define ISO_MAX_DIMENSION 3
@@ -501,15 +498,15 @@ extern int 
iso_charset_table[ISO_MAX_DIMENSION][ISO_MAX_CHARS][ISO_MAX_FINAL];
    || ((CHARSET_UNIFIED_P (charset)                                     \
        || (charset)->method == CHARSET_METHOD_SUBSET                    \
        || (charset)->method == CHARSET_METHOD_SUPERSET)                 \
-       ? encode_char ((charset), (c)) != (charset)->invalid_code        \
-       : (CHARSET_FAST_MAP_REF ((c), (charset)->fast_map)               \
+       ? encode_char (charset, c) != (charset)->invalid_code    \
+       : (CHARSET_FAST_MAP_REF (c, (charset)->fast_map)                 \
          && ((charset)->method == CHARSET_METHOD_OFFSET                 \
              ? (c) >= (charset)->min_char && (c) <= (charset)->max_char \
              : ((charset)->method == CHARSET_METHOD_MAP                 \
                 && (charset)->compact_codes_p                           \
                 && CHAR_TABLE_P (CHARSET_ENCODER (charset)))            \
-             ? ! NILP (CHAR_TABLE_REF (CHARSET_ENCODER (charset), (c))) \
-             : encode_char ((charset), (c)) != (charset)->invalid_code))))
+             ? ! NILP (CHAR_TABLE_REF (CHARSET_ENCODER (charset), c))   \
+             : encode_char (charset, c) != (charset)->invalid_code))))
 
 
 /* Special macros for emacs-mule encoding.  */
diff --git a/src/cm.c b/src/cm.c
index 4711085d796..d6b54d507c7 100644
--- a/src/cm.c
+++ b/src/cm.c
@@ -1,5 +1,5 @@
 /* Cursor motion subroutines for GNU Emacs.
-   Copyright (C) 1985, 1995, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1995, 2001-2024 Free Software Foundation, Inc.
     based primarily on public domain code written by Chris Torek
 
 This file is part of GNU Emacs.
diff --git a/src/cm.h b/src/cm.h
index 70d2c7078fc..871980551d9 100644
--- a/src/cm.h
+++ b/src/cm.h
@@ -1,5 +1,5 @@
 /* Cursor motion calculation definitions for GNU Emacs
-   Copyright (C) 1985, 1989, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1989, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/cmds.c b/src/cmds.c
index a9b4bd9c321..81788b07242 100644
--- a/src/cmds.c
+++ b/src/cmds.c
@@ -1,6 +1,6 @@
 /* Simple built-in editing commands.
 
-Copyright (C) 1985, 1993-1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1993-1998, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/coding.c b/src/coding.c
index b7f4120dc8d..5f3ceab718b 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -1,5 +1,5 @@
 /* Coding system handler (conversion, detection, etc).
-   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
      2005, 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
@@ -314,9 +314,9 @@ static Lisp_Object Vbig5_coding_system;
 /* ISO2022 section */
 
 #define CODING_ISO_INITIAL(coding, reg)                        \
-  (XFIXNUM (AREF (AREF (CODING_ID_ATTRS ((coding)->id),        \
-                    coding_attr_iso_initial),          \
-              reg)))
+  XFIXNUM (AREF (AREF (CODING_ID_ATTRS ((coding)->id), \
+                      coding_attr_iso_initial),        \
+                reg))
 
 
 #define CODING_ISO_REQUEST(coding, charset_id)         \
@@ -466,7 +466,7 @@ enum iso_code_class_type
 #define CODING_CCL_ENCODER(coding)     \
   AREF (CODING_ID_ATTRS ((coding)->id), coding_attr_ccl_encoder)
 #define CODING_CCL_VALIDS(coding)                                         \
-  (SDATA (AREF (CODING_ID_ATTRS ((coding)->id), coding_attr_ccl_valids)))
+  SDATA (AREF (CODING_ID_ATTRS ((coding)->id), coding_attr_ccl_valids))
 
 /* Index for each coding category in `coding_categories' */
 
@@ -4198,12 +4198,12 @@ decode_coding_iso_2022 (struct coding_system *coding)
 #define ENCODE_ISO_CHARACTER(charset, c)                                  \
   do {                                                                    \
     unsigned code;                                                        \
-    CODING_ENCODE_CHAR (coding, dst, dst_end, (charset), (c), code);      \
+    CODING_ENCODE_CHAR (coding, dst, dst_end, charset, c, code);          \
                                                                           \
     if (CHARSET_DIMENSION (charset) == 1)                                 \
-      ENCODE_ISO_CHARACTER_DIMENSION1 ((charset), code);                  \
+      ENCODE_ISO_CHARACTER_DIMENSION1 (charset, code);            \
     else                                                                  \
-      ENCODE_ISO_CHARACTER_DIMENSION2 ((charset), code >> 8, code & 0xFF); \
+      ENCODE_ISO_CHARACTER_DIMENSION2 (charset, code >> 8, code & 0xFF); \
   } while (0)
 
 
@@ -7658,8 +7658,7 @@ consume_chars (struct coding_system *coding, Lisp_Object 
translation_table,
          if (pos == stop_charset)
            buf = handle_charset_annotation (pos, end_pos, coding,
                                             buf, &stop_charset);
-         stop = (stop_composition < stop_charset
-                 ? stop_composition : stop_charset);
+         stop = min (stop_composition, stop_charset);
        }
 
       if (! multibytep)
@@ -8170,7 +8169,7 @@ decode_coding_object (struct coding_system *coding,
                             Fcons (undo_list, Fcurrent_buffer ()));
       bset_undo_list (current_buffer, Qt);
       TEMP_SET_PT_BOTH (coding->dst_pos, coding->dst_pos_byte);
-      val = safe_call1 (CODING_ATTR_POST_READ (attrs),
+      val = safe_calln (CODING_ATTR_POST_READ (attrs),
                        make_fixnum (coding->produced_char));
       CHECK_FIXNAT (val);
       coding->produced_char += Z - prev_Z;
@@ -8336,7 +8335,7 @@ encode_coding_object (struct coding_system *coding,
          set_buffer_internal (XBUFFER (coding->src_object));
        }
 
-      safe_call2 (CODING_ATTR_PRE_WRITE (attrs),
+      safe_calln (CODING_ATTR_PRE_WRITE (attrs),
                  make_fixnum (BEG), make_fixnum (Z));
       if (XBUFFER (coding->src_object) != current_buffer)
        kill_src_buffer = 1;
diff --git a/src/coding.h b/src/coding.h
index 08c29c884a5..8905e36838d 100644
--- a/src/coding.h
+++ b/src/coding.h
@@ -1,5 +1,5 @@
 /* Header for coding system handler.
-   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
      2005, 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
@@ -166,35 +166,35 @@ enum coding_attr_index
 
 /* Return the name of a coding system specified by ID.  */
 #define CODING_ID_NAME(id) \
-  (HASH_KEY (XHASH_TABLE (Vcoding_system_hash_table), id))
+  HASH_KEY (XHASH_TABLE (Vcoding_system_hash_table), id)
 
 /* Return the attribute vector of a coding system specified by ID.  */
 
 #define CODING_ID_ATTRS(id)    \
-  (AREF (HASH_VALUE (XHASH_TABLE (Vcoding_system_hash_table), id), 0))
+  AREF (HASH_VALUE (XHASH_TABLE (Vcoding_system_hash_table), id), 0)
 
 /* Return the list of aliases of a coding system specified by ID.  */
 
 #define CODING_ID_ALIASES(id)  \
-  (AREF (HASH_VALUE (XHASH_TABLE (Vcoding_system_hash_table), id), 1))
+  AREF (HASH_VALUE (XHASH_TABLE (Vcoding_system_hash_table), id), 1)
 
 /* Return the eol-type of a coding system specified by ID.  */
 
 #define CODING_ID_EOL_TYPE(id) \
-  (AREF (HASH_VALUE (XHASH_TABLE (Vcoding_system_hash_table), id), 2))
+  AREF (HASH_VALUE (XHASH_TABLE (Vcoding_system_hash_table), id), 2)
 
 
 /* Return the spec vector of CODING_SYSTEM_SYMBOL.  */
 
 #define CODING_SYSTEM_SPEC(coding_system_symbol)       \
-  (Fgethash (coding_system_symbol, Vcoding_system_hash_table, Qnil))
+  Fgethash (coding_system_symbol, Vcoding_system_hash_table, Qnil)
 
 
 /* Return the ID of CODING_SYSTEM_SYMBOL.  */
 
 #define CODING_SYSTEM_ID(coding_system_symbol)                 \
   hash_lookup (XHASH_TABLE (Vcoding_system_hash_table),                \
-              coding_system_symbol, NULL)
+              coding_system_symbol)
 
 /* Return true if CODING_SYSTEM_SYMBOL is a coding system.  */
 
@@ -209,7 +209,7 @@ enum coding_attr_index
   do {                                                 \
     if (CODING_SYSTEM_ID (x) < 0                       \
        && NILP (Fcheck_coding_system (x)))             \
-      wrong_type_argument (Qcoding_system_p, (x));     \
+      wrong_type_argument (Qcoding_system_p, x);       \
   } while (false)
 
 
@@ -225,7 +225,7 @@ enum coding_attr_index
        spec = CODING_SYSTEM_SPEC (x);                  \
       }                                                        \
     if (NILP (spec))                                   \
-      wrong_type_argument (Qcoding_system_p, (x));     \
+      wrong_type_argument (Qcoding_system_p, x);       \
   } while (false)
 
 
@@ -242,7 +242,7 @@ enum coding_attr_index
          id = CODING_SYSTEM_ID (x);                            \
        }                                                       \
       if (id < 0)                                              \
-       wrong_type_argument (Qcoding_system_p, (x));    \
+       wrong_type_argument (Qcoding_system_p, x);              \
     } while (false)
 
 
@@ -745,10 +745,9 @@ extern Lisp_Object from_unicode_buffer (const wchar_t 
*wstr);
 
 #define decode_coding_c_string(coding, src, bytes, dst_object)         \
   do {                                                                 \
-    (coding)->source = (src);                                          \
-    (coding)->src_chars = (coding)->src_bytes = (bytes);               \
-    decode_coding_object ((coding), Qnil, 0, 0, (bytes), (bytes),      \
-                         (dst_object));                                \
+    (coding)->source = src;                                            \
+    (coding)->src_chars = (coding)->src_bytes = bytes;                 \
+    decode_coding_object (coding, Qnil, 0, 0, bytes, bytes, dst_object); \
   } while (false)
 
 
diff --git a/src/commands.h b/src/commands.h
index ac7cdb60db3..6ba81241f99 100644
--- a/src/commands.h
+++ b/src/commands.h
@@ -1,5 +1,5 @@
 /* Definitions needed by most editing commands.
-   Copyright (C) 1985, 1994, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1994, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/comp.c b/src/comp.c
index b81a80b00f8..853757f6162 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -1,5 +1,5 @@
 /* Compile Emacs Lisp into native code.
-   Copyright (C) 2019-2023 Free Software Foundation, Inc.
+   Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 Author: Andrea Corallo <acorallo@gnu.org>
 
@@ -522,7 +522,7 @@ load_gccjit_if_necessary (bool mandatory)
 
 #define DECL_BLOCK(name, func)                         \
   gcc_jit_block *(name) =                              \
-    gcc_jit_function_new_block ((func), STR (name))
+    gcc_jit_function_new_block (func, STR (name))
 
 #ifndef WINDOWSNT
 # ifdef HAVE__SETJMP
@@ -4330,11 +4330,10 @@ compile_function (Lisp_Object func)
   declare_block (Qentry);
   Lisp_Object blocks = CALL1I (comp-func-blocks, func);
   struct Lisp_Hash_Table *ht = XHASH_TABLE (blocks);
-  for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (ht); i++)
+  DOHASH_SAFE (ht, i)
     {
       Lisp_Object block_name = HASH_KEY (ht, i);
-      if (!EQ (block_name, Qentry)
-         && !BASE_EQ (block_name, Qunbound))
+      if (!EQ (block_name, Qentry))
        declare_block (block_name);
     }
 
@@ -4344,24 +4343,21 @@ compile_function (Lisp_Object func)
                                gcc_jit_lvalue_as_rvalue (comp.func_relocs));
 
 
-  for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (ht); i++)
+  DOHASH_SAFE (ht, i)
     {
       Lisp_Object block_name = HASH_KEY (ht, i);
-      if (!BASE_EQ (block_name, Qunbound))
+      Lisp_Object block = HASH_VALUE (ht, i);
+      Lisp_Object insns = CALL1I (comp-block-insns, block);
+      if (NILP (block) || NILP (insns))
+       xsignal1 (Qnative_ice,
+                 build_string ("basic block is missing or empty"));
+
+      comp.block = retrive_block (block_name);
+      while (CONSP (insns))
        {
-         Lisp_Object block = HASH_VALUE (ht, i);
-         Lisp_Object insns = CALL1I (comp-block-insns, block);
-         if (NILP (block) || NILP (insns))
-           xsignal1 (Qnative_ice,
-                     build_string ("basic block is missing or empty"));
-
-         comp.block = retrive_block (block_name);
-         while (CONSP (insns))
-           {
-             Lisp_Object insn = XCAR (insns);
-             emit_limple_insn (insn);
-             insns = XCDR (insns);
-           }
+         Lisp_Object insn = XCAR (insns);
+         emit_limple_insn (insn);
+         insns = XCDR (insns);
        }
     }
   const char *err =  gcc_jit_context_get_first_error (comp.ctxt);
@@ -4965,14 +4961,12 @@ DEFUN ("comp--compile-ctxt-to-file", 
Fcomp__compile_ctxt_to_file,
 
   struct Lisp_Hash_Table *func_h =
     XHASH_TABLE (CALL1I (comp-ctxt-funcs-h, Vcomp_ctxt));
-  for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++)
-    if (!BASE_EQ (HASH_VALUE (func_h, i), Qunbound))
-      declare_function (HASH_VALUE (func_h, i));
+  DOHASH_SAFE (func_h, i)
+    declare_function (HASH_VALUE (func_h, i));
   /* Compile all functions. Can't be done before because the
      relocation structs has to be already defined.  */
-  for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++)
-    if (!BASE_EQ (HASH_VALUE (func_h, i), Qunbound))
-      compile_function (HASH_VALUE (func_h, i));
+  DOHASH_SAFE (func_h, i)
+    compile_function (HASH_VALUE (func_h, i));
 
   /* Work around bug#46495 (GCC PR99126). */
 #if defined (WIDE_EMACS_INT)                                           \
diff --git a/src/comp.h b/src/comp.h
index f86f3c5ed85..158ed0b46df 100644
--- a/src/comp.h
+++ b/src/comp.h
@@ -1,6 +1,6 @@
 /* Elisp native compiler definitions
 
-Copyright (C) 2019-2023 Free Software Foundation, Inc.
+Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/composite.c b/src/composite.c
index 9332c1cb9a3..111b1cea88b 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -1,5 +1,5 @@
 /* Composite sequence support.
-   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 
2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H14PRO021
@@ -166,7 +166,7 @@ ptrdiff_t
 get_composition_id (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t nchars,
                    Lisp_Object prop, Lisp_Object string)
 {
-  Lisp_Object id, length, components, key, *key_contents, hash_code;
+  Lisp_Object id, length, components, key, *key_contents;
   ptrdiff_t glyph_len;
   struct Lisp_Hash_Table *hash_table = XHASH_TABLE (composition_hash_table);
   ptrdiff_t hash_index;
@@ -240,7 +240,8 @@ get_composition_id (ptrdiff_t charpos, ptrdiff_t bytepos, 
ptrdiff_t nchars,
   else
     goto invalid_composition;
 
-  hash_index = hash_lookup (hash_table, key, &hash_code);
+  hash_hash_t hash_code;
+  hash_index = hash_lookup_get_hash (hash_table, key, &hash_code);
   if (hash_index >= 0)
     {
       /* We have already registered the same composition.  Change PROP
@@ -320,7 +321,7 @@ get_composition_id (ptrdiff_t charpos, ptrdiff_t bytepos, 
ptrdiff_t nchars,
   cmp = xmalloc (sizeof *cmp);
 
   cmp->method = method;
-  cmp->hash_index = hash_index;
+  cmp->key = key;
   cmp->glyph_len = glyph_len;
   cmp->offsets = xnmalloc (glyph_len, 2 * sizeof *cmp->offsets);
   cmp->font = NULL;
@@ -642,10 +643,7 @@ static Lisp_Object gstring_hash_table;
 Lisp_Object
 composition_gstring_lookup_cache (Lisp_Object header)
 {
-  struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
-  ptrdiff_t i = hash_lookup (h, header, NULL);
-
-  return (i >= 0 ? HASH_VALUE (h, i) : Qnil);
+  return Fgethash (header, gstring_hash_table, Qnil);
 }
 
 Lisp_Object
@@ -653,7 +651,7 @@ composition_gstring_put_cache (Lisp_Object gstring, 
ptrdiff_t len)
 {
   struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
   Lisp_Object header = LGSTRING_HEADER (gstring);
-  Lisp_Object hash = h->test.hashfn (header, h);
+  EMACS_UINT hash = hash_from_key (h, header);
   if (len < 0)
     {
       ptrdiff_t glyph_len = LGSTRING_GLYPH_LEN (gstring);
@@ -675,7 +673,7 @@ Lisp_Object
 composition_gstring_from_id (ptrdiff_t id)
 {
   struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
-
+  /* FIXME: The stability of this value depends on the hash table internals!  
*/
   return HASH_VALUE (h, id);
 }
 
@@ -686,18 +684,9 @@ composition_gstring_cache_clear_font (Lisp_Object 
font_object)
 {
   struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
 
-  for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
-    {
-      Lisp_Object k = HASH_KEY (h, i);
-
-      if (!BASE_EQ (k, Qunbound))
-       {
-         Lisp_Object gstring = HASH_VALUE (h, i);
-
-         if (EQ (LGSTRING_FONT (gstring), font_object))
-           hash_remove_from_table (h, k);
-       }
-    }
+  DOHASH (h, k, gstring)
+    if (EQ (LGSTRING_FONT (gstring), font_object))
+      hash_remove_from_table (h, k);
 }
 
 DEFUN ("clear-composition-cache", Fclear_composition_cache,
@@ -987,7 +976,7 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, 
ptrdiff_t bytepos,
       if (NILP (string))
        record_unwind_protect (restore_point_unwind,
                               build_marker (current_buffer, pt, pt_byte));
-      lgstring = safe_call (7, Vauto_composition_function, AREF (rule, 2),
+      lgstring = safe_calln (Vauto_composition_function, AREF (rule, 2),
                            pos, make_fixnum (to), font_object, string,
                            direction);
     }
@@ -2159,6 +2148,16 @@ of the way buffer text is examined for matching one of 
the rules.  */)
 }
 
 
+/* Not strictly necessary, because all those "keys" are also
+   reachable from `composition_hash_table`.  */
+void
+mark_composite (void)
+{
+  for (int i = 0; i < n_compositions; i++)
+    mark_object (composition_table[i]->key);
+}
+
+
 void
 syms_of_composite (void)
 {
diff --git a/src/composite.h b/src/composite.h
index 0f791c1ea62..4b412cea696 100644
--- a/src/composite.h
+++ b/src/composite.h
@@ -1,5 +1,5 @@
 /* Header for composite sequence handler.
-   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 
2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H14PRO021
@@ -84,23 +84,20 @@ composition_registered_p (Lisp_Object prop)
    ? XCDR (XCDR (XCDR (prop)))                 \
    : CONSP (prop) ? XCDR (prop) : Qnil)
 
+#define COMPOSITION_KEY(cmp) (cmp)->key
+
 /* Return the Nth glyph of composition specified by CMP.  CMP is a
    pointer to `struct composition'.  */
 #define COMPOSITION_GLYPH(cmp, n)                                      \
-  XFIXNUM (XVECTOR (XVECTOR (XHASH_TABLE (composition_hash_table)              
\
-                         ->key_and_value)                              \
-                ->contents[cmp->hash_index * 2])                       \
-       ->contents[cmp->method == COMPOSITION_WITH_RULE_ALTCHARS        \
-                 ? (n) * 2 : (n)])
+  XFIXNUM (AREF (COMPOSITION_KEY (cmp),                                        
\
+                (cmp)->method == COMPOSITION_WITH_RULE_ALTCHARS        \
+                ? (n) * 2 : (n)))
 
 /* Return the encoded composition rule to compose the Nth glyph of
    rule-base composition specified by CMP.  CMP is a pointer to
    `struct composition'. */
-#define COMPOSITION_RULE(cmp, n)                               \
-  XFIXNUM (XVECTOR (XVECTOR (XHASH_TABLE (composition_hash_table)      \
-                         ->key_and_value)                      \
-                ->contents[cmp->hash_index * 2])               \
-       ->contents[(n) * 2 - 1])
+#define COMPOSITION_RULE(cmp, n)                                       \
+  XFIXNUM (AREF (COMPOSITION_KEY (cmp), (n) * 2 - 1))
 
 /* Decode encoded composition rule RULE_CODE into GREF (global
    reference point code), NREF (new ref. point code).  Don't check RULE_CODE;
@@ -165,8 +162,8 @@ struct composition {
   /* Method of the composition.  */
   enum composition_method method;
 
-  /* Index to the composition hash table.  */
-  ptrdiff_t hash_index;
+  /* The key under which it's found in the composition hash table.  */
+  Lisp_Object key;
 
   /* For which font we have calculated the remaining members.  The
      actual type is device dependent.  */
@@ -202,6 +199,7 @@ extern bool find_composition (ptrdiff_t, ptrdiff_t, 
ptrdiff_t *, ptrdiff_t *,
 extern void update_compositions (ptrdiff_t, ptrdiff_t, int);
 extern void make_composition_value_copy (Lisp_Object);
 extern void syms_of_composite (void);
+extern void mark_composite (void);
 extern void compose_text (ptrdiff_t, ptrdiff_t, Lisp_Object, Lisp_Object,
                           Lisp_Object);
 
@@ -262,8 +260,8 @@ composition_valid_p (ptrdiff_t start, ptrdiff_t end, 
Lisp_Object prop)
 #define LGSTRING_CHAR(lgs, i) AREF (LGSTRING_HEADER (lgs), (i) + 1)
 #define LGSTRING_CHAR_LEN(lgs) (ASIZE (LGSTRING_HEADER (lgs)) - 1)
 
-#define LGSTRING_SET_FONT(lgs, val) ASET (LGSTRING_HEADER (lgs), 0, (val))
-#define LGSTRING_SET_CHAR(lgs, i, c) ASET (LGSTRING_HEADER (lgs), (i) + 1, (c))
+#define LGSTRING_SET_FONT(lgs, val) ASET (LGSTRING_HEADER (lgs), 0, val)
+#define LGSTRING_SET_CHAR(lgs, i, c) ASET (LGSTRING_HEADER (lgs), (i) + 1, c)
 
 #define LGSTRING_ID(lgs) AREF (lgs, 1)
 #define LGSTRING_SET_ID(lgs, id) ASET (lgs, 1, id)
@@ -272,9 +270,9 @@ composition_valid_p (ptrdiff_t start, ptrdiff_t end, 
Lisp_Object prop)
    LGSTRING can hold.  This is NOT the actual number of valid LGLYPHs;
    to find the latter, walk the glyphs returned by LGSTRING_GLYPH
    until the first one that is nil.  */
-#define LGSTRING_GLYPH_LEN(lgs) (ASIZE ((lgs)) - 2)
-#define LGSTRING_GLYPH(lgs, idx) AREF ((lgs), (idx) + 2)
-#define LGSTRING_SET_GLYPH(lgs, idx, val) ASET ((lgs), (idx) + 2, (val))
+#define LGSTRING_GLYPH_LEN(lgs) (ASIZE (lgs) - 2)
+#define LGSTRING_GLYPH(lgs, idx) AREF (lgs, (idx) + 2)
+#define LGSTRING_SET_GLYPH(lgs, idx, val) ASET (lgs, (idx) + 2, val)
 INLINE Lisp_Object *
 lgstring_glyph_addr (Lisp_Object lgs, ptrdiff_t idx)
 {
@@ -300,33 +298,33 @@ enum lglyph_indices
    contributed to the glyph (since there isn't a 1:1 correspondence
    between composed characters and the font glyphs).  */
 #define LGLYPH_NEW() make_nil_vector (LGLYPH_SIZE)
-#define LGLYPH_FROM(g) XFIXNUM (AREF ((g), LGLYPH_IX_FROM))
-#define LGLYPH_TO(g) XFIXNUM (AREF ((g), LGLYPH_IX_TO))
-#define LGLYPH_CHAR(g) XFIXNUM (AREF ((g), LGLYPH_IX_CHAR))
+#define LGLYPH_FROM(g) XFIXNUM (AREF (g, LGLYPH_IX_FROM))
+#define LGLYPH_TO(g) XFIXNUM (AREF (g, LGLYPH_IX_TO))
+#define LGLYPH_CHAR(g) XFIXNUM (AREF (g, LGLYPH_IX_CHAR))
 #define LGLYPH_CODE(g)                                         \
-  (NILP (AREF ((g), LGLYPH_IX_CODE))                           \
+  (NILP (AREF (g, LGLYPH_IX_CODE))                             \
    ? FONT_INVALID_CODE                                         \
    : cons_to_unsigned (AREF (g, LGLYPH_IX_CODE), TYPE_MAXIMUM (unsigned)))
-#define LGLYPH_WIDTH(g) XFIXNUM (AREF ((g), LGLYPH_IX_WIDTH))
-#define LGLYPH_LBEARING(g) XFIXNUM (AREF ((g), LGLYPH_IX_LBEARING))
-#define LGLYPH_RBEARING(g) XFIXNUM (AREF ((g), LGLYPH_IX_RBEARING))
-#define LGLYPH_ASCENT(g) XFIXNUM (AREF ((g), LGLYPH_IX_ASCENT))
-#define LGLYPH_DESCENT(g) XFIXNUM (AREF ((g), LGLYPH_IX_DESCENT))
-#define LGLYPH_ADJUSTMENT(g) AREF ((g), LGLYPH_IX_ADJUSTMENT)
-#define LGLYPH_SET_FROM(g, val) ASET ((g), LGLYPH_IX_FROM, make_fixnum (val))
-#define LGLYPH_SET_TO(g, val) ASET ((g), LGLYPH_IX_TO, make_fixnum (val))
-#define LGLYPH_SET_CHAR(g, val) ASET ((g), LGLYPH_IX_CHAR, make_fixnum (val))
+#define LGLYPH_WIDTH(g) XFIXNUM (AREF (g, LGLYPH_IX_WIDTH))
+#define LGLYPH_LBEARING(g) XFIXNUM (AREF (g, LGLYPH_IX_LBEARING))
+#define LGLYPH_RBEARING(g) XFIXNUM (AREF (g, LGLYPH_IX_RBEARING))
+#define LGLYPH_ASCENT(g) XFIXNUM (AREF (g, LGLYPH_IX_ASCENT))
+#define LGLYPH_DESCENT(g) XFIXNUM (AREF (g, LGLYPH_IX_DESCENT))
+#define LGLYPH_ADJUSTMENT(g) AREF (g, LGLYPH_IX_ADJUSTMENT)
+#define LGLYPH_SET_FROM(g, val) ASET (g, LGLYPH_IX_FROM, make_fixnum (val))
+#define LGLYPH_SET_TO(g, val) ASET (g, LGLYPH_IX_TO, make_fixnum (val))
+#define LGLYPH_SET_CHAR(g, val) ASET (g, LGLYPH_IX_CHAR, make_fixnum (val))
 /* Callers must assure that VAL is not negative!  */
 #define LGLYPH_SET_CODE(g, val)                                                
\
   ASET (g, LGLYPH_IX_CODE,                                             \
        val == FONT_INVALID_CODE ? Qnil : INT_TO_INTEGER (val))
 
-#define LGLYPH_SET_WIDTH(g, val) ASET ((g), LGLYPH_IX_WIDTH, make_fixnum (val))
-#define LGLYPH_SET_LBEARING(g, val) ASET ((g), LGLYPH_IX_LBEARING, make_fixnum 
(val))
-#define LGLYPH_SET_RBEARING(g, val) ASET ((g), LGLYPH_IX_RBEARING, make_fixnum 
(val))
-#define LGLYPH_SET_ASCENT(g, val) ASET ((g), LGLYPH_IX_ASCENT, make_fixnum 
(val))
-#define LGLYPH_SET_DESCENT(g, val) ASET ((g), LGLYPH_IX_DESCENT, make_fixnum 
(val))
-#define LGLYPH_SET_ADJUSTMENT(g, val) ASET ((g), LGLYPH_IX_ADJUSTMENT, (val))
+#define LGLYPH_SET_WIDTH(g, val) ASET (g, LGLYPH_IX_WIDTH, make_fixnum (val))
+#define LGLYPH_SET_LBEARING(g, val) ASET (g, LGLYPH_IX_LBEARING, make_fixnum 
(val))
+#define LGLYPH_SET_RBEARING(g, val) ASET (g, LGLYPH_IX_RBEARING, make_fixnum 
(val))
+#define LGLYPH_SET_ASCENT(g, val) ASET (g, LGLYPH_IX_ASCENT, make_fixnum (val))
+#define LGLYPH_SET_DESCENT(g, val) ASET (g, LGLYPH_IX_DESCENT, make_fixnum 
(val))
+#define LGLYPH_SET_ADJUSTMENT(g, val) ASET (g, LGLYPH_IX_ADJUSTMENT, val)
 
 #define LGLYPH_XOFF(g) (VECTORP (LGLYPH_ADJUSTMENT (g)) \
                        ? XFIXNUM (AREF (LGLYPH_ADJUSTMENT (g), 0)) : 0)
diff --git a/src/conf_post.h b/src/conf_post.h
index f31e012dc6e..83a0dd1b09b 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -1,6 +1,6 @@
 /* conf_post.h --- configure.ac includes this via AH_BOTTOM
 
-Copyright (C) 1988, 1993-1994, 1999-2002, 2004-2023 Free Software
+Copyright (C) 1988, 1993-1994, 1999-2002, 2004-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -96,7 +96,7 @@ typedef bool bool_bf;
 #ifdef emacs
 /* We include stdlib.h here, because Gnulib's stdlib.h might redirect
    'free' to its replacement, and we want to avoid that in unexec
-   builds.  Inclduing it here will render its inclusion after config.h
+   builds.  Including it here will render its inclusion after config.h
    a no-op.  */
 # if (defined DARWIN_OS && defined HAVE_UNEXEC) || defined HYBRID_MALLOC
 #  include <stdlib.h>
@@ -178,8 +178,8 @@ You lose; /* Emacs for DOS must be compiled with DJGPP */
 
 /* Things that lib/reg* wants.  */
 
-#define mbrtowc(pwc, s, n, ps) mbtowc ((pwc), (s), (n))
-#define wcrtomb(s, wc, ps) wctomb ((s), (wc))
+#define mbrtowc(pwc, s, n, ps) mbtowc (pwc, s, n)
+#define wcrtomb(s, wc, ps) wctomb (s, wc)
 #define btowc(b) ((wchar_t) (b))
 #define towupper(chr) toupper (chr)
 #define towlower(chr) tolower (chr)
@@ -317,7 +317,7 @@ extern int emacs_setenv_TZ (char const *);
   type _GL_ATTRIBUTE_MAY_ALIAS *name = (type *) (addr)
 
 #if 3 <= __GNUC__
-# define ATTRIBUTE_SECTION(name) __attribute__((section (name)))
+# define ATTRIBUTE_SECTION(name) __attribute__ ((section (name)))
 #else
 # define ATTRIBUTE_SECTION(name)
 #endif
diff --git a/src/cygw32.c b/src/cygw32.c
index 35cac23504e..7658e9a24a0 100644
--- a/src/cygw32.c
+++ b/src/cygw32.c
@@ -1,5 +1,5 @@
 /* Cygwin support routines.
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/cygw32.h b/src/cygw32.h
index 6f8706e3436..cc3414a39d9 100644
--- a/src/cygw32.h
+++ b/src/cygw32.h
@@ -1,5 +1,5 @@
 /* Header for Cygwin support routines.
-   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/data.c b/src/data.c
index b2b58fe9594..755c49f0272 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1,5 +1,5 @@
 /* Primitive operations on Lisp data types for GNU Emacs Lisp interpreter.
-   Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2023 Free Software
+   Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 97094e407d7..7069e27e3eb 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -1,5 +1,5 @@
 /* Elisp bindings for D-Bus.
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/decompress.c b/src/decompress.c
index 162f6167b73..fcdbb40fc90 100644
--- a/src/decompress.c
+++ b/src/decompress.c
@@ -1,5 +1,5 @@
 /* Interface to zlib.
-   Copyright (C) 2013-2023 Free Software Foundation, Inc.
+   Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/deps.mk b/src/deps.mk
index a7c8ae11f72..65536729014 100644
--- a/src/deps.mk
+++ b/src/deps.mk
@@ -1,6 +1,6 @@
 ### deps.mk --- src/Makefile fragment for GNU Emacs
 
-## Copyright (C) 1985, 1987-1988, 1993-1995, 1999-2023 Free Software
+## Copyright (C) 1985, 1987-1988, 1993-1995, 1999-2024 Free Software
 ## Foundation, Inc.
 
 ## This file is part of GNU Emacs.
diff --git a/src/dired.c b/src/dired.c
index c10531cdb16..9a372201ae0 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -1,5 +1,5 @@
 /* Lisp functions for making directory listings.
-   Copyright (C) 1985-1986, 1993-1994, 1999-2023 Free Software
+   Copyright (C) 1985-1986, 1993-1994, 1999-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/dispextern.h b/src/dispextern.h
index 3a4d6095f73..5387cb45603 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1,6 +1,6 @@
 /* Interface definitions for display code.
 
-Copyright (C) 1985, 1993-1994, 1997-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1993-1994, 1997-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -315,7 +315,7 @@ struct text_pos
 /* Set marker MARKER from text position POS.  */
 
 #define SET_MARKER_FROM_TEXT_POS(MARKER, POS) \
-     set_marker_both ((MARKER), Qnil, CHARPOS ((POS)), BYTEPOS ((POS)))
+     set_marker_both (MARKER, Qnil, CHARPOS (POS), BYTEPOS (POS))
 
 /* Value is non-zero if character and byte positions of POS1 and POS2
    are equal.  */
@@ -399,7 +399,7 @@ GLYPH_CODE_FACE (Lisp_Object gc)
        SET_GLYPH (glyph, XFIXNUM (XCAR (gc)), XFIXNUM (XCDR (gc)));            
\
       else                                                             \
        SET_GLYPH (glyph, (XFIXNUM (gc) & ((1 << CHARACTERBITS)-1)),    \
-                  (XFIXNUM (gc) >> CHARACTERBITS));                    \
+                  XFIXNUM (gc) >> CHARACTERBITS);                      \
     }                                                                  \
   while (false)
 
@@ -676,9 +676,9 @@ struct glyph
    defined in lisp.h.  */
 
 #define SET_CHAR_GLYPH_FROM_GLYPH(GLYPH, FROM)                 \
-     SET_CHAR_GLYPH ((GLYPH),                                  \
-                    GLYPH_CHAR ((FROM)),                       \
-                    GLYPH_FACE ((FROM)),                       \
+     SET_CHAR_GLYPH (GLYPH,                                    \
+                    GLYPH_CHAR (FROM),                         \
+                    GLYPH_FACE (FROM),                         \
                     false)
 
 /* Construct a glyph code from a character glyph GLYPH.  If the
@@ -689,9 +689,9 @@ struct glyph
   do                                                           \
     {                                                          \
       if ((GLYPH).u.ch < 256)                                  \
-       SET_GLYPH ((G), (GLYPH).u.ch, ((GLYPH).face_id));       \
+       SET_GLYPH (G, (GLYPH).u.ch, (GLYPH).face_id);           \
       else                                                     \
-       SET_GLYPH ((G), -1, 0);                                 \
+       SET_GLYPH (G, -1, 0);                                   \
     }                                                          \
   while (false)
 
@@ -837,7 +837,7 @@ struct glyph_matrix
 
 #ifdef GLYPH_DEBUG
 void check_matrix_pointer_lossage (struct glyph_matrix *);
-#define CHECK_MATRIX(MATRIX) check_matrix_pointer_lossage ((MATRIX))
+#define CHECK_MATRIX(MATRIX) check_matrix_pointer_lossage (MATRIX)
 #else
 #define CHECK_MATRIX(MATRIX) ((void) 0)
 #endif
@@ -1130,7 +1130,7 @@ struct glyph_row
 
 #ifdef GLYPH_DEBUG
 struct glyph_row *matrix_row (struct glyph_matrix *, int);
-#define MATRIX_ROW(MATRIX, ROW)   matrix_row ((MATRIX), (ROW))
+#define MATRIX_ROW(MATRIX, ROW)   matrix_row (MATRIX, ROW)
 #else
 #define MATRIX_ROW(MATRIX, ROW)          ((MATRIX)->rows + (ROW))
 #endif
@@ -1166,12 +1166,12 @@ struct glyph_row *matrix_row (struct glyph_matrix *, 
int);
    MATRIX.  */
 
 #define MATRIX_ROW_GLYPH_START(MATRIX, ROW) \
-     (MATRIX_ROW ((MATRIX), (ROW))->glyphs[TEXT_AREA])
+     (MATRIX_ROW (MATRIX, ROW)->glyphs[TEXT_AREA])
 
 /* Return the number of used glyphs in the text area of a row.  */
 
 #define MATRIX_ROW_USED(MATRIX, ROW) \
-     (MATRIX_ROW ((MATRIX), (ROW))->used[TEXT_AREA])
+     (MATRIX_ROW (MATRIX, ROW)->used[TEXT_AREA])
 
 /* Return the character/ byte position at which the display of ROW
    starts.  BIDI Note: this is the smallest character/byte position
@@ -1201,7 +1201,7 @@ struct glyph_row *matrix_row (struct glyph_matrix *, int);
 #define MATRIX_BOTTOM_TEXT_ROW(MATRIX, W)              \
      ((MATRIX)->rows                                   \
       + (MATRIX)->nrows                                        \
-      - (window_wants_mode_line ((W)) ? 1 : 0))
+      - (window_wants_mode_line (W) ? 1 : 0))
 
 /* Non-zero if the face of the last glyph in ROW's text area has
    to be drawn to the end of the text area.  */
@@ -1211,7 +1211,7 @@ struct glyph_row *matrix_row (struct glyph_matrix *, int);
 /* Set and query the enabled_p flag of glyph row ROW in MATRIX.  */
 
 #define SET_MATRIX_ROW_ENABLED_P(MATRIX, ROW, VALUE) \
-     (MATRIX_ROW (MATRIX, ROW)->enabled_p = (VALUE))
+     (MATRIX_ROW (MATRIX, ROW)->enabled_p = VALUE)
 
 #define MATRIX_ROW_ENABLED_P(MATRIX, ROW) \
      (MATRIX_ROW (MATRIX, ROW)->enabled_p)
@@ -1232,28 +1232,28 @@ struct glyph_row *matrix_row (struct glyph_matrix *, 
int);
 
 #define MR_PARTIALLY_VISIBLE_AT_BOTTOM(W, ROW)  \
   (((ROW)->y + (ROW)->height - (ROW)->extra_line_spacing) \
-   > WINDOW_BOX_HEIGHT_NO_MODE_LINE ((W)))
+   > WINDOW_BOX_HEIGHT_NO_MODE_LINE (W))
 
 /* Non-zero if ROW is not completely visible in window W.  */
 
 #define MATRIX_ROW_PARTIALLY_VISIBLE_P(W, ROW)         \
-  (MR_PARTIALLY_VISIBLE ((ROW))                                \
-   && (MR_PARTIALLY_VISIBLE_AT_TOP ((W), (ROW))                \
-       || MR_PARTIALLY_VISIBLE_AT_BOTTOM ((W), (ROW))))
+  (MR_PARTIALLY_VISIBLE (ROW)                          \
+   && (MR_PARTIALLY_VISIBLE_AT_TOP (W, ROW)            \
+       || MR_PARTIALLY_VISIBLE_AT_BOTTOM (W, ROW)))
 
 
 
 /* Non-zero if ROW is partially visible at the top of window W.  */
 
 #define MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P(W, ROW)          \
-  (MR_PARTIALLY_VISIBLE ((ROW))                                        \
-   && MR_PARTIALLY_VISIBLE_AT_TOP ((W), (ROW)))
+  (MR_PARTIALLY_VISIBLE (ROW)                                  \
+   && MR_PARTIALLY_VISIBLE_AT_TOP (W, ROW))
 
 /* Non-zero if ROW is partially visible at the bottom of window W.  */
 
 #define MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P(W, ROW)       \
-  (MR_PARTIALLY_VISIBLE ((ROW))                                        \
-   && MR_PARTIALLY_VISIBLE_AT_BOTTOM ((W), (ROW)))
+  (MR_PARTIALLY_VISIBLE (ROW)                                  \
+   && MR_PARTIALLY_VISIBLE_AT_BOTTOM (W, ROW))
 
 /* Return the bottom Y + 1 of ROW.   */
 
@@ -1263,7 +1263,7 @@ struct glyph_row *matrix_row (struct glyph_matrix *, int);
    iterator structure pointed to by IT?.  */
 
 #define MATRIX_ROW_LAST_VISIBLE_P(ROW, IT) \
-     (MATRIX_ROW_BOTTOM_Y ((ROW)) >= (IT)->last_visible_y)
+     (MATRIX_ROW_BOTTOM_Y (ROW) >= (IT)->last_visible_y)
 
 /* Non-zero if ROW displays a continuation line.  */
 
@@ -1537,9 +1537,9 @@ struct glyph_string
 /* Return the desired face id for the mode line of window W.  */
 
 #define CURRENT_MODE_LINE_ACTIVE_FACE_ID(W)            \
-       (CURRENT_MODE_LINE_ACTIVE_FACE_ID_3((W),        \
+        CURRENT_MODE_LINE_ACTIVE_FACE_ID_3(W, \
                                            XWINDOW (selected_window), \
-                                           (W)))
+                                           W)
 
 /* Return the current height of the mode line of window W.  If not known
    from W->mode_line_height, look at W's current glyph matrix, or return
@@ -1625,8 +1625,8 @@ struct glyph_string
 
 #define VCENTER_BASELINE_OFFSET(FONT, F)                       \
   (FONT_DESCENT (FONT)                                         \
-   + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))           \
-      + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2  \
+   + (FRAME_LINE_HEIGHT (F) - FONT_HEIGHT (FONT)               \
+      + (FRAME_LINE_HEIGHT (F) > FONT_HEIGHT (FONT))) / 2      \
    - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
 
 /* A heuristic test for fonts that claim they need a preposterously
@@ -2752,6 +2752,16 @@ struct it
      pixel_width with each call to produce_glyphs.  */
   int current_x;
 
+  /* Pixel position within a display line with a wrap prefix.  Updated
+     to reflect current_x in produce_glyphs when producing glyphs from
+     a prefix string and continuation_lines_width > 0, which is to
+     say, from a wrap prefix.
+
+     Such updates are unnecessary where it is impossible for a wrap
+     prefix to be active, e.g. when continuation lines are being
+     produced.  */
+  int wrap_prefix_width;
+
   /* Accumulated width of continuation lines.  If > 0, this means we
      are currently in a continuation line.  This is initially zero and
      incremented/reset by display_line, move_it_to etc.  */
@@ -2858,12 +2868,12 @@ struct it
     if ((IT)->glyph_row != NULL && (IT)->bidi_p)       \
       (IT)->glyph_row->reversed_p = (IT)->bidi_it.paragraph_dir == R2L; \
     if (FRAME_RIF ((IT)->f) != NULL)                    \
-      FRAME_RIF ((IT)->f)->produce_glyphs ((IT));       \
+      FRAME_RIF ((IT)->f)->produce_glyphs (IT);                \
     else                                                \
-      produce_glyphs ((IT));                            \
+      produce_glyphs (IT);                             \
     if ((IT)->glyph_row != NULL)                        \
       inhibit_free_realized_faces =true;               \
-    reset_box_start_end_flags ((IT));                  \
+    reset_box_start_end_flags (IT);                    \
   } while (false)
 
 /* Bit-flags indicating what operation move_it_to should perform.  */
@@ -3618,6 +3628,7 @@ void image_prune_animation_caches (bool);
 bool valid_image_p (Lisp_Object);
 void prepare_image_for_display (struct frame *, struct image *);
 ptrdiff_t lookup_image (struct frame *, Lisp_Object, int);
+Lisp_Object image_spec_value (Lisp_Object, Lisp_Object, bool *);
 
 #if defined HAVE_X_WINDOWS || defined USE_CAIRO || defined HAVE_NS \
   || defined HAVE_HAIKU || defined HAVE_ANDROID
diff --git a/src/dispnew.c b/src/dispnew.c
index e4037494775..c204a9dbf1b 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -1,6 +1,6 @@
 /* Updating of data structures for redisplay.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2023 Free Software Foundation,
+Copyright (C) 1985-1988, 1993-1995, 1997-2024 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
@@ -134,8 +134,8 @@ static struct frame *frame_matrix_frame;
 
 static int window_to_frame_vpos (struct window *, int);
 static int window_to_frame_hpos (struct window *, int);
-#define WINDOW_TO_FRAME_VPOS(W, VPOS) window_to_frame_vpos ((W), (VPOS))
-#define WINDOW_TO_FRAME_HPOS(W, HPOS) window_to_frame_hpos ((W), (HPOS))
+#define WINDOW_TO_FRAME_VPOS(W, VPOS) window_to_frame_vpos (W, VPOS)
+#define WINDOW_TO_FRAME_HPOS(W, HPOS) window_to_frame_hpos (W, HPOS)
 
 /* One element of the ring buffer containing redisplay history
    information.  */
@@ -5240,7 +5240,7 @@ count_match (struct glyph *str1, struct glyph *end1, 
struct glyph *str2, struct
 /* Char insertion/deletion cost vector, from term.c */
 
 #ifndef HAVE_ANDROID
-#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_TOTAL_COLS ((f))])
+#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_TOTAL_COLS (f)])
 #endif
 
 
diff --git a/src/disptab.h b/src/disptab.h
index 0069176fd24..2080181610a 100644
--- a/src/disptab.h
+++ b/src/disptab.h
@@ -1,5 +1,5 @@
 /* Things for GLYPHS and glyph tables.
-   Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -39,13 +39,13 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 extern Lisp_Object disp_char_vector (struct Lisp_Char_Table *, int);
 
 #define DISP_CHAR_VECTOR(dp, c)                                \
-  (ASCII_CHAR_P(c)                                     \
+  (ASCII_CHAR_P (c)                                    \
    ? (NILP ((dp)->ascii)                               \
       ? (dp)->defalt                                   \
       : (SUB_CHAR_TABLE_P ((dp)->ascii)                        \
         ? XSUB_CHAR_TABLE ((dp)->ascii)->contents[c]   \
         : (dp)->ascii))                                \
-   : disp_char_vector ((dp), (c)))
+   : disp_char_vector (dp, c))
 
 /* Defined in window.c.  */
 extern struct Lisp_Char_Table *window_display_table (struct window *);
@@ -78,8 +78,8 @@ extern struct Lisp_Char_Table *buffer_display_table (void);
    LENGTH), and set G to the final glyph.  */
 #define GLYPH_FOLLOW_ALIASES(base, length, g)                  \
   do {                                                         \
-    while (GLYPH_ALIAS_P ((base), (length), (g)))              \
-      SET_GLYPH_CHAR ((g), XFIXNUM ((base)[GLYPH_CHAR (g)]));  \
+    while (GLYPH_ALIAS_P (base, length, g))                    \
+      SET_GLYPH_CHAR (g, XFIXNUM ((base)[GLYPH_CHAR (g)]));    \
     if (!GLYPH_CHAR_VALID_P (g))                               \
       SET_GLYPH_CHAR (g, ' ');                                 \
   } while (false)
diff --git a/src/dmpstruct.awk b/src/dmpstruct.awk
index 344a22f977a..706e137a5b0 100644
--- a/src/dmpstruct.awk
+++ b/src/dmpstruct.awk
@@ -1,4 +1,4 @@
-# Copyright (C) 2018-2023 Free Software Foundation, Inc.
+# Copyright (C) 2018-2024 Free Software Foundation, Inc.
 #
 # This file is part of GNU Emacs.
 #
diff --git a/src/doc.c b/src/doc.c
index a731e856f0d..45028ebe8c0 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -1,6 +1,6 @@
 /* Record indices of function doc strings stored in a file. -*- coding: utf-8 
-*-
 
-Copyright (C) 1985-1986, 1993-1995, 1997-2023 Free Software Foundation,
+Copyright (C) 1985-1986, 1993-1995, 1997-2024 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
@@ -357,6 +357,20 @@ reread_doc_file (Lisp_Object file)
   return 1;
 }
 
+DEFUN ("documentation-stringp", Fdocumentation_stringp, Sdocumentation_stringp,
+       1, 1, 0,
+       doc: /* Return non-nil if OBJECT is a well-formed docstring object.
+OBJECT can be either a string or a reference if it's kept externally.  */)
+  (Lisp_Object object)
+{
+  return (STRINGP (object)
+          || FIXNUMP (object)   /* Reference to DOC.  */
+          || (CONSP (object)    /* Reference to .elc.  */
+              && STRINGP (XCAR (object))
+              && FIXNUMP (XCDR (object)))
+          ? Qt : Qnil);
+}
+
 DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0,
        doc: /* Return the documentation string of FUNCTION.
 Unless a non-nil second argument RAW is given, the
@@ -508,46 +522,13 @@ store_function_docstring (Lisp_Object obj, EMACS_INT 
offset)
   /* If it's a lisp form, stick it in the form.  */
   if (CONSP (fun) && EQ (XCAR (fun), Qmacro))
     fun = XCDR (fun);
-  if (CONSP (fun))
-    {
-      Lisp_Object tem = XCAR (fun);
-      if (EQ (tem, Qlambda) || EQ (tem, Qautoload)
-         || (EQ (tem, Qclosure) && (fun = XCDR (fun), 1)))
-       {
-         tem = Fcdr (Fcdr (fun));
-         if (CONSP (tem) && FIXNUMP (XCAR (tem)))
-           /* FIXME: This modifies typically pure hash-cons'd data, so its
-              correctness is quite delicate.  */
-           XSETCAR (tem, make_fixnum (offset));
-       }
-    }
   /* Lisp_Subrs have a slot for it.  */
-  else if (SUBRP (fun) && !SUBR_NATIVE_COMPILEDP (fun))
-    {
-      XSUBR (fun)->doc = offset;
-    }
-
-  /* Bytecode objects sometimes have slots for it.  */
-  else if (COMPILEDP (fun))
+  if (SUBRP (fun) && !SUBR_NATIVE_COMPILEDP (fun))
+    XSUBR (fun)->doc = offset;
+  else
     {
-      /* This bytecode object must have a slot for the
-        docstring, since we've found a docstring for it.  */
-      if (PVSIZE (fun) > COMPILED_DOC_STRING
-         /* Don't overwrite a non-docstring value placed there,
-           * such as the symbols used for Oclosures.  */
-         && VALID_DOCSTRING_P (AREF (fun, COMPILED_DOC_STRING)))
-       ASET (fun, COMPILED_DOC_STRING, make_fixnum (offset));
-      else
-       {
-         AUTO_STRING (format,
-                      (PVSIZE (fun) > COMPILED_DOC_STRING
-                       ? "Docstring slot busy for %s"
-                       : "No docstring slot for %s"));
-         CALLN (Fmessage, format,
-                (SYMBOLP (obj)
-                 ? SYMBOL_NAME (obj)
-                 : build_string ("<anonymous>")));
-       }
+      AUTO_STRING (format, "Ignoring DOC string on non-subr: %S");
+      CALLN (Fmessage, format, obj);
     }
 }
 
@@ -783,6 +764,7 @@ compute the correct value for the current terminal in the 
nil case.  */);
               doc: /* If nil, a nil `text-quoting-style' is treated as 
`grave'.  */);
   /* Initialized by ‘main’.  */
 
+  defsubr (&Sdocumentation_stringp);
   defsubr (&Sdocumentation);
   defsubr (&Ssubr_documentation);
   defsubr (&Sdocumentation_property);
diff --git a/src/doprnt.c b/src/doprnt.c
index e8911fad252..d764f25c6f7 100644
--- a/src/doprnt.c
+++ b/src/doprnt.c
@@ -1,7 +1,7 @@
 /* Output like sprintf to a buffer of specified size.    -*- coding: utf-8 -*-
    Also takes args differently: pass one pointer to the end
    of the format string in addition to the format string itself.
-   Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/dosfns.c b/src/dosfns.c
index ad885311c80..96087116c19 100644
--- a/src/dosfns.c
+++ b/src/dosfns.c
@@ -1,6 +1,6 @@
 /* MS-DOS specific Lisp utilities.  Coded by Manabu Higashida, 1991.
    Major changes May-July 1993 Morten Welinder (only 10% original code left)
-   Copyright (C) 1991, 1993, 1996-1998, 2001-2023 Free Software
+   Copyright (C) 1991, 1993, 1996-1998, 2001-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -652,10 +652,7 @@ dos_memory_info (unsigned long *totalram, unsigned long 
*freeram,
     mem2 *= 4096;
   /* Surely, the available memory is at least what we have physically
      available, right?  */
-  if (mem1 >= mem2)
-    freemem = mem1;
-  else
-    freemem = mem2;
+  freemem = max (mem1, mem2);
   *freeram = freemem;
   *totalswap =
     ((long)info.max_pages_in_paging_file == -1L)
diff --git a/src/dosfns.h b/src/dosfns.h
index fbfd734023a..47254d4670b 100644
--- a/src/dosfns.h
+++ b/src/dosfns.h
@@ -2,7 +2,7 @@
    Coded by Manabu Higashida, 1991.
    Modified by Morten Welinder, 1993-1994.
 
-Copyright (C) 1991, 1994-1995, 1997, 1999, 2001-2023 Free Software
+Copyright (C) 1991, 1994-1995, 1997, 1999, 2001-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/dynlib.c b/src/dynlib.c
index abbb0c45917..62e6e176c14 100644
--- a/src/dynlib.c
+++ b/src/dynlib.c
@@ -1,6 +1,6 @@
 /* Portable API for dynamic loading.
 
-Copyright 2015-2023 Free Software Foundation, Inc.
+Copyright 2015-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/dynlib.h b/src/dynlib.h
index 9527b758af9..e12958c73cc 100644
--- a/src/dynlib.h
+++ b/src/dynlib.h
@@ -1,6 +1,6 @@
 /* Portable API for dynamic loading.
 
-Copyright 2015-2023 Free Software Foundation, Inc.
+Copyright 2015-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/editfns.c b/src/editfns.c
index 686dd73e529..a764d2e7190 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -1,6 +1,6 @@
 /* Lisp functions pertaining to editing.                 -*- coding: utf-8 -*-
 
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -1785,7 +1785,7 @@ determines whether case is significant or ignored.  */)
   register EMACS_INT begp1, endp1, begp2, endp2, temp;
   register struct buffer *bp1, *bp2;
   register Lisp_Object trt
-    = (!NILP (BVAR (current_buffer, case_fold_search))
+    = (!NILP (Vcase_fold_search)
        ? BVAR (current_buffer, case_canon_table) : Qnil);
   ptrdiff_t chars = 0;
   ptrdiff_t i1, i2, i1_byte, i2_byte;
@@ -1908,7 +1908,7 @@ determines whether case is significant or ignored.  */)
 #define USE_HEURISTIC
 
 #define XVECREF_YVECREF_EQUAL(ctx, xoff, yoff)  \
-  buffer_chars_equal ((ctx), (xoff), (yoff))
+  buffer_chars_equal (ctx, xoff, yoff)
 
 #define OFFSET ptrdiff_t
 
@@ -2877,9 +2877,9 @@ void
 labeled_narrow_to_region (Lisp_Object begv, Lisp_Object zv,
                          Lisp_Object label)
 {
-  Finternal__labeled_narrow_to_region (begv, zv, label);
   record_unwind_protect (restore_point_unwind, Fpoint_marker ());
   record_unwind_protect (unwind_labeled_narrow_to_region, label);
+  Finternal__labeled_narrow_to_region (begv, zv, label);
 }
 
 DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
@@ -4368,7 +4368,7 @@ Case is ignored if `case-fold-search' is non-nil in the 
current buffer.  */)
 
   if (XFIXNUM (c1) == XFIXNUM (c2))
     return Qt;
-  if (NILP (BVAR (current_buffer, case_fold_search)))
+  if (NILP (Vcase_fold_search))
     return Qnil;
 
   i1 = XFIXNAT (c1);
diff --git a/src/emacs-icon.h b/src/emacs-icon.h
index 84ae557be2b..22915b14f33 100644
--- a/src/emacs-icon.h
+++ b/src/emacs-icon.h
@@ -1,7 +1,7 @@
 /* XPM */
 /* Emacs icon
 
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 Author: Kentaro Ohkouchi <nanasess@fsm.ne.jp>
         Nicolas Petton <nicolas@petton.fr>
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 86360a0f225..08db39b0b0d 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -1,6 +1,6 @@
 /* emacs-module.c - Module loading and runtime implementation
 
-Copyright (C) 2015-2023 Free Software Foundation, Inc.
+Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -410,12 +410,9 @@ module_global_reference_p (emacs_value v, ptrdiff_t *n)
   struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
   /* Note that we can't use `hash_lookup' because V might be a local
      reference that's identical to some global reference.  */
-  for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
-    {
-      if (!BASE_EQ (HASH_KEY (h, i), Qunbound)
-          && &XMODULE_GLOBAL_REFERENCE (HASH_VALUE (h, i))->value == v)
-        return true;
-    }
+  DOHASH (h, k, val)
+    if (&XMODULE_GLOBAL_REFERENCE (val)->value == v)
+      return true;
   /* Only used for debugging, so we don't care about overflow, just
      make sure the operation is defined.  */
   ckd_add (n, *n, h->count);
@@ -427,8 +424,9 @@ module_make_global_ref (emacs_env *env, emacs_value value)
 {
   MODULE_FUNCTION_BEGIN (NULL);
   struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
-  Lisp_Object new_obj = value_to_lisp (value), hashcode;
-  ptrdiff_t i = hash_lookup (h, new_obj, &hashcode);
+  Lisp_Object new_obj = value_to_lisp (value);
+  hash_hash_t hashcode;
+  ptrdiff_t i = hash_lookup_get_hash (h, new_obj, &hashcode);
 
   /* Note: This approach requires the garbage collector to never move
      objects.  */
@@ -467,7 +465,7 @@ module_free_global_ref (emacs_env *env, emacs_value 
global_value)
   MODULE_FUNCTION_BEGIN ();
   struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
   Lisp_Object obj = value_to_lisp (global_value);
-  ptrdiff_t i = hash_lookup (h, obj, NULL);
+  ptrdiff_t i = hash_lookup (h, obj);
 
   if (module_assertions)
     {
@@ -1697,9 +1695,7 @@ syms_of_module (void)
 {
   staticpro (&Vmodule_refs_hash);
   Vmodule_refs_hash
-    = make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE,
-                      DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
-                      Qnil, false);
+    = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None, false);
 
   DEFSYM (Qmodule_load_failed, "module-load-failed");
   Fput (Qmodule_load_failed, Qerror_conditions,
diff --git a/src/emacs-module.h.in b/src/emacs-module.h.in
index a455c41a5f1..690254bd28c 100644
--- a/src/emacs-module.h.in
+++ b/src/emacs-module.h.in
@@ -1,6 +1,6 @@
 /* emacs-module.h - GNU Emacs module API.
 
-Copyright (C) 2015-2023 Free Software Foundation, Inc.
+Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/emacs.c b/src/emacs.c
index 6101ed4004c..97c65fbfd33 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1,6 +1,6 @@
 /* Fully extensible Emacs, running on Unix, intended for GNU.
 
-Copyright (C) 1985-1987, 1993-1995, 1997-1999, 2001-2023 Free Software
+Copyright (C) 1985-1987, 1993-1995, 1997-1999, 2001-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -401,11 +401,6 @@ section of the Emacs manual or the file BUGS.\n"
 /* True if handling a fatal error already.  */
 bool fatal_error_in_progress;
 
-#ifdef HAVE_NS
-/* NS autorelease pool, for memory management.  */
-static void *ns_pool;
-#endif
-
 #if !HAVE_SETLOCALE
 static char *
 setlocale (int cat, char const *locale)
@@ -1424,6 +1419,11 @@ main (int argc, char **argv)
   w32_init_main_thread ();
 #endif
 
+#ifdef HAVE_NS
+  /* Initialize the Obj C autorelease pool.  */
+  ns_init_pool ();
+#endif
+
 #ifdef HAVE_PDUMPER
   if (attempt_load_pdump)
     initial_emacs_executable = load_pdump (argc, argv, dump_file);
@@ -1643,7 +1643,6 @@ main (int argc, char **argv)
   if (! (lc_all && strcmp (lc_all, "C") == 0))
     {
       #ifdef HAVE_NS
-        ns_pool = ns_alloc_autorelease_pool ();
         ns_init_locale ();
       #endif
       setlocale (LC_ALL, "");
@@ -2901,7 +2900,7 @@ sort_args (int argc, char **argv)
            new[to++] = argv[best + i + 1];
        }
 
-      incoming_used += 1 + (options[best] > 0 ? options[best] : 0);
+      incoming_used += 1 + max (options[best], 0);
 
       /* Clear out this option in ARGV.  */
       argv[best] = 0;
@@ -2993,10 +2992,6 @@ killed.  */
 
   shut_down_emacs (0, (STRINGP (arg) && !feof (stdin)) ? arg : Qnil);
 
-#ifdef HAVE_NS
-  ns_release_autorelease_pool (ns_pool);
-#endif
-
   /* If we have an auto-save list file,
      kill it because we are exiting Emacs deliberately (not crashing).
      Do it after shut_down_emacs, which does an auto-save.  */
@@ -3331,9 +3326,6 @@ decode_env_path (const char *evarname, const char 
*defalt, bool empty)
 {
   const char *path, *p;
   Lisp_Object lpath, element, tem;
-#ifdef NS_SELF_CONTAINED
-  void *autorelease = NULL;
-#endif
   /* Default is to use "." for empty path elements.
      But if argument EMPTY is true, use nil instead.  */
   Lisp_Object empty_element = empty ? Qnil : build_string (".");
@@ -3361,8 +3353,6 @@ decode_env_path (const char *evarname, const char 
*defalt, bool empty)
   if (!path)
     {
 #ifdef NS_SELF_CONTAINED
-      /* ns_relocate needs a valid autorelease pool around it.  */
-      autorelease = ns_alloc_autorelease_pool ();
       path = ns_relocate (defalt);
 #else
       path = defalt;
@@ -3466,10 +3456,6 @@ decode_env_path (const char *evarname, const char 
*defalt, bool empty)
        break;
     }
 
-#ifdef NS_SELF_CONTAINED
-  if (autorelease)
-    ns_release_autorelease_pool (autorelease);
-#endif
   return Fnreverse (lpath);
 }
 
diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c
index 2b6ebee65fd..3941960b3ba 100644
--- a/src/emacsgtkfixed.c
+++ b/src/emacsgtkfixed.c
@@ -1,7 +1,7 @@
 /* A Gtk Widget that inherits GtkFixed, but can be shrunk.
 This file is only use when compiling with Gtk+ 3.
 
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/emacsgtkfixed.h b/src/emacsgtkfixed.h
index 952dfed5e1e..2db78fd00b5 100644
--- a/src/emacsgtkfixed.h
+++ b/src/emacsgtkfixed.h
@@ -1,7 +1,7 @@
 /* A Gtk Widget that inherits GtkFixed, but can be shrunk.
 This file is only use when compiling with Gtk+ 3.
 
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -28,8 +28,8 @@ struct frame;
 G_BEGIN_DECLS
 
 #ifdef HAVE_PGTK
-#define EMACS_TYPE_FIXED        (emacs_fixed_get_type ())
-#define EMACS_IS_FIXED(obj)     (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
EMACS_TYPE_FIXED))
+#define EMACS_TYPE_FIXED emacs_fixed_get_type ()
+#define EMACS_IS_FIXED(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, EMACS_TYPE_FIXED)
 #endif
 
 struct frame;
diff --git a/src/epaths.in b/src/epaths.in
index afddd57763a..275d13985aa 100644
--- a/src/epaths.in
+++ b/src/epaths.in
@@ -1,6 +1,6 @@
 /* Hey Emacs, this is -*- C -*- code!  */
 /*
-Copyright (C) 1993, 1995, 1997, 1999, 2001-2023 Free Software
+Copyright (C) 1993, 1995, 1997, 1999, 2001-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/eval.c b/src/eval.c
index 8ecfeb426bf..23beff2ee30 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1,6 +1,6 @@
 /* Evaluator for GNU Emacs Lisp interpreter.
 
-Copyright (C) 1985-1987, 1993-1995, 1999-2023 Free Software Foundation,
+Copyright (C) 1985-1987, 1993-1995, 1999-2024 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
@@ -57,12 +57,6 @@ Lisp_Object Vrun_hooks;
 /* FIXME: We should probably get rid of this!  */
 Lisp_Object Vsignaling_function;
 
-/* The handler structure which will catch errors in Lisp hooks called
-   from redisplay.  We do not use it for this; we compare it with the
-   handler which is about to be used in signal_or_quit, and if it
-   matches, cause a backtrace to be generated.  */
-static struct handler *redisplay_deep_handler;
-
 /* These would ordinarily be static, but they need to be visible to GDB.  */
 bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE;
 Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE;
@@ -212,7 +206,6 @@ void
 init_eval_once (void)
 {
   /* Don't forget to update docs (lispref node "Eval").  */
-  max_lisp_eval_depth = 1600;
   Vrun_hooks = Qnil;
   pdumper_do_now_and_after_load (init_eval_once_for_pdumper);
 }
@@ -245,25 +238,31 @@ init_eval (void)
   lisp_eval_depth = 0;
   /* This is less than the initial value of num_nonmacro_input_events.  */
   when_entered_debugger = -1;
-  redisplay_deep_handler = NULL;
 }
 
-/* Ensure that *M is at least A + B if possible, or is its maximum
-   value otherwise.  */
-
 static void
-max_ensure_room (intmax_t *m, intmax_t a, intmax_t b)
+restore_stack_limits (Lisp_Object data)
 {
-  intmax_t sum = ckd_add (&sum, a, b) ? INTMAX_MAX : sum;
-  *m = max (*m, sum);
+  intmax_t old_depth;
+  integer_to_intmax (data, &old_depth);
+  lisp_eval_depth_reserve += max_lisp_eval_depth - old_depth;
+  max_lisp_eval_depth = old_depth;
 }
 
-/* Unwind-protect function used by call_debugger.  */
+/* Try and ensure that we have at least B dpeth available.  */
 
 static void
-restore_stack_limits (Lisp_Object data)
+max_ensure_room (intmax_t b)
 {
-  integer_to_intmax (data, &max_lisp_eval_depth);
+  intmax_t sum = ckd_add (&sum, lisp_eval_depth, b) ? INTMAX_MAX : sum;
+  intmax_t diff = min (sum - max_lisp_eval_depth, lisp_eval_depth_reserve);
+  if (diff <= 0)
+    return;
+  intmax_t old_depth = max_lisp_eval_depth;
+  max_lisp_eval_depth += diff;
+  lisp_eval_depth_reserve -= diff;
+  /* Restore limits after leaving the debugger.  */
+  record_unwind_protect (restore_stack_limits, make_int (old_depth));
 }
 
 /* Call the Lisp debugger, giving it argument ARG.  */
@@ -274,16 +273,12 @@ call_debugger (Lisp_Object arg)
   bool debug_while_redisplaying;
   specpdl_ref count = SPECPDL_INDEX ();
   Lisp_Object val;
-  intmax_t old_depth = max_lisp_eval_depth;
 
   /* The previous value of 40 is too small now that the debugger
      prints using cl-prin1 instead of prin1.  Printing lists nested 8
      deep (which is the value of print-level used in the debugger)
      currently requires 77 additional frames.  See bug#31919.  */
-  max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
-
-  /* Restore limits after leaving the debugger.  */
-  record_unwind_protect (restore_stack_limits, make_int (old_depth));
+  max_ensure_room (100);
 
 #ifdef HAVE_WINDOW_SYSTEM
   if (display_hourglass_p)
@@ -317,6 +312,7 @@ call_debugger (Lisp_Object arg)
   /* Interrupting redisplay and resuming it later is not safe under
      all circumstances.  So, when the debugger returns, abort the
      interrupted redisplay by going back to the top-level.  */
+  /* FIXME: Move this to the redisplay code?  */
   if (debug_while_redisplaying
       && !EQ (Vdebugger, Qdebug_early))
     Ftop_level ();
@@ -797,8 +793,7 @@ DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0,
 You are not required to define a variable in order to use it, but
 defining it lets you supply an initial value and documentation, which
 can be referred to by the Emacs help facilities and other programming
-tools.  The `defvar' form also declares the variable as \"special\",
-so that it is always dynamically bound even if `lexical-binding' is t.
+tools.
 
 If SYMBOL's value is void and the optional argument INITVALUE is
 provided, INITVALUE is evaluated and the result used to set SYMBOL's
@@ -806,6 +801,13 @@ value.  If SYMBOL is buffer-local, its default value is 
what is set;
 buffer-local values are not affected.  If INITVALUE is missing,
 SYMBOL's value is not set.
 
+If INITVALUE is provided, the `defvar' form also declares the variable
+as \"special\", so that it is always dynamically bound even if
+`lexical-binding' is t.  If INITVALUE is missing, the form marks the
+variable \"special\" locally (i.e., within the current
+lexical scope, or the current file, if the form is at top-level),
+and does nothing if `lexical-binding' is nil.
+
 If SYMBOL is let-bound, then this form does not affect the local let
 binding but the toplevel default binding instead, like
 `set-toplevel-default-binding`.
@@ -1252,6 +1254,12 @@ usage: (catch TAG BODY...)  */)
 
 #define clobbered_eassert(E) verify (sizeof (E) != 0)
 
+void
+pop_handler (void)
+{
+  handlerlist = handlerlist->next;
+}
+
 /* Set up a catch, then call C function FUNC on argument ARG.
    FUNC should return a Lisp_Object.
    This is how catches are done from within C code.  */
@@ -1415,6 +1423,49 @@ usage: (condition-case VAR BODYFORM &rest HANDLERS)  */)
   return internal_lisp_condition_case (var, bodyform, handlers);
 }
 
+void
+push_handler_bind (Lisp_Object conditions, Lisp_Object handler, int skip)
+{
+  if (!CONSP (conditions))
+    conditions = Fcons (conditions, Qnil);
+  struct handler *c = push_handler (conditions, HANDLER_BIND);
+  c->val = handler;
+  c->bytecode_dest = skip;
+}
+
+DEFUN ("handler-bind-1", Fhandler_bind_1, Shandler_bind_1, 1, MANY, 0,
+       doc: /* Setup error handlers around execution of BODYFUN.
+BODYFUN be a function and it is called with no arguments.
+CONDITIONS should be a list of condition names (symbols).
+When an error is signaled during execution of BODYFUN, if that
+error matches one of CONDITIONS, then the associated HANDLER is
+called with the error as argument.
+HANDLER should either transfer the control via a non-local exit,
+or return normally.
+If it returns normally, the search for an error handler continues
+from where it left off.
+
+usage: (handler-bind BODYFUN [CONDITIONS HANDLER]...)  */)
+  (ptrdiff_t nargs, Lisp_Object *args)
+{
+  eassert (nargs >= 1);
+  Lisp_Object bodyfun = args[0];
+  int count = 0;
+  if (nargs % 2 == 0)
+    error ("Trailing CONDITIONS without HANDLER in `handler-bind`");
+  for (ptrdiff_t i = nargs - 2; i > 0; i -= 2)
+    {
+      Lisp_Object conditions = args[i], handler = args[i + 1];
+      if (NILP (conditions))
+        continue;
+      push_handler_bind (conditions, handler, count++);
+    }
+  Lisp_Object ret = call0 (bodyfun);
+  for (; count > 0; count--)
+    pop_handler ();
+  return ret;
+}
+
 /* Like Fcondition_case, but the args are separate
    rather than passed in a list.  Used by Fbyte_code.  */
 
@@ -1613,16 +1664,12 @@ internal_condition_case_n (Lisp_Object (*bfun) 
(ptrdiff_t, Lisp_Object *),
                                                ptrdiff_t nargs,
                                                Lisp_Object *args))
 {
-  struct handler *old_deep = redisplay_deep_handler;
   struct handler *c = push_handler (handlers, CONDITION_CASE);
-  if (redisplaying_p)
-    redisplay_deep_handler = c;
   if (sys_setjmp (c->jmp))
     {
       Lisp_Object val = handlerlist->val;
       clobbered_eassert (handlerlist == c);
       handlerlist = handlerlist->next;
-      redisplay_deep_handler = old_deep;
       return hfun (val, nargs, args);
     }
   else
@@ -1630,7 +1677,6 @@ internal_condition_case_n (Lisp_Object (*bfun) 
(ptrdiff_t, Lisp_Object *),
       Lisp_Object val = bfun (nargs, args);
       eassert (handlerlist == c);
       handlerlist = c->next;
-      redisplay_deep_handler = old_deep;
       return val;
     }
 }
@@ -1708,8 +1754,7 @@ push_handler_nosignal (Lisp_Object tag_ch_val, enum 
handlertype handlertype)
 
 static Lisp_Object signal_or_quit (Lisp_Object, Lisp_Object, bool);
 static Lisp_Object find_handler_clause (Lisp_Object, Lisp_Object);
-static bool maybe_call_debugger (Lisp_Object conditions, Lisp_Object sig,
-                                Lisp_Object data);
+static bool maybe_call_debugger (Lisp_Object conditions, Lisp_Object error);
 
 static void
 process_quit_flag (void)
@@ -1769,28 +1814,29 @@ quit (void)
   return signal_or_quit (Qquit, Qnil, true);
 }
 
-/* Has an error in redisplay giving rise to a backtrace occurred as
-   yet in the current command?  This gets reset in the command
-   loop.  */
-bool backtrace_yet = false;
-
 /* Signal an error, or quit.  ERROR_SYMBOL and DATA are as with Fsignal.
-   If KEYBOARD_QUIT, this is a quit; ERROR_SYMBOL should be
-   Qquit and DATA should be Qnil, and this function may return.
+   If CONTINUABLE, the caller allows this function to return
+   (presumably after calling the debugger);
    Otherwise this function is like Fsignal and does not return.  */
 
 static Lisp_Object
-signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
+signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool continuable)
 {
   /* When memory is full, ERROR-SYMBOL is nil,
      and DATA is (REAL-ERROR-SYMBOL . REAL-DATA).
      That is a special case--don't do this in other situations.  */
+  bool oom = NILP (error_symbol);
+  Lisp_Object error             /* The error object.  */
+    = oom ? data
+      : (!SYMBOLP (error_symbol) && NILP (data)) ? error_symbol
+      : Fcons (error_symbol, data);
   Lisp_Object conditions;
   Lisp_Object string;
   Lisp_Object real_error_symbol
-    = (NILP (error_symbol) ? Fcar (data) : error_symbol);
+    = CONSP (error) ? XCAR (error) : error_symbol;
   Lisp_Object clause = Qnil;
   struct handler *h;
+  int skip;
 
   if (gc_in_progress || waiting_for_input)
     emacs_abort ();
@@ -1805,15 +1851,15 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object 
data, bool keyboard_quit)
 
   /* This hook is used by edebug.  */
   if (! NILP (Vsignal_hook_function)
-      && ! NILP (error_symbol)
-      /* Don't try to call a lisp function if we've already overflowed
-         the specpdl stack.  */
-      && specpdl_ptr < specpdl_end)
+      && !oom)
     {
-      /* Edebug takes care of restoring these variables when it exits.  */
-      max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 20);
-
+      specpdl_ref count = SPECPDL_INDEX ();
+      max_ensure_room (20);
+      /* FIXME: 'handler-bind' makes `signal-hook-function' obsolete?  */
+      /* FIXME: Here we still "split" the error object
+         into its error-symbol and its error-data?  */
       call2 (Vsignal_hook_function, error_symbol, data);
+      unbind_to (count, Qnil);
     }
 
   conditions = Fget (real_error_symbol, Qerror_conditions);
@@ -1823,7 +1869,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object 
data, bool keyboard_quit)
      too.  Don't do this when ERROR_SYMBOL is nil, because that
      is a memory-full error.  */
   Vsignaling_function = Qnil;
-  if (!NILP (error_symbol))
+  if (!oom)
     {
       union specbinding *pdl = backtrace_next (backtrace_top ());
       if (backtrace_p (pdl) && EQ (backtrace_function (pdl), Qerror))
@@ -1832,16 +1878,42 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object 
data, bool keyboard_quit)
        Vsignaling_function = backtrace_function (pdl);
     }
 
-  for (h = handlerlist; h; h = h->next)
+  for (skip = 0, h = handlerlist; h; skip++, h = h->next)
     {
-      if (h->type == CATCHER_ALL)
+      switch (h->type)
         {
+        case CATCHER_ALL:
           clause = Qt;
           break;
-        }
-      if (h->type != CONDITION_CASE)
-       continue;
-      clause = find_handler_clause (h->tag_or_ch, conditions);
+       case CATCHER:
+         continue;
+        case CONDITION_CASE:
+          clause = find_handler_clause (h->tag_or_ch, conditions);
+         break;
+       case HANDLER_BIND:
+         {
+           if (!NILP (find_handler_clause (h->tag_or_ch, conditions)))
+             {
+               specpdl_ref count = SPECPDL_INDEX ();
+               max_ensure_room (20);
+               push_handler (make_fixnum (skip + h->bytecode_dest),
+                             SKIP_CONDITIONS);
+               call1 (h->val, error);
+               unbind_to (count, Qnil);
+               pop_handler ();
+             }
+           continue;
+         }
+       case SKIP_CONDITIONS:
+         {
+           int toskip = XFIXNUM (h->tag_or_ch);
+           while (toskip-- >= 0)
+             h = h->next;
+           continue;
+         }
+       default:
+         abort ();
+       }
       if (!NILP (clause))
        break;
     }
@@ -1849,7 +1921,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object 
data, bool keyboard_quit)
   bool debugger_called = false;
   if (/* Don't run the debugger for a memory-full error.
         (There is no room in memory to do that!)  */
-      !NILP (error_symbol)
+      !oom
       && (!NILP (Vdebug_on_signal)
          /* If no handler is present now, try to run the debugger.  */
          || NILP (clause)
@@ -1858,85 +1930,25 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object 
data, bool keyboard_quit)
          || (CONSP (clause) && !NILP (Fmemq (Qdebug, clause)))
          /* Special handler that means "print a message and run debugger
             if requested".  */
-         || EQ (h->tag_or_ch, Qerror)))
+         || EQ (clause, Qerror)))
     {
       debugger_called
-       = maybe_call_debugger (conditions, error_symbol, data);
+       = maybe_call_debugger (conditions, error);
       /* We can't return values to code which signaled an error, but we
         can continue code which has signaled a quit.  */
-      if (keyboard_quit && debugger_called && EQ (real_error_symbol, Qquit))
+      if (continuable && debugger_called)
        return Qnil;
     }
 
-  /* If we're in batch mode, print a backtrace unconditionally to help
-     with debugging.  Make sure to use `debug-early' unconditionally
-     to not interfere with ERT or other packages that install custom
-     debuggers.  */
-  if (!debugger_called && !NILP (error_symbol)
-      && (NILP (clause) || EQ (h->tag_or_ch, Qerror))
-      && noninteractive && backtrace_on_error_noninteractive
-      && NILP (Vinhibit_debugger)
-      && !NILP (Ffboundp (Qdebug_early)))
-    {
-      max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
-      specpdl_ref count = SPECPDL_INDEX ();
-      specbind (Qdebugger, Qdebug_early);
-      call_debugger (list2 (Qerror, Fcons (error_symbol, data)));
-      unbind_to (count, Qnil);
-    }
-
-  /* If an error is signaled during a Lisp hook in redisplay, write a
-     backtrace into the buffer *Redisplay-trace*.  */
-  if (!debugger_called && !NILP (error_symbol)
-      && backtrace_on_redisplay_error
-      && (NILP (clause) || h == redisplay_deep_handler)
-      && NILP (Vinhibit_debugger)
-      && !NILP (Ffboundp (Qdebug_early)))
-    {
-      max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
-      specpdl_ref count = SPECPDL_INDEX ();
-      AUTO_STRING (redisplay_trace, "*Redisplay_trace*");
-      Lisp_Object redisplay_trace_buffer;
-      AUTO_STRING (gap, "\n\n\n\n"); /* Separates things in *Redisplay-trace* 
*/
-      Lisp_Object delayed_warning;
-      redisplay_trace_buffer = Fget_buffer_create (redisplay_trace, Qnil);
-      current_buffer = XBUFFER (redisplay_trace_buffer);
-      if (!backtrace_yet) /* Are we on the first backtrace of the command?  */
-       Ferase_buffer ();
-      else
-       Finsert (1, &gap);
-      backtrace_yet = true;
-      specbind (Qstandard_output, redisplay_trace_buffer);
-      specbind (Qdebugger, Qdebug_early);
-      call_debugger (list2 (Qerror, Fcons (error_symbol, data)));
-      unbind_to (count, Qnil);
-      delayed_warning = make_string
-       ("Error in a redisplay Lisp hook.  See buffer *Redisplay_trace*", 61);
-
-      Vdelayed_warnings_list = Fcons (list2 (Qerror, delayed_warning),
-                                     Vdelayed_warnings_list);
-    }
-
   if (!NILP (clause))
-    {
-      Lisp_Object unwind_data
-       = (NILP (error_symbol) ? data : Fcons (error_symbol, data));
-
-      unwind_to_catch (h, NONLOCAL_EXIT_SIGNAL, unwind_data);
-    }
-  else
-    {
-      if (handlerlist != handlerlist_sentinel)
-       /* FIXME: This will come right back here if there's no `top-level'
-          catcher.  A better solution would be to abort here, and instead
-          add a catch-all condition handler so we never come here.  */
-       Fthrow (Qtop_level, Qt);
-    }
-
-  if (! NILP (error_symbol))
-    data = Fcons (error_symbol, data);
-
-  string = Ferror_message_string (data);
+    unwind_to_catch (h, NONLOCAL_EXIT_SIGNAL, error);
+  else if (handlerlist != handlerlist_sentinel)
+    /* FIXME: This will come right back here if there's no `top-level'
+       catcher.  A better solution would be to abort here, and instead
+       add a catch-all condition handler so we never come here.  */
+    Fthrow (Qtop_level, Qt);
+
+  string = Ferror_message_string (error);
   fatal ("%s", SDATA (string));
 }
 
@@ -2061,14 +2073,15 @@ skip_debugger (Lisp_Object conditions, Lisp_Object data)
   return 0;
 }
 
-/* Say whether SIGNAL is a `quit' symbol (or inherits from it).  */
+/* Say whether SIGNAL is a `quit' error (or inherits from it).  */
 bool
-signal_quit_p (Lisp_Object signal)
+signal_quit_p (Lisp_Object error)
 {
+  Lisp_Object signal = CONSP (error) ? XCAR (error) : Qnil;
   Lisp_Object list;
 
   return EQ (signal, Qquit)
-    || (!NILP (Fsymbolp (signal))
+    || (SYMBOLP (signal)
        && CONSP (list = Fget (signal, Qerror_conditions))
        && !NILP (Fmemq (Qquit, list)));
 }
@@ -2079,27 +2092,23 @@ signal_quit_p (Lisp_Object signal)
     = SIG is nil, and DATA is (SYMBOL . REST-OF-DATA).
       This is for memory-full errors only.  */
 static bool
-maybe_call_debugger (Lisp_Object conditions, Lisp_Object sig, Lisp_Object data)
+maybe_call_debugger (Lisp_Object conditions, Lisp_Object error)
 {
-  Lisp_Object combined_data;
-
-  combined_data = Fcons (sig, data);
-
   if (
       /* Don't try to run the debugger with interrupts blocked.
         The editing loop would return anyway.  */
       ! input_blocked_p ()
       && NILP (Vinhibit_debugger)
       /* Does user want to enter debugger for this kind of error?  */
-      && (signal_quit_p (sig)
+      && (signal_quit_p (error)
          ? debug_on_quit
          : wants_debugger (Vdebug_on_error, conditions))
-      && ! skip_debugger (conditions, combined_data)
+      && ! skip_debugger (conditions, error)
       /* See commentary on definition of
          `internal-when-entered-debugger'.  */
       && when_entered_debugger < num_nonmacro_input_events)
     {
-      call_debugger (list2 (Qerror, combined_data));
+      call_debugger (list2 (Qerror, error));
       return 1;
     }
 
@@ -2112,13 +2121,10 @@ find_handler_clause (Lisp_Object handlers, Lisp_Object 
conditions)
   register Lisp_Object h;
 
   /* t is used by handlers for all conditions, set up by C code.  */
-  if (EQ (handlers, Qt))
-    return Qt;
-
   /* error is used similarly, but means print an error message
      and run the debugger if that is enabled.  */
-  if (EQ (handlers, Qerror))
-    return Qt;
+  if (!CONSP (handlers))
+    return handlers;
 
   for (h = handlers; CONSP (h); h = XCDR (h))
     {
@@ -3088,6 +3094,35 @@ usage: (funcall FUNCTION &rest ARGUMENTS)  */)
 }
 
 
+static Lisp_Object
+safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
+{
+  add_to_log ("Error muted by safe_call: %S signaled %S",
+             Flist (nargs, args), arg);
+  return Qnil;
+}
+
+Lisp_Object
+safe_funcall (ptrdiff_t nargs, Lisp_Object *args)
+{
+  specpdl_ref count = SPECPDL_INDEX ();
+  /* FIXME: This function started its life in 'xdisp.c' for use internally
+     by the redisplay.  So it was important to inhibit redisplay.
+     Not clear if we still need this 'specbind' now that 'xdisp.c' has its
+     own version of this code.  */
+  specbind (Qinhibit_redisplay, Qt);
+  /* Use Qt to ensure debugger does not run.  */
+  Lisp_Object val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
+                                              safe_eval_handler);
+  return unbind_to (count, val);
+}
+
+Lisp_Object
+safe_eval (Lisp_Object sexp)
+{
+  return safe_calln (Qeval, sexp, Qt);
+}
+
 /* Apply a C subroutine SUBR to the NUMARGS evaluated arguments in ARG_VECTOR
    and return the result of evaluation.  */
 
@@ -3098,21 +3133,21 @@ funcall_subr (struct Lisp_Subr *subr, ptrdiff_t 
numargs, Lisp_Object *args)
   if (numargs >= subr->min_args)
     {
       /* Conforming call to finite-arity subr.  */
-      if (numargs <= subr->max_args
-         && subr->max_args <= 8)
+      ptrdiff_t maxargs = subr->max_args;
+      if (numargs <= maxargs && maxargs <= 8)
        {
          Lisp_Object argbuf[8];
          Lisp_Object *a;
-         if (numargs < subr->max_args)
+         if (numargs < maxargs)
            {
-             eassume (subr->max_args <= ARRAYELTS (argbuf));
+             eassume (maxargs <= ARRAYELTS (argbuf));
              a = argbuf;
              memcpy (a, args, numargs * word_size);
-             memclear (a + numargs, (subr->max_args - numargs) * word_size);
+             memclear (a + numargs, (maxargs - numargs) * word_size);
            }
          else
            a = args;
-         switch (subr->max_args)
+         switch (maxargs)
            {
            case 0:
              return subr->function.a0 ();
@@ -3134,14 +3169,12 @@ funcall_subr (struct Lisp_Subr *subr, ptrdiff_t 
numargs, Lisp_Object *args)
            case 8:
              return subr->function.a8 (a[0], a[1], a[2], a[3], a[4], a[5],
                                        a[6], a[7]);
-           default:
-             emacs_abort ();   /* Can't happen. */
            }
+         eassume (false);      /* In case the compiler is too stupid.  */
        }
 
       /* Call to n-adic subr.  */
-      if (subr->max_args == MANY
-         || subr->max_args > 8)
+      if (maxargs == MANY || maxargs > 8)
        return subr->function.aMANY (numargs, args);
     }
 
@@ -3154,19 +3187,6 @@ funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, 
Lisp_Object *args)
     xsignal2 (Qwrong_number_of_arguments, fun, make_fixnum (numargs));
 }
 
-/* Call the compiled Lisp function FUN.  If we have not yet read FUN's
-   bytecode string and constants vector, fetch them from the file first.  */
-
-static Lisp_Object
-fetch_and_exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
-                         ptrdiff_t nargs, Lisp_Object *args)
-{
-  if (CONSP (AREF (fun, COMPILED_BYTECODE)))
-    Ffetch_bytecode (fun);
-
-  return exec_byte_code (fun, args_template, nargs, args);
-}
-
 static Lisp_Object
 apply_lambda (Lisp_Object fun, Lisp_Object args, specpdl_ref count)
 {
@@ -3236,8 +3256,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
         ARGLIST slot value: pass the arguments to the byte-code
         engine directly.  */
       if (FIXNUMP (syms_left))
-       return fetch_and_exec_byte_code (fun, XFIXNUM (syms_left),
-                                        nargs, arg_vector);
+       return exec_byte_code (fun, XFIXNUM (syms_left), nargs, arg_vector);
       /* Otherwise the bytecode object uses dynamic binding and the
         ARGLIST slot contains a standard formal argument list whose
         variables are bound dynamically below.  */
@@ -3325,7 +3344,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
       val = XSUBR (fun)->function.a0 ();
     }
   else
-    val = fetch_and_exec_byte_code (fun, 0, 0, NULL);
+    val = exec_byte_code (fun, 0, 0, NULL);
 
   return unbind_to (count, val);
 }
@@ -3443,46 +3462,6 @@ lambda_arity (Lisp_Object fun)
   return Fcons (make_fixnum (minargs), make_fixnum (maxargs));
 }
 
-DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode,
-       1, 1, 0,
-       doc: /* If byte-compiled OBJECT is lazy-loaded, fetch it now.  */)
-  (Lisp_Object object)
-{
-  Lisp_Object tem;
-
-  if (COMPILEDP (object))
-    {
-      if (CONSP (AREF (object, COMPILED_BYTECODE)))
-       {
-         tem = read_doc_string (AREF (object, COMPILED_BYTECODE));
-         if (! (CONSP (tem) && STRINGP (XCAR (tem))
-                && VECTORP (XCDR (tem))))
-           {
-             tem = AREF (object, COMPILED_BYTECODE);
-             if (CONSP (tem) && STRINGP (XCAR (tem)))
-               error ("Invalid byte code in %s", SDATA (XCAR (tem)));
-             else
-               error ("Invalid byte code");
-           }
-
-         Lisp_Object bytecode = XCAR (tem);
-         if (STRING_MULTIBYTE (bytecode))
-           {
-             /* BYTECODE must have been produced by Emacs 20.2 or earlier
-                because it produced a raw 8-bit string for byte-code and now
-                such a byte-code string is loaded as multibyte with raw 8-bit
-                characters converted to multibyte form.  Convert them back to
-                the original unibyte form.  */
-             bytecode = Fstring_as_unibyte (bytecode);
-           }
-
-         pin_string (bytecode);
-         ASET (object, COMPILED_BYTECODE, bytecode);
-         ASET (object, COMPILED_CONSTANTS, XCDR (tem));
-       }
-    }
-  return object;
-}
 
 /* Return true if SYMBOL's default currently has a let-binding
    which was made in the buffer that is now current.  */
@@ -3871,10 +3850,18 @@ get_backtrace_starting_at (Lisp_Object base)
 
   if (!NILP (base))
     { /* Skip up to `base'.  */
+      int offset = 0;
+      if (CONSP (base) && FIXNUMP (XCAR (base)))
+        {
+          offset = XFIXNUM (XCAR (base));
+          base = XCDR (base);
+        }
       base = Findirect_function (base, Qt);
       while (backtrace_p (pdl)
              && !EQ (base, Findirect_function (backtrace_function (pdl), Qt)))
         pdl = backtrace_next (pdl);
+      while (backtrace_p (pdl) && offset-- > 0)
+        pdl = backtrace_next (pdl);
     }
 
   return pdl;
@@ -3914,13 +3901,14 @@ backtrace_frame_apply (Lisp_Object function, union 
specbinding *pdl)
     }
 }
 
-DEFUN ("backtrace-debug", Fbacktrace_debug, Sbacktrace_debug, 2, 2, 0,
+DEFUN ("backtrace-debug", Fbacktrace_debug, Sbacktrace_debug, 2, 3, 0,
        doc: /* Set the debug-on-exit flag of eval frame LEVEL levels down to 
FLAG.
+LEVEL and BASE specify the activation frame to use, as in `backtrace-frame'.
 The debugger is entered when that frame exits, if the flag is non-nil.  */)
-  (Lisp_Object level, Lisp_Object flag)
+  (Lisp_Object level, Lisp_Object flag, Lisp_Object base)
 {
   CHECK_FIXNUM (level);
-  union specbinding *pdl = get_backtrace_frame(level, Qnil);
+  union specbinding *pdl = get_backtrace_frame (level, base);
 
   if (backtrace_p (pdl))
     set_backtrace_debug_on_exit (pdl, !NILP (flag));
@@ -4273,23 +4261,18 @@ mark_specpdl (union specbinding *first, union 
specbinding *ptr)
     }
 }
 
+/* Fill ARRAY of size SIZE with backtrace entries, most recent call first.
+   Truncate the backtrace if longer than SIZE; pad with nil if shorter.  */
 void
-get_backtrace (Lisp_Object array)
+get_backtrace (Lisp_Object *array, ptrdiff_t size)
 {
-  union specbinding *pdl = backtrace_top ();
-  ptrdiff_t i = 0, asize = ASIZE (array);
-
   /* Copy the backtrace contents into working memory.  */
-  for (; i < asize; i++)
-    {
-      if (backtrace_p (pdl))
-       {
-         ASET (array, i, backtrace_function (pdl));
-         pdl = backtrace_next (pdl);
-       }
-      else
-       ASET (array, i, Qnil);
-    }
+  union specbinding *pdl = backtrace_top ();
+  ptrdiff_t i = 0;
+  for (; i < size && backtrace_p (pdl); i++, pdl = backtrace_next (pdl))
+    array[i] = backtrace_function (pdl);
+  for (; i < size; i++)
+    array[i] = Qnil;
 }
 
 Lisp_Object backtrace_top_function (void)
@@ -4309,6 +4292,13 @@ actual stack overflow in C, which would be fatal for 
Emacs.
 You can safely make it considerably larger than its default value,
 if that proves inconveniently small.  However, if you increase it too far,
 Emacs could overflow the real C stack, and crash.  */);
+  max_lisp_eval_depth = 1600;
+
+  DEFVAR_INT ("lisp-eval-depth-reserve", lisp_eval_depth_reserve,
+             doc: /* Extra depth that can be allocated to handle errors.
+This is the max depth that the system will add to `max-lisp-eval-depth'
+when calling debuggers or `handler-bind' handlers.  */);
+  lisp_eval_depth_reserve = 200;
 
   DEFVAR_LISP ("quit-flag", Vquit_flag,
               doc: /* Non-nil causes `eval' to abort, unless `inhibit-quit' is 
non-nil.
@@ -4346,6 +4336,7 @@ before making `inhibit-quit' nil.  */);
   DEFSYM (QCdocumentation, ":documentation");
   DEFSYM (Qdebug, "debug");
   DEFSYM (Qdebug_early, "debug-early");
+  DEFSYM (Qdebug_early__handler, "debug-early--handler");
 
   DEFVAR_LISP ("inhibit-debugger", Vinhibit_debugger,
               doc: /* Non-nil means never enter the debugger.
@@ -4404,11 +4395,14 @@ might not be safe to continue.  */);
   DEFSYM (Qdebugger, "debugger");
   DEFVAR_LISP ("debugger", Vdebugger,
               doc: /* Function to call to invoke debugger.
-If due to frame exit, args are `exit' and the value being returned;
+If due to frame exit, arguments are `exit' and the value being returned;
  this function's value will be returned instead of that.
-If due to error, args are `error' and a list of the args to `signal'.
-If due to `apply' or `funcall' entry, one arg, `lambda'.
-If due to `eval' entry, one arg, t.  */);
+If due to error, arguments are `error' and a list of arguments to `signal'.
+If due to `apply' or `funcall' entry, one argument, `lambda'.
+If due to `eval' entry, one argument, t.
+IF the desired entry point of the debugger is higher in the call stack,
+it can be specified with the keyword argument `:backtrace-base', whose
+format should be the same as the BASE argument of `backtrace-frame'.  */);
   Vdebugger = Qdebug_early;
 
   DEFVAR_LISP ("signal-hook-function", Vsignal_hook_function,
@@ -4521,6 +4515,7 @@ alist of active lexical bindings.  */);
   defsubr (&Sthrow);
   defsubr (&Sunwind_protect);
   defsubr (&Scondition_case);
+  defsubr (&Shandler_bind_1);
   DEFSYM (QCsuccess, ":success");
   defsubr (&Ssignal);
   defsubr (&Scommandp);
@@ -4535,7 +4530,6 @@ alist of active lexical bindings.  */);
   defsubr (&Srun_hook_with_args_until_success);
   defsubr (&Srun_hook_with_args_until_failure);
   defsubr (&Srun_hook_wrapped);
-  defsubr (&Sfetch_bytecode);
   defsubr (&Sbacktrace_debug);
   DEFSYM (QCdebug_on_exit, ":debug-on-exit");
   defsubr (&Smapbacktrace);
diff --git a/src/fileio.c b/src/fileio.c
index 51937e6d765..a92da93ae48 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1,6 +1,6 @@
 /* File IO for GNU Emacs.
 
-Copyright (C) 1985-1988, 1993-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -203,7 +203,7 @@ check_vfs_filename (Lisp_Object encoded, const char *reason)
 #ifdef HAVE_LIBSELINUX
 
 /* Return whether SELinux is enabled and pertinent to FILE.  Provide
-   for cases where FILE is or is a constitutent of a special
+   for cases where FILE is or is a constituent of a special
    directory, such as /assets or /content on Android.  */
 
 static bool
diff --git a/src/filelock.c b/src/filelock.c
index c2b306ab47d..8c27b226900 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -1,6 +1,6 @@
 /* Lock files for editing.
 
-Copyright (C) 1985-1987, 1993-1994, 1996, 1998-2023 Free Software
+Copyright (C) 1985-1987, 1993-1994, 1996, 1998-2024 Free Software
 Foundation, Inc.
 
 Author: Richard King
@@ -563,7 +563,7 @@ lock_file (Lisp_Object fn)
 
   /* See if this file is visited and has changed on disk since it was
      visited.  */
-  Lisp_Object subject_buf = get_truename_buffer (fn);
+  Lisp_Object subject_buf = Fget_truename_buffer (fn);
   if (!NILP (subject_buf)
       && NILP (Fverify_visited_file_modtime (subject_buf))
       && !NILP (Ffile_exists_p (fn))
diff --git a/src/firstfile.c b/src/firstfile.c
index 0b4881dbbe3..737757a2779 100644
--- a/src/firstfile.c
+++ b/src/firstfile.c
@@ -1,5 +1,5 @@
 /* Mark beginning of data space to dump as pure, for GNU Emacs.
-   Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/floatfns.c b/src/floatfns.c
index e40364f8188..4492815c765 100644
--- a/src/floatfns.c
+++ b/src/floatfns.c
@@ -1,6 +1,6 @@
 /* Primitive operations on floating point for GNU Emacs Lisp interpreter.
 
-Copyright (C) 1988, 1993-1994, 1999, 2001-2023 Free Software Foundation,
+Copyright (C) 1988, 1993-1994, 1999, 2001-2024 Free Software Foundation,
 Inc.
 
 Author: Wolfgang Rupprecht (according to ack.texi)
diff --git a/src/fns.c b/src/fns.c
index 8729663c1f9..185abeb8e01 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1,6 +1,6 @@
 /* Random utility Lisp functions.
 
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -2731,6 +2731,10 @@ equal_no_quit (Lisp_Object o1, Lisp_Object o2)
   return internal_equal (o1, o2, EQUAL_NO_QUIT, 0, Qnil);
 }
 
+static ptrdiff_t hash_lookup_with_hash (struct Lisp_Hash_Table *h,
+                                       Lisp_Object key, hash_hash_t hash);
+
+
 /* Return true if O1 and O2 are equal.  EQUAL_KIND specifies what kind
    of equality test to use: if it is EQUAL_NO_QUIT, do not check for
    cycles or large arguments or quits; if EQUAL_PLAIN, do ordinary
@@ -2759,8 +2763,8 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum 
equal_kind equal_kind,
        case Lisp_Cons: case Lisp_Vectorlike:
          {
            struct Lisp_Hash_Table *h = XHASH_TABLE (ht);
-           Lisp_Object hash;
-           ptrdiff_t i = hash_lookup (h, o1, &hash);
+           hash_hash_t hash = hash_from_key (h, o1);
+           ptrdiff_t i = hash_lookup_with_hash (h, o1, hash);
            if (i >= 0)
              { /* `o1' was seen already.  */
                Lisp_Object o2s = HASH_VALUE (h, i);
@@ -4275,17 +4279,20 @@ CHECK_HASH_TABLE (Lisp_Object x)
 static void
 set_hash_next_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, ptrdiff_t val)
 {
-  gc_aset (h->next, idx, make_fixnum (val));
+  eassert (idx >= 0 && idx < h->table_size);
+  h->next[idx] = val;
 }
 static void
-set_hash_hash_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val)
+set_hash_hash_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, hash_hash_t val)
 {
-  gc_aset (h->hash, idx, val);
+  eassert (idx >= 0 && idx < h->table_size);
+  h->hash[idx] = val;
 }
 static void
 set_hash_index_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, ptrdiff_t val)
 {
-  gc_aset (h->index, idx, make_fixnum (val));
+  eassert (idx >= 0 && idx < h->index_size);
+  h->index[idx] = val;
 }
 
 /* If OBJ is a Lisp hash table, return a pointer to its struct
@@ -4339,11 +4346,10 @@ get_key_arg (Lisp_Object key, ptrdiff_t nargs, 
Lisp_Object *args, char *used)
 /* Return a Lisp vector which has the same contents as VEC but has
    at least INCR_MIN more entries, where INCR_MIN is positive.
    If NITEMS_MAX is not -1, do not grow the vector to be any larger
-   than NITEMS_MAX.  New entries in the resulting vector are
-   uninitialized.  */
+   than NITEMS_MAX.  New entries in the resulting vector are nil.  */
 
-static Lisp_Object
-larger_vecalloc (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max)
+Lisp_Object
+larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max)
 {
   struct Lisp_Vector *v;
   ptrdiff_t incr, incr_max, old_size, new_size;
@@ -4360,23 +4366,11 @@ larger_vecalloc (Lisp_Object vec, ptrdiff_t incr_min, 
ptrdiff_t nitems_max)
   new_size = old_size + incr;
   v = allocate_vector (new_size);
   memcpy (v->contents, XVECTOR (vec)->contents, old_size * sizeof 
*v->contents);
+  memclear (v->contents + old_size, (new_size - old_size) * word_size);
   XSETVECTOR (vec, v);
   return vec;
 }
 
-/* Likewise, except set new entries in the resulting vector to nil.  */
-
-Lisp_Object
-larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max)
-{
-  ptrdiff_t old_size = ASIZE (vec);
-  Lisp_Object v = larger_vecalloc (vec, incr_min, nitems_max);
-  ptrdiff_t new_size = ASIZE (v);
-  memclear (XVECTOR (v)->contents + old_size,
-           (new_size - old_size) * word_size);
-  return v;
-}
-
 
 /***********************************************************************
                         Low-level Functions
@@ -4388,7 +4382,8 @@ larger_vector (Lisp_Object vec, ptrdiff_t incr_min, 
ptrdiff_t nitems_max)
 static ptrdiff_t
 HASH_NEXT (struct Lisp_Hash_Table *h, ptrdiff_t idx)
 {
-  return XFIXNUM (AREF (h->next, idx));
+  eassert (idx >= 0 && idx < h->table_size);
+  return h->next[idx];
 }
 
 /* Return the index of the element in hash table H that is the start
@@ -4397,7 +4392,8 @@ HASH_NEXT (struct Lisp_Hash_Table *h, ptrdiff_t idx)
 static ptrdiff_t
 HASH_INDEX (struct Lisp_Hash_Table *h, ptrdiff_t idx)
 {
-  return XFIXNUM (AREF (h->index, idx));
+  eassert (idx >= 0 && idx < h->index_size);
+  return h->index[idx];
 }
 
 /* Restore a hash table's mutability after the critical section exits.  */
@@ -4452,89 +4448,111 @@ static Lisp_Object
 cmpfn_user_defined (Lisp_Object key1, Lisp_Object key2,
                    struct Lisp_Hash_Table *h)
 {
-  Lisp_Object args[] = { h->test.user_cmp_function, key1, key2 };
+  Lisp_Object args[] = { h->test->user_cmp_function, key1, key2 };
   return hash_table_user_defined_call (ARRAYELTS (args), args, h);
 }
 
-/* Ignore H and return a hash code for KEY which uses 'eq' to compare keys.  */
+/* Reduce an EMACS_UINT hash value to hash_hash_t.  */
+static inline hash_hash_t
+reduce_emacs_uint_to_hash_hash (EMACS_UINT x)
+{
+  verify (sizeof x <= 2 * sizeof (hash_hash_t));
+  return (sizeof x == sizeof (hash_hash_t)
+         ? x
+         : x ^ (x >> (8 * (sizeof x - sizeof (hash_hash_t)))));
+}
 
-static Lisp_Object
-hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h)
+static EMACS_INT
+sxhash_eq (Lisp_Object key)
 {
   if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (key))
     key = SYMBOL_WITH_POS_SYM (key);
-  return make_ufixnum (XHASH (key) ^ XTYPE (key));
+  return XHASH (key) ^ XTYPE (key);
 }
 
-/* Ignore H and return a hash code for KEY which uses 'equal' to compare keys.
-   The hash code is at most INTMASK.  */
+static EMACS_INT
+sxhash_eql (Lisp_Object key)
+{
+  return FLOATP (key) || BIGNUMP (key) ? sxhash (key) : sxhash_eq (key);
+}
 
-static Lisp_Object
-hashfn_equal (Lisp_Object key, struct Lisp_Hash_Table *h)
+/* Ignore H and return a hash code for KEY which uses 'eq' to compare keys.  */
+
+static hash_hash_t
+hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h)
 {
-  return make_ufixnum (sxhash (key));
+  return reduce_emacs_uint_to_hash_hash (sxhash_eq (key));
 }
 
-/* Ignore H and return a hash code for KEY which uses 'eql' to compare keys.
-   The hash code is at most INTMASK.  */
+/* Ignore H and return a hash code for KEY which uses 'equal' to
+   compare keys.  */
+static hash_hash_t
+hashfn_equal (Lisp_Object key, struct Lisp_Hash_Table *h)
+{
+  return reduce_emacs_uint_to_hash_hash (sxhash (key));
+}
 
-static Lisp_Object
+/* Ignore H and return a hash code for KEY which uses 'eql' to compare keys.  
*/
+static hash_hash_t
 hashfn_eql (Lisp_Object key, struct Lisp_Hash_Table *h)
 {
-  return (FLOATP (key) || BIGNUMP (key) ? hashfn_equal : hashfn_eq) (key, h);
+  return reduce_emacs_uint_to_hash_hash (sxhash_eql (key));
 }
 
 /* Given H, return a hash code for KEY which uses a user-defined
    function to compare keys.  */
 
-Lisp_Object
+static hash_hash_t
 hashfn_user_defined (Lisp_Object key, struct Lisp_Hash_Table *h)
 {
-  Lisp_Object args[] = { h->test.user_hash_function, key };
+  Lisp_Object args[] = { h->test->user_hash_function, key };
   Lisp_Object hash = hash_table_user_defined_call (ARRAYELTS (args), args, h);
-  return FIXNUMP (hash) ? hash : make_ufixnum (sxhash (hash));
+  return reduce_emacs_uint_to_hash_hash (FIXNUMP (hash)
+                                        ? XUFIXNUM(hash) : sxhash (hash));
 }
 
 struct hash_table_test const
-  hashtest_eq = { LISPSYM_INITIALLY (Qeq), LISPSYM_INITIALLY (Qnil),
-                 LISPSYM_INITIALLY (Qnil), 0, hashfn_eq },
-  hashtest_eql = { LISPSYM_INITIALLY (Qeql), LISPSYM_INITIALLY (Qnil),
-                  LISPSYM_INITIALLY (Qnil), cmpfn_eql, hashfn_eql },
-  hashtest_equal = { LISPSYM_INITIALLY (Qequal), LISPSYM_INITIALLY (Qnil),
-                    LISPSYM_INITIALLY (Qnil), cmpfn_equal, hashfn_equal };
+  hashtest_eq = { .name = LISPSYM_INITIALLY (Qeq),
+                 .cmpfn = 0, .hashfn = hashfn_eq },
+  hashtest_eql = { .name = LISPSYM_INITIALLY (Qeql),
+                  .cmpfn = cmpfn_eql, .hashfn = hashfn_eql },
+  hashtest_equal = { .name = LISPSYM_INITIALLY (Qequal),
+                    .cmpfn = cmpfn_equal, .hashfn = hashfn_equal };
 
 /* Allocate basically initialized hash table.  */
 
 static struct Lisp_Hash_Table *
 allocate_hash_table (void)
 {
-  return ALLOCATE_PSEUDOVECTOR (struct Lisp_Hash_Table,
-                               index, PVEC_HASH_TABLE);
+  return ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Hash_Table, PVEC_HASH_TABLE);
 }
 
-/* An upper bound on the size of a hash table index.  It must fit in
-   ptrdiff_t and be a valid Emacs fixnum.  This is an upper bound on
-   VECTOR_ELTS_MAX (see alloc.c) and gets as close as we can without
-   violating modularity.  */
-#define INDEX_SIZE_BOUND \
-  ((ptrdiff_t) min (MOST_POSITIVE_FIXNUM, \
-                   ((min (PTRDIFF_MAX, SIZE_MAX) \
-                     - header_size - GCALIGNMENT) \
-                    / word_size)))
-
+/* Compute the size of the index from the table capacity.  */
 static ptrdiff_t
-hash_index_size (struct Lisp_Hash_Table *h, ptrdiff_t size)
-{
-  double threshold = h->rehash_threshold;
-  double index_float = size / threshold;
-  ptrdiff_t index_size = (index_float < INDEX_SIZE_BOUND + 1
-                         ? next_almost_prime (index_float)
-                         : INDEX_SIZE_BOUND + 1);
-  if (INDEX_SIZE_BOUND < index_size)
+hash_index_size (ptrdiff_t size)
+{
+  /* An upper bound on the size of a hash table index.  It must fit in
+     ptrdiff_t and be a valid Emacs fixnum.  */
+  ptrdiff_t upper_bound = min (MOST_POSITIVE_FIXNUM,
+                              min (TYPE_MAXIMUM (hash_idx_t),
+                                   PTRDIFF_MAX / sizeof (ptrdiff_t)));
+  /* Single-element index vectors are used iff size=0.  */
+  eassert (size > 0);
+  ptrdiff_t lower_bound = 2;
+  ptrdiff_t index_size = size + max (size >> 2, 1);  /* 1.25x larger */
+  if (index_size < upper_bound)
+    index_size = (index_size < lower_bound
+                 ? lower_bound
+                 : next_almost_prime (index_size));
+  if (index_size > upper_bound)
     error ("Hash table too large");
   return index_size;
 }
 
+/* Constant hash index vector used when the table size is zero.
+   This avoids allocating it from the heap.  */
+static const hash_idx_t empty_hash_index_vector[] = {-1};
+
 /* Create and initialize a new hash table.
 
    TEST specifies the test the hash table will use to compare keys.
@@ -4544,63 +4562,63 @@ hash_index_size (struct Lisp_Hash_Table *h, ptrdiff_t 
size)
 
    Give the table initial capacity SIZE, 0 <= SIZE <= MOST_POSITIVE_FIXNUM.
 
-   If REHASH_SIZE is equal to a negative integer, this hash table's
-   new size when it becomes full is computed by subtracting
-   REHASH_SIZE from its old size.  Otherwise it must be positive, and
-   the table's new size is computed by multiplying its old size by
-   REHASH_SIZE + 1.
-
-   REHASH_THRESHOLD must be a float <= 1.0, and > 0.  The table will
-   be resized when the approximate ratio of table entries to table
-   size exceeds REHASH_THRESHOLD.
-
-   WEAK specifies the weakness of the table.  If non-nil, it must be
-   one of the symbols `key', `value', `key-or-value', or `key-and-value'.
+   WEAK specifies the weakness of the table.
 
    If PURECOPY is non-nil, the table can be copied to pure storage via
    `purecopy' when Emacs is being dumped. Such tables can no longer be
    changed after purecopy.  */
 
 Lisp_Object
-make_hash_table (struct hash_table_test test, EMACS_INT size,
-                float rehash_size, float rehash_threshold,
-                Lisp_Object weak, bool purecopy)
+make_hash_table (const struct hash_table_test *test, EMACS_INT size,
+                hash_table_weakness_t weak, bool purecopy)
 {
-  struct Lisp_Hash_Table *h;
-  Lisp_Object table;
-  ptrdiff_t i;
+  eassert (SYMBOLP (test->name));
+  eassert (0 <= size && size <= min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX));
 
-  /* Preconditions.  */
-  eassert (SYMBOLP (test.name));
-  eassert (0 <= size && size <= MOST_POSITIVE_FIXNUM);
-  eassert (rehash_size <= -1 || 0 < rehash_size);
-  eassert (0 < rehash_threshold && rehash_threshold <= 1);
+  struct Lisp_Hash_Table *h = allocate_hash_table ();
+
+  h->test = test;
+  h->weakness = weak;
+  h->count = 0;
+  h->table_size = size;
 
   if (size == 0)
-    size = 1;
+    {
+      h->key_and_value = NULL;
+      h->hash = NULL;
+      h->next = NULL;
+      h->index_size = 1;
+      h->index = (hash_idx_t *)empty_hash_index_vector;
+      h->next_free = -1;
+    }
+  else
+    {
+      h->key_and_value = hash_table_alloc_bytes (2 * size
+                                                * sizeof *h->key_and_value);
+      for (ptrdiff_t i = 0; i < 2 * size; i++)
+       h->key_and_value[i] = HASH_UNUSED_ENTRY_KEY;
 
-  /* Allocate a table and initialize it.  */
-  h = allocate_hash_table ();
+      h->hash = hash_table_alloc_bytes (size * sizeof *h->hash);
+
+      h->next = hash_table_alloc_bytes (size * sizeof *h->next);
+      for (ptrdiff_t i = 0; i < size - 1; i++)
+       h->next[i] = i + 1;
+      h->next[size - 1] = -1;
+
+      int index_size = hash_index_size (size);
+      h->index_size = index_size;
+      h->index = hash_table_alloc_bytes (index_size * sizeof *h->index);
+      for (ptrdiff_t i = 0; i < index_size; i++)
+       h->index[i] = -1;
+
+      h->next_free = 0;
+    }
 
-  /* Initialize hash table slots.  */
-  h->test = test;
-  h->weak = weak;
-  h->rehash_threshold = rehash_threshold;
-  h->rehash_size = rehash_size;
-  h->count = 0;
-  h->key_and_value = make_vector (2 * size, Qunbound);
-  h->hash = make_nil_vector (size);
-  h->next = make_vector (size, make_fixnum (-1));
-  h->index = make_vector (hash_index_size (h, size), make_fixnum (-1));
   h->next_weak = NULL;
   h->purecopy = purecopy;
   h->mutable = true;
 
-  /* Set up the free list.  */
-  for (i = 0; i < size - 1; ++i)
-    set_hash_next_slot (h, i, i + 1);
-  h->next_free = 0;
-
+  Lisp_Object table;
   XSET_HASH_TABLE (table, h);
   eassert (HASH_TABLE_P (table));
   eassert (XHASH_TABLE (table) == h);
@@ -4621,16 +4639,39 @@ copy_hash_table (struct Lisp_Hash_Table *h1)
   h2 = allocate_hash_table ();
   *h2 = *h1;
   h2->mutable = true;
-  h2->key_and_value = Fcopy_sequence (h1->key_and_value);
-  h2->hash = Fcopy_sequence (h1->hash);
-  h2->next = Fcopy_sequence (h1->next);
-  h2->index = Fcopy_sequence (h1->index);
+
+  if (h1->table_size > 0)
+    {
+      ptrdiff_t kv_bytes = 2 * h1->table_size * sizeof *h1->key_and_value;
+      h2->key_and_value = hash_table_alloc_bytes (kv_bytes);
+      memcpy (h2->key_and_value, h1->key_and_value, kv_bytes);
+
+      ptrdiff_t hash_bytes = h1->table_size * sizeof *h1->hash;
+      h2->hash = hash_table_alloc_bytes (hash_bytes);
+      memcpy (h2->hash, h1->hash, hash_bytes);
+
+      ptrdiff_t next_bytes = h1->table_size * sizeof *h1->next;
+      h2->next = hash_table_alloc_bytes (next_bytes);
+      memcpy (h2->next, h1->next, next_bytes);
+
+      ptrdiff_t index_bytes = h1->index_size * sizeof *h1->index;
+      h2->index = hash_table_alloc_bytes (index_bytes);
+      memcpy (h2->index, h1->index, index_bytes);
+    }
   XSET_HASH_TABLE (table, h2);
 
   return table;
 }
 
 
+/* Compute index into the index vector from a hash value.  */
+static inline ptrdiff_t
+hash_index_index (struct Lisp_Hash_Table *h, hash_hash_t hash)
+{
+  eassert (h->index_size > 0);
+  return hash % h->index_size;
+}
+
 /* Resize hash table H if it's too full.  If H cannot be resized
    because it's already too large, throw an error.  */
 
@@ -4640,121 +4681,166 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
   if (h->next_free < 0)
     {
       ptrdiff_t old_size = HASH_TABLE_SIZE (h);
-      EMACS_INT new_size;
-      double rehash_size = h->rehash_size;
-
-      if (rehash_size < 0)
-       new_size = old_size - rehash_size;
-      else
-       {
-         double float_new_size = old_size * (rehash_size + 1);
-         if (float_new_size < EMACS_INT_MAX)
-           new_size = float_new_size;
-         else
-           new_size = EMACS_INT_MAX;
-       }
-      if (PTRDIFF_MAX < new_size)
-       new_size = PTRDIFF_MAX;
-      if (new_size <= old_size)
-       new_size = old_size + 1;
+      ptrdiff_t min_size = 8;
+      ptrdiff_t base_size = min (max (old_size, min_size), PTRDIFF_MAX / 2);
+      /* Grow aggressively at small sizes, then just double.  */
+      ptrdiff_t new_size =
+       old_size == 0
+       ? min_size
+       : (base_size <= 64 ? base_size * 4 : base_size * 2);
 
       /* Allocate all the new vectors before updating *H, to
-        avoid problems if memory is exhausted.  larger_vecalloc
-        finishes computing the size of the replacement vectors.  */
-      Lisp_Object next = larger_vecalloc (h->next, new_size - old_size,
-                                         new_size);
-      ptrdiff_t next_size = ASIZE (next);
-      for (ptrdiff_t i = old_size; i < next_size - 1; i++)
-       ASET (next, i, make_fixnum (i + 1));
-      ASET (next, next_size - 1, make_fixnum (-1));
-
-      /* Build the new&larger key_and_value vector, making sure the new
-         fields are initialized to `unbound`.  */
-      Lisp_Object key_and_value
-       = larger_vecalloc (h->key_and_value, 2 * (next_size - old_size),
-                          2 * next_size);
-      for (ptrdiff_t i = 2 * old_size; i < 2 * next_size; i++)
-        ASET (key_and_value, i, Qunbound);
-
-      Lisp_Object hash = larger_vector (h->hash, next_size - old_size,
-                                       next_size);
-      ptrdiff_t index_size = hash_index_size (h, next_size);
-      h->index = make_vector (index_size, make_fixnum (-1));
+        avoid problems if memory is exhausted.  */
+      hash_idx_t *next = hash_table_alloc_bytes (new_size * sizeof *next);
+      for (ptrdiff_t i = old_size; i < new_size - 1; i++)
+       next[i] = i + 1;
+      next[new_size - 1] = -1;
+
+      Lisp_Object *key_and_value
+       = hash_table_alloc_bytes (2 * new_size * sizeof *key_and_value);
+      memcpy (key_and_value, h->key_and_value,
+             2 * old_size * sizeof *key_and_value);
+      for (ptrdiff_t i = 2 * old_size; i < 2 * new_size; i++)
+        key_and_value[i] = HASH_UNUSED_ENTRY_KEY;
+
+      hash_hash_t *hash = hash_table_alloc_bytes (new_size * sizeof *hash);
+      memcpy (hash, h->hash, old_size * sizeof *hash);
+
+      ptrdiff_t old_index_size = h->index_size;
+      ptrdiff_t index_size = hash_index_size (new_size);
+      hash_idx_t *index = hash_table_alloc_bytes (index_size * sizeof *index);
+      for (ptrdiff_t i = 0; i < index_size; i++)
+       index[i] = -1;
+
+      h->index_size = index_size;
+      h->table_size = new_size;
+      h->next_free = old_size;
+
+      if (old_index_size > 1)
+       hash_table_free_bytes (h->index, old_index_size * sizeof *h->index);
+      h->index = index;
+
+      hash_table_free_bytes (h->key_and_value,
+                            2 * old_size * sizeof *h->key_and_value);
       h->key_and_value = key_and_value;
+
+      hash_table_free_bytes (h->hash, old_size * sizeof *h->hash);
       h->hash = hash;
+
+      hash_table_free_bytes (h->next, old_size * sizeof *h->next);
       h->next = next;
-      h->next_free = old_size;
 
-      /* Rehash.  */
+      h->key_and_value = key_and_value;
+
+      /* Rehash: all data occupy entries 0..old_size-1.  */
       for (ptrdiff_t i = 0; i < old_size; i++)
-       if (!NILP (HASH_HASH (h, i)))
-         {
-           EMACS_UINT hash_code = XUFIXNUM (HASH_HASH (h, i));
-           ptrdiff_t start_of_bucket = hash_code % ASIZE (h->index);
-           set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket));
-           set_hash_index_slot (h, start_of_bucket, i);
-         }
+       {
+         hash_hash_t hash_code = HASH_HASH (h, i);
+         ptrdiff_t start_of_bucket = hash_index_index (h, hash_code);
+         set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket));
+         set_hash_index_slot (h, start_of_bucket, i);
+       }
 
 #ifdef ENABLE_CHECKING
       if (HASH_TABLE_P (Vpurify_flag) && XHASH_TABLE (Vpurify_flag) == h)
-       message ("Growing hash table to: %"pD"d", next_size);
+       message ("Growing hash table to: %"pD"d", new_size);
 #endif
     }
 }
 
-/* Recompute the hashes (and hence also the "next" pointers).
-   Normally there's never a need to recompute hashes.
-   This is done only on first access to a hash-table loaded from
-   the "pdump", because the objects' addresses may have changed, thus
-   affecting their hashes.  */
+static const struct hash_table_test *
+hash_table_test_from_std (hash_table_std_test_t test)
+{
+  switch (test)
+    {
+    case Test_eq:    return &hashtest_eq;
+    case Test_eql:   return &hashtest_eql;
+    case Test_equal: return &hashtest_equal;
+    }
+  emacs_abort();
+}
+
+/* Rebuild a hash table from its frozen (dumped) form.  */
 void
-hash_table_rehash (Lisp_Object hash)
+hash_table_thaw (Lisp_Object hash_table)
 {
-  struct Lisp_Hash_Table *h = XHASH_TABLE (hash);
-  ptrdiff_t i, count = h->count;
+  struct Lisp_Hash_Table *h = XHASH_TABLE (hash_table);
+
+  /* Freezing discarded most non-essential information; recompute it.
+     The allocation is minimal with no room for growth.  */
+  h->test = hash_table_test_from_std (h->frozen_test);
+  ptrdiff_t size = h->count;
+  h->table_size = size;
+  h->next_free = -1;
 
-  /* Recompute the actual hash codes for each entry in the table.
-     Order is still invalid.  */
-  for (i = 0; i < count; i++)
+  if (size == 0)
     {
-      Lisp_Object key = HASH_KEY (h, i);
-      Lisp_Object hash_code = h->test.hashfn (key, h);
-      ptrdiff_t start_of_bucket = XUFIXNUM (hash_code) % ASIZE (h->index);
-      set_hash_hash_slot (h, i, hash_code);
-      set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket));
-      set_hash_index_slot (h, start_of_bucket, i);
-      eassert (HASH_NEXT (h, i) != i); /* Stop loops.  */
+      h->key_and_value = NULL;
+      h->hash = NULL;
+      h->next = NULL;
+      h->index_size = 1;
+      h->index = (hash_idx_t *)empty_hash_index_vector;
     }
+  else
+    {
+      ptrdiff_t index_size = hash_index_size (size);
+      h->index_size = index_size;
 
-  ptrdiff_t size = ASIZE (h->next);
-  for (; i + 1 < size; i++)
-    set_hash_next_slot (h, i, i + 1);
-}
-
-/* Lookup KEY in hash table H.  If HASH is non-null, return in *HASH
-   the hash code of KEY.  Value is the index of the entry in H
-   matching KEY, or -1 if not found.  */
+      h->hash = hash_table_alloc_bytes (size * sizeof *h->hash);
 
-ptrdiff_t
-hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object *hash)
-{
-  ptrdiff_t start_of_bucket, i;
+      h->next = hash_table_alloc_bytes (size * sizeof *h->next);
 
-  Lisp_Object hash_code;
-  hash_code = h->test.hashfn (key, h);
-  if (hash)
-    *hash = hash_code;
+      h->index = hash_table_alloc_bytes (index_size * sizeof *h->index);
+      for (ptrdiff_t i = 0; i < index_size; i++)
+       h->index[i] = -1;
 
-  start_of_bucket = XUFIXNUM (hash_code) % ASIZE (h->index);
+      /* Recompute the hash codes for each entry in the table.  */
+      for (ptrdiff_t i = 0; i < size; i++)
+       {
+         Lisp_Object key = HASH_KEY (h, i);
+         hash_hash_t hash_code = hash_from_key (h, key);
+         ptrdiff_t start_of_bucket = hash_index_index (h, hash_code);
+         set_hash_hash_slot (h, i, hash_code);
+         set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket));
+         set_hash_index_slot (h, start_of_bucket, i);
+       }
+    }
+}
 
-  for (i = HASH_INDEX (h, start_of_bucket); 0 <= i; i = HASH_NEXT (h, i))
+/* Look up KEY with hash HASH in table H.
+   Return entry index or -1 if none.  */
+static ptrdiff_t
+hash_lookup_with_hash (struct Lisp_Hash_Table *h,
+                      Lisp_Object key, hash_hash_t hash)
+{
+  ptrdiff_t start_of_bucket = hash_index_index (h, hash);
+  for (ptrdiff_t i = HASH_INDEX (h, start_of_bucket);
+       0 <= i; i = HASH_NEXT (h, i))
     if (EQ (key, HASH_KEY (h, i))
-       || (h->test.cmpfn
-           && EQ (hash_code, HASH_HASH (h, i))
-           && !NILP (h->test.cmpfn (key, HASH_KEY (h, i), h))))
-      break;
+       || (h->test->cmpfn
+           && hash == HASH_HASH (h, i)
+           && !NILP (h->test->cmpfn (key, HASH_KEY (h, i), h))))
+      return i;
 
-  return i;
+  return -1;
+}
+
+/* Look up KEY in table H.  Return entry index or -1 if none.  */
+ptrdiff_t
+hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key)
+{
+  return hash_lookup_with_hash (h, key, hash_from_key (h, key));
+}
+
+/* Look up KEY in hash table H.  Return its hash value in *PHASH.
+   Value is the index of the entry in H matching KEY, or -1 if not found.  */
+ptrdiff_t
+hash_lookup_get_hash (struct Lisp_Hash_Table *h, Lisp_Object key,
+                     hash_hash_t *phash)
+{
+  EMACS_UINT hash = hash_from_key (h, key);
+  *phash = hash;
+  return hash_lookup_with_hash (h, key, hash);
 }
 
 static void
@@ -4765,33 +4851,22 @@ check_mutable_hash_table (Lisp_Object obj, struct 
Lisp_Hash_Table *h)
   eassert (!PURE_P (h));
 }
 
-static void
-collect_interval (INTERVAL interval, Lisp_Object collector)
-{
-  nconc2 (collector,
-         list1(list3 (make_fixnum (interval->position),
-                      make_fixnum (interval->position + LENGTH (interval)),
-                      interval->plist)));
-}
-
 /* Put an entry into hash table H that associates KEY with VALUE.
    HASH is a previously computed hash code of KEY.
    Value is the index of the entry in H matching KEY.  */
 
 ptrdiff_t
 hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value,
-         Lisp_Object hash)
+         hash_hash_t hash)
 {
-  ptrdiff_t start_of_bucket, i;
-
+  eassert (!hash_unused_entry_key_p (key));
   /* Increment count after resizing because resizing may fail.  */
   maybe_resize_hash_table (h);
   h->count++;
 
   /* Store key/value in the key_and_value vector.  */
-  i = h->next_free;
-  eassert (NILP (HASH_HASH (h, i)));
-  eassert (BASE_EQ (Qunbound, (HASH_KEY (h, i))));
+  ptrdiff_t i = h->next_free;
+  eassert (hash_unused_entry_key_p (HASH_KEY (h, i)));
   h->next_free = HASH_NEXT (h, i);
   set_hash_key_slot (h, i, key);
   set_hash_value_slot (h, i, value);
@@ -4800,7 +4875,7 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, 
Lisp_Object value,
   set_hash_hash_slot (h, i, hash);
 
   /* Add new entry to its collision chain.  */
-  start_of_bucket = XUFIXNUM (hash) % ASIZE (h->index);
+  ptrdiff_t start_of_bucket = hash_index_index (h, hash);
   set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket));
   set_hash_index_slot (h, start_of_bucket, i);
   return i;
@@ -4812,8 +4887,8 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, 
Lisp_Object value,
 void
 hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key)
 {
-  Lisp_Object hash_code = h->test.hashfn (key, h);
-  ptrdiff_t start_of_bucket = XUFIXNUM (hash_code) % ASIZE (h->index);
+  hash_hash_t hashval = hash_from_key (h, key);
+  ptrdiff_t start_of_bucket = hash_index_index (h, hashval);
   ptrdiff_t prev = -1;
 
   for (ptrdiff_t i = HASH_INDEX (h, start_of_bucket);
@@ -4821,9 +4896,9 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, 
Lisp_Object key)
        i = HASH_NEXT (h, i))
     {
       if (EQ (key, HASH_KEY (h, i))
-         || (h->test.cmpfn
-             && EQ (hash_code, HASH_HASH (h, i))
-             && !NILP (h->test.cmpfn (key, HASH_KEY (h, i), h))))
+         || (h->test->cmpfn
+             && hashval == HASH_HASH (h, i)
+             && !NILP (h->test->cmpfn (key, HASH_KEY (h, i), h))))
        {
          /* Take entry out of collision chain.  */
          if (prev < 0)
@@ -4833,9 +4908,8 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, 
Lisp_Object key)
 
          /* Clear slots in key_and_value and add the slots to
             the free list.  */
-         set_hash_key_slot (h, i, Qunbound);
+         set_hash_key_slot (h, i, HASH_UNUSED_ENTRY_KEY);
          set_hash_value_slot (h, i, Qnil);
-         set_hash_hash_slot (h, i, Qnil);
          set_hash_next_slot (h, i, h->next_free);
          h->next_free = i;
          h->count--;
@@ -4856,16 +4930,15 @@ hash_clear (struct Lisp_Hash_Table *h)
   if (h->count > 0)
     {
       ptrdiff_t size = HASH_TABLE_SIZE (h);
-      memclear (xvector_contents (h->hash), size * word_size);
       for (ptrdiff_t i = 0; i < size; i++)
        {
          set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1);
-         set_hash_key_slot (h, i, Qunbound);
+         set_hash_key_slot (h, i, HASH_UNUSED_ENTRY_KEY);
          set_hash_value_slot (h, i, Qnil);
        }
 
-      for (ptrdiff_t i = 0; i < ASIZE (h->index); i++)
-       ASET (h->index, i, make_fixnum (-1));
+      for (ptrdiff_t i = 0; i < h->index_size; i++)
+       h->index[i] = -1;
 
       h->next_free = 0;
       h->count = 0;
@@ -4878,6 +4951,23 @@ hash_clear (struct Lisp_Hash_Table *h)
                           Weak Hash Tables
  ************************************************************************/
 
+/* Whether to keep an entry whose key and value are known to be retained
+   if STRONG_KEY and STRONG_VALUE, respectively, are true.  */
+static inline bool
+keep_entry_p (hash_table_weakness_t weakness,
+             bool strong_key, bool strong_value)
+{
+  switch (weakness)
+    {
+    case Weak_None:          return true;
+    case Weak_Key:           return strong_key;
+    case Weak_Value:         return strong_value;
+    case Weak_Key_Or_Value:  return strong_key || strong_value;
+    case Weak_Key_And_Value: return strong_key && strong_value;
+    }
+  emacs_abort();
+}
+
 /* Sweep weak hash table H.  REMOVE_ENTRIES_P means remove
    entries from the table that don't survive the current GC.
    !REMOVE_ENTRIES_P means mark entries that are in use.  Value is
@@ -4886,7 +4976,7 @@ hash_clear (struct Lisp_Hash_Table *h)
 bool
 sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p)
 {
-  ptrdiff_t n = gc_asize (h->index);
+  ptrdiff_t n = h->index_size;
   bool marked = false;
 
   for (ptrdiff_t bucket = 0; bucket < n; ++bucket)
@@ -4899,18 +4989,9 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool 
remove_entries_p)
         {
          bool key_known_to_survive_p = survives_gc_p (HASH_KEY (h, i));
          bool value_known_to_survive_p = survives_gc_p (HASH_VALUE (h, i));
-         bool remove_p;
-
-         if (EQ (h->weak, Qkey))
-           remove_p = !key_known_to_survive_p;
-         else if (EQ (h->weak, Qvalue))
-           remove_p = !value_known_to_survive_p;
-         else if (EQ (h->weak, Qkey_or_value))
-           remove_p = !(key_known_to_survive_p || value_known_to_survive_p);
-         else if (EQ (h->weak, Qkey_and_value))
-           remove_p = !(key_known_to_survive_p && value_known_to_survive_p);
-         else
-           emacs_abort ();
+         bool remove_p = !keep_entry_p (h->weakness,
+                                        key_known_to_survive_p,
+                                        value_known_to_survive_p);
 
          next = HASH_NEXT (h, i);
 
@@ -4930,11 +5011,9 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool 
remove_entries_p)
                  set_hash_next_slot (h, i, h->next_free);
                  h->next_free = i;
 
-                 /* Clear key, value, and hash.  */
-                 set_hash_key_slot (h, i, Qunbound);
+                 /* Clear key and value.  */
+                 set_hash_key_slot (h, i, HASH_UNUSED_ENTRY_KEY);
                  set_hash_value_slot (h, i, Qnil);
-                  if (!NILP (h->hash))
-                    set_hash_hash_slot (h, i, Qnil);
 
                   eassert (h->count != 0);
                   h->count--;
@@ -5016,16 +5095,6 @@ hash_string (char const *ptr, ptrdiff_t len)
   return hash;
 }
 
-/* Return a hash for string PTR which has length LEN.  The hash
-   code returned is at most INTMASK.  */
-
-static EMACS_UINT
-sxhash_string (char const *ptr, ptrdiff_t len)
-{
-  EMACS_UINT hash = hash_string (ptr, len);
-  return SXHASH_REDUCE (hash);
-}
-
 /* Return a hash for the floating point value VAL.  */
 
 static EMACS_UINT
@@ -5035,7 +5104,7 @@ sxhash_float (double val)
   union double_and_words u = { .val = val };
   for (int i = 0; i < WORDS_PER_DOUBLE; i++)
     hash = sxhash_combine (hash, u.word[i]);
-  return SXHASH_REDUCE (hash);
+  return hash;
 }
 
 /* Return a hash for list LIST.  DEPTH is the current depth in the
@@ -5062,7 +5131,7 @@ sxhash_list (Lisp_Object list, int depth)
       hash = sxhash_combine (hash, hash2);
     }
 
-  return SXHASH_REDUCE (hash);
+  return hash;
 }
 
 
@@ -5082,7 +5151,7 @@ sxhash_vector (Lisp_Object vec, int depth)
       hash = sxhash_combine (hash, hash2);
     }
 
-  return SXHASH_REDUCE (hash);
+  return hash;
 }
 
 /* Return a hash for bool-vector VECTOR.  */
@@ -5098,7 +5167,7 @@ sxhash_bool_vector (Lisp_Object vec)
   for (i = 0; i < n; ++i)
     hash = sxhash_combine (hash, bool_vector_data (vec)[i]);
 
-  return SXHASH_REDUCE (hash);
+  return hash;
 }
 
 /* Return a hash for a bignum.  */
@@ -5113,19 +5182,18 @@ sxhash_bignum (Lisp_Object bignum)
   for (i = 0; i < nlimbs; ++i)
     hash = sxhash_combine (hash, mpz_getlimbn (*n, i));
 
-  return SXHASH_REDUCE (hash);
+  return hash;
 }
 
-
-/* Return a hash code for OBJ.  DEPTH is the current depth in the Lisp
-   structure.  Value is an unsigned integer clipped to INTMASK.  */
-
 EMACS_UINT
 sxhash (Lisp_Object obj)
 {
   return sxhash_obj (obj, 0);
 }
 
+/* Return a hash code for OBJ.  DEPTH is the current depth in the Lisp
+   structure.  */
+
 static EMACS_UINT
 sxhash_obj (Lisp_Object obj, int depth)
 {
@@ -5141,7 +5209,7 @@ sxhash_obj (Lisp_Object obj, int depth)
       return XHASH (obj);
 
     case Lisp_String:
-      return sxhash_string (SSDATA (obj), SBYTES (obj));
+      return hash_string (SSDATA (obj), SBYTES (obj));
 
     case Lisp_Vectorlike:
       {
@@ -5168,7 +5236,7 @@ sxhash_obj (Lisp_Object obj, int depth)
              = XMARKER (obj)->buffer ? XMARKER (obj)->bytepos : 0;
            EMACS_UINT hash
              = sxhash_combine ((intptr_t) XMARKER (obj)->buffer, bytepos);
-           return SXHASH_REDUCE (hash);
+           return hash;
          }
        else if (pvec_type == PVEC_BOOL_VECTOR)
          return sxhash_bool_vector (obj);
@@ -5177,7 +5245,7 @@ sxhash_obj (Lisp_Object obj, int depth)
            EMACS_UINT hash = OVERLAY_START (obj);
            hash = sxhash_combine (hash, OVERLAY_END (obj));
            hash = sxhash_combine (hash, sxhash_obj (XOVERLAY (obj)->plist, 
depth));
-           return SXHASH_REDUCE (hash);
+           return hash;
          }
        else if (symbols_with_pos_enabled && pvec_type == PVEC_SYMBOL_WITH_POS)
          return sxhash_obj (XSYMBOL_WITH_POS (obj)->sym, depth + 1);
@@ -5198,12 +5266,41 @@ sxhash_obj (Lisp_Object obj, int depth)
     }
 }
 
+static void
+hash_interval (INTERVAL interval, void *arg)
+{
+  EMACS_UINT *phash = arg;
+  EMACS_UINT hash = *phash;
+  hash = sxhash_combine (hash, interval->position);
+  hash = sxhash_combine (hash, LENGTH (interval));
+  hash = sxhash_combine (hash, sxhash_obj (interval->plist, 0));
+  *phash = hash;
+}
+
+static void
+collect_interval (INTERVAL interval, void *arg)
+{
+  Lisp_Object *collector = arg;
+  *collector = Fcons (list3 (make_fixnum (interval->position),
+                            make_fixnum (interval->position
+                                         + LENGTH (interval)),
+                            interval->plist),
+                     *collector);
+}
+
 
 
 /***********************************************************************
                            Lisp Interface
  ***********************************************************************/
 
+/* Reduce the hash value X to a Lisp fixnum.  */
+static inline Lisp_Object
+reduce_emacs_uint_to_fixnum (EMACS_UINT x)
+{
+  return make_ufixnum (SXHASH_REDUCE (x));
+}
+
 DEFUN ("sxhash-eq", Fsxhash_eq, Ssxhash_eq, 1, 1, 0,
        doc: /* Return an integer hash code for OBJ suitable for `eq'.
 If (eq A B), then (= (sxhash-eq A) (sxhash-eq B)).
@@ -5211,7 +5308,7 @@ If (eq A B), then (= (sxhash-eq A) (sxhash-eq B)).
 Hash codes are not guaranteed to be preserved across Emacs sessions.  */)
   (Lisp_Object obj)
 {
-  return hashfn_eq (obj, NULL);
+  return reduce_emacs_uint_to_fixnum (sxhash_eq (obj));
 }
 
 DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0,
@@ -5222,7 +5319,7 @@ isn't necessarily true.
 Hash codes are not guaranteed to be preserved across Emacs sessions.  */)
   (Lisp_Object obj)
 {
-  return hashfn_eql (obj, NULL);
+  return reduce_emacs_uint_to_fixnum (sxhash_eql (obj));
 }
 
 DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0,
@@ -5233,7 +5330,7 @@ opposite isn't necessarily true.
 Hash codes are not guaranteed to be preserved across Emacs sessions.  */)
   (Lisp_Object obj)
 {
-  return hashfn_equal (obj, NULL);
+  return reduce_emacs_uint_to_fixnum (sxhash (obj));
 }
 
 DEFUN ("sxhash-equal-including-properties", Fsxhash_equal_including_properties,
@@ -5246,18 +5343,65 @@ If (sxhash-equal-including-properties A B), then
 Hash codes are not guaranteed to be preserved across Emacs sessions.  */)
   (Lisp_Object obj)
 {
+  EMACS_UINT hash = sxhash (obj);
   if (STRINGP (obj))
+    traverse_intervals (string_intervals (obj), 0, hash_interval, &hash);
+  return reduce_emacs_uint_to_fixnum (hash);
+}
+
+
+/* This is a cache of hash_table_test structures so that they can be
+   shared between hash tables using the same test.
+   FIXME: This way of storing and looking up hash_table_test structs
+   isn't wonderful.  Find a better solution.  */
+struct hash_table_user_test
+{
+  struct hash_table_test test;
+  struct hash_table_user_test *next;
+};
+
+static struct hash_table_user_test *hash_table_user_tests = NULL;
+
+void
+mark_fns (void)
+{
+  for (struct hash_table_user_test *ut = hash_table_user_tests;
+       ut; ut = ut->next)
     {
-      Lisp_Object collector = Fcons (Qnil, Qnil);
-      traverse_intervals (string_intervals (obj), 0, collect_interval,
-                         collector);
-      return
-       make_ufixnum (
-         SXHASH_REDUCE (sxhash_combine (sxhash (obj),
-                                        sxhash (CDR (collector)))));
+      mark_object (ut->test.name);
+      mark_object (ut->test.user_cmp_function);
+      mark_object (ut->test.user_hash_function);
     }
+}
 
-  return hashfn_equal (obj, NULL);
+/* Find the hash_table_test object correponding to the (bare) symbol TEST,
+   creating one if none existed.  */
+static struct hash_table_test *
+get_hash_table_user_test (Lisp_Object test)
+{
+  Lisp_Object prop = Fget (test, Qhash_table_test);
+  if (!CONSP (prop) || !CONSP (XCDR (prop)))
+    signal_error ("Invalid hash table test", test);
+
+  Lisp_Object equal_fn = XCAR (prop);
+  Lisp_Object hash_fn = XCAR (XCDR (prop));
+  struct hash_table_user_test *ut = hash_table_user_tests;
+  while (ut && !(BASE_EQ (test, ut->test.name)
+                && EQ (equal_fn, ut->test.user_cmp_function)
+                && EQ (hash_fn, ut->test.user_hash_function)))
+    ut = ut->next;
+  if (!ut)
+    {
+      ut = xmalloc (sizeof *ut);
+      ut->test.name = test;
+      ut->test.user_cmp_function = equal_fn;
+      ut->test.user_hash_function = hash_fn;
+      ut->test.hashfn = hashfn_user_defined;
+      ut->test.cmpfn = cmpfn_user_defined;
+      ut->next = hash_table_user_tests;
+      hash_table_user_tests = ut;
+    }
+  return &ut->test;
 }
 
 DEFUN ("make-hash-table", Fmake_hash_table, Smake_hash_table, 0, MANY, 0,
@@ -5272,16 +5416,8 @@ keys.  Default is `eql'.  Predefined are the tests `eq', 
`eql', and
 `define-hash-table-test'.
 
 :size SIZE -- A hint as to how many elements will be put in the table.
-Default is 65.
-
-:rehash-size REHASH-SIZE - Indicates how to expand the table when it
-fills up.  If REHASH-SIZE is an integer, increase the size by that
-amount.  If it is a float, it must be > 1.0, and the new size is the
-old size multiplied by that factor.  Default is 1.5.
-
-:rehash-threshold THRESHOLD -- THRESHOLD must a float > 0, and <= 1.0.
-Resize the hash table when the ratio (table entries / table size)
-exceeds an approximation to THRESHOLD.  Default is 0.8125.
+The table will always grow as needed; this argument may help performance
+slightly if the size is known in advance but is never required.
 
 :weakness WEAK -- WEAK must be one of nil, t, `key', `value',
 `key-or-value', or `key-and-value'.  If WEAK is not nil, the table
@@ -5296,13 +5432,12 @@ to pure storage when Emacs is being dumped, making the 
contents of the
 table read only. Any further changes to purified tables will result
 in an error.
 
+The keywords arguments :rehash-threshold and :rehash-size are obsolete
+and ignored.
+
 usage: (make-hash-table &rest KEYWORD-ARGS)  */)
   (ptrdiff_t nargs, Lisp_Object *args)
 {
-  Lisp_Object test, weak;
-  bool purecopy;
-  struct hash_table_test testdesc;
-  ptrdiff_t i;
   USE_SAFE_ALLOCA;
 
   /* The vector `used' is used to keep track of arguments that
@@ -5311,32 +5446,23 @@ usage: (make-hash-table &rest KEYWORD-ARGS)  */)
   memset (used, 0, nargs * sizeof *used);
 
   /* See if there's a `:test TEST' among the arguments.  */
-  i = get_key_arg (QCtest, nargs, args, used);
-  test = i ? args[i] : Qeql;
-  if (EQ (test, Qeq))
-    testdesc = hashtest_eq;
-  else if (EQ (test, Qeql))
-    testdesc = hashtest_eql;
-  else if (EQ (test, Qequal))
-    testdesc = hashtest_equal;
+  ptrdiff_t i = get_key_arg (QCtest, nargs, args, used);
+  Lisp_Object test = i ? args[i] : Qeql;
+  if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (test))
+    test = SYMBOL_WITH_POS_SYM (test);
+  const struct hash_table_test *testdesc;
+  if (BASE_EQ (test, Qeq))
+    testdesc = &hashtest_eq;
+  else if (BASE_EQ (test, Qeql))
+    testdesc = &hashtest_eql;
+  else if (BASE_EQ (test, Qequal))
+    testdesc = &hashtest_equal;
   else
-    {
-      /* See if it is a user-defined test.  */
-      Lisp_Object prop;
-
-      prop = Fget (test, Qhash_table_test);
-      if (!CONSP (prop) || !CONSP (XCDR (prop)))
-       signal_error ("Invalid hash table test", test);
-      testdesc.name = test;
-      testdesc.user_cmp_function = XCAR (prop);
-      testdesc.user_hash_function = XCAR (XCDR (prop));
-      testdesc.hashfn = hashfn_user_defined;
-      testdesc.cmpfn = cmpfn_user_defined;
-    }
+    testdesc = get_hash_table_user_test (test);
 
   /* See if there's a `:purecopy PURECOPY' argument.  */
   i = get_key_arg (QCpurecopy, nargs, args, used);
-  purecopy = i && !NILP (args[i]);
+  bool purecopy = i && !NILP (args[i]);
   /* See if there's a `:size SIZE' argument.  */
   i = get_key_arg (QCsize, nargs, args, used);
   Lisp_Object size_arg = i ? args[i] : Qnil;
@@ -5348,46 +5474,36 @@ usage: (make-hash-table &rest KEYWORD-ARGS)  */)
   else
     signal_error ("Invalid hash table size", size_arg);
 
-  /* Look for `:rehash-size SIZE'.  */
-  float rehash_size;
-  i = get_key_arg (QCrehash_size, nargs, args, used);
-  if (!i)
-    rehash_size = DEFAULT_REHASH_SIZE;
-  else if (FIXNUMP (args[i]) && 0 < XFIXNUM (args[i]))
-    rehash_size = - XFIXNUM (args[i]);
-  else if (FLOATP (args[i]) && 0 < (float) (XFLOAT_DATA (args[i]) - 1))
-    rehash_size = (float) (XFLOAT_DATA (args[i]) - 1);
-  else
-    signal_error ("Invalid hash table rehash size", args[i]);
-
-  /* Look for `:rehash-threshold THRESHOLD'.  */
-  i = get_key_arg (QCrehash_threshold, nargs, args, used);
-  float rehash_threshold = (!i ? DEFAULT_REHASH_THRESHOLD
-                           : !FLOATP (args[i]) ? 0
-                           : (float) XFLOAT_DATA (args[i]));
-  if (! (0 < rehash_threshold && rehash_threshold <= 1))
-    signal_error ("Invalid hash table rehash threshold", args[i]);
-
   /* Look for `:weakness WEAK'.  */
   i = get_key_arg (QCweakness, nargs, args, used);
-  weak = i ? args[i] : Qnil;
-  if (EQ (weak, Qt))
-    weak = Qkey_and_value;
-  if (!NILP (weak)
-      && !EQ (weak, Qkey)
-      && !EQ (weak, Qvalue)
-      && !EQ (weak, Qkey_or_value)
-      && !EQ (weak, Qkey_and_value))
-    signal_error ("Invalid hash table weakness", weak);
+  Lisp_Object weakness = i ? args[i] : Qnil;
+  hash_table_weakness_t weak;
+  if (NILP (weakness))
+    weak = Weak_None;
+  else if (EQ (weakness, Qkey))
+    weak = Weak_Key;
+  else if (EQ (weakness, Qvalue))
+    weak = Weak_Value;
+  else if (EQ (weakness, Qkey_or_value))
+    weak = Weak_Key_Or_Value;
+  else if (EQ (weakness, Qt) || EQ (weakness, Qkey_and_value))
+    weak = Weak_Key_And_Value;
+  else
+    signal_error ("Invalid hash table weakness", weakness);
 
   /* Now, all args should have been used up, or there's a problem.  */
   for (i = 0; i < nargs; ++i)
     if (!used[i])
-      signal_error ("Invalid argument list", args[i]);
+      {
+       /* Ignore obsolete arguments.  */
+       if (EQ (args[i], QCrehash_threshold) || EQ (args[i], QCrehash_size))
+         i++;
+       else
+         signal_error ("Invalid argument list", args[i]);
+      }
 
   SAFE_FREE ();
-  return make_hash_table (testdesc, size, rehash_size, rehash_threshold, weak,
-                         purecopy);
+  return make_hash_table (testdesc, size, weak, purecopy);
 }
 
 
@@ -5410,34 +5526,37 @@ DEFUN ("hash-table-count", Fhash_table_count, 
Shash_table_count, 1, 1, 0,
 
 DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size,
        Shash_table_rehash_size, 1, 1, 0,
-       doc: /* Return the current rehash size of TABLE.  */)
+       doc: /* Return the rehash size of TABLE.
+This function is for compatibility only; it returns a nominal value
+without current significance.  */)
   (Lisp_Object table)
 {
-  double rehash_size = check_hash_table (table)->rehash_size;
-  if (rehash_size < 0)
-    {
-      EMACS_INT s = -rehash_size;
-      return make_fixnum (min (s, MOST_POSITIVE_FIXNUM));
-    }
-  else
-    return make_float (rehash_size + 1);
+  CHECK_HASH_TABLE (table);
+  return make_float (1.5);  /* The old default rehash-size value.  */
 }
 
 
 DEFUN ("hash-table-rehash-threshold", Fhash_table_rehash_threshold,
        Shash_table_rehash_threshold, 1, 1, 0,
-       doc: /* Return the current rehash threshold of TABLE.  */)
+       doc: /* Return the rehash threshold of TABLE.
+This function is for compatibility only; it returns a nominal value
+without current significance.  */)
   (Lisp_Object table)
 {
-  return make_float (check_hash_table (table)->rehash_threshold);
+  CHECK_HASH_TABLE (table);
+  return make_float (0.8125);  /* The old default rehash-threshold value.  */
 }
 
 
 DEFUN ("hash-table-size", Fhash_table_size, Shash_table_size, 1, 1, 0,
-       doc: /* Return the size of TABLE.
-The size can be used as an argument to `make-hash-table' to create
-a hash table than can hold as many elements as TABLE holds
-without need for resizing.  */)
+       doc: /* Return the current allocation size of TABLE.
+
+This is probably not the function that you are looking for.  To get the
+number of entries in a table, use `hash-table-count' instead.
+
+The returned value is the number of entries that TABLE can currently
+hold without growing, but since hash tables grow automatically, this
+number is rarely of interest.  */)
   (Lisp_Object table)
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
@@ -5449,16 +5568,29 @@ DEFUN ("hash-table-test", Fhash_table_test, 
Shash_table_test, 1, 1, 0,
        doc: /* Return the test TABLE uses.  */)
   (Lisp_Object table)
 {
-  return check_hash_table (table)->test.name;
+  return check_hash_table (table)->test->name;
 }
 
+Lisp_Object
+hash_table_weakness_symbol (hash_table_weakness_t weak)
+{
+  switch (weak)
+    {
+    case Weak_None:          return Qnil;
+    case Weak_Key:           return Qkey;
+    case Weak_Value:         return Qvalue;
+    case Weak_Key_And_Value: return Qkey_and_value;
+    case Weak_Key_Or_Value:  return Qkey_or_value;
+    }
+  emacs_abort ();
+}
 
 DEFUN ("hash-table-weakness", Fhash_table_weakness, Shash_table_weakness,
        1, 1, 0,
        doc: /* Return the weakness of TABLE.  */)
   (Lisp_Object table)
 {
-  return check_hash_table (table)->weak;
+  return hash_table_weakness_symbol (check_hash_table (table)->weakness);
 }
 
 
@@ -5491,7 +5623,7 @@ If KEY is not found, return DFLT which defaults to nil.  
*/)
   if (symbols_with_pos_enabled
       && Fsymbol_with_pos_p (key))
     key = Fbare_symbol (key);
-  ptrdiff_t i = hash_lookup (h, key, NULL);
+  ptrdiff_t i = hash_lookup (h, key);
   return i >= 0 ? HASH_VALUE (h, i) : dflt;
 }
 
@@ -5508,8 +5640,9 @@ VALUE.  In any case, return VALUE.  */)
   if (symbols_with_pos_enabled
       && Fsymbol_with_pos_p (key))
     key = Fbare_symbol (key);
-  Lisp_Object hash;
-  ptrdiff_t i = hash_lookup (h, key, &hash);
+
+  EMACS_UINT hash = hash_from_key (h, key);
+  ptrdiff_t i = hash_lookup_with_hash (h, key, hash);
   if (i >= 0)
     set_hash_value_slot (h, i, value);
   else
@@ -5533,18 +5666,17 @@ DEFUN ("remhash", Fremhash, Sremhash, 2, 2, 0,
 DEFUN ("maphash", Fmaphash, Smaphash, 2, 2, 0,
        doc: /* Call FUNCTION for all entries in hash table TABLE.
 FUNCTION is called with two arguments, KEY and VALUE.
+It should not alter TABLE in any way other than using `puthash' to
+set a new value for KEY, or `remhash' to remove KEY.
 `maphash' always returns nil.  */)
   (Lisp_Object function, Lisp_Object table)
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
-
-  for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
-    {
-      Lisp_Object k = HASH_KEY (h, i);
-      if (!BASE_EQ (k, Qunbound))
-        call2 (function, k, HASH_VALUE (h, i));
-    }
-
+  /* We can't use DOHASH here since FUNCTION may violate the rules and
+     we shouldn't crash as a result (although the effects are
+     unpredictable).  */
+  DOHASH_SAFE (h, i)
+    call2 (function, HASH_KEY (h, i), HASH_VALUE (h, i));
   return Qnil;
 }
 
@@ -5566,6 +5698,67 @@ returns nil, then (funcall TEST x1 x2) also returns nil. 
 */)
   return Fput (name, Qhash_table_test, list2 (test, hash));
 }
 
+DEFUN ("internal--hash-table-histogram",
+       Finternal__hash_table_histogram,
+       Sinternal__hash_table_histogram,
+       1, 1, 0,
+       doc: /* Bucket size histogram of HASH-TABLE.  Internal use only. */)
+  (Lisp_Object hash_table)
+{
+  struct Lisp_Hash_Table *h = check_hash_table (hash_table);
+  ptrdiff_t size = HASH_TABLE_SIZE (h);
+  ptrdiff_t *freq = xzalloc (size * sizeof *freq);
+  ptrdiff_t index_size = h->index_size;
+  for (ptrdiff_t i = 0; i < index_size; i++)
+    {
+      ptrdiff_t n = 0;
+      for (ptrdiff_t j = HASH_INDEX (h, i); j != -1; j = HASH_NEXT (h, j))
+       n++;
+      if (n > 0)
+       freq[n - 1]++;
+    }
+  Lisp_Object ret = Qnil;
+  for (ptrdiff_t i = 0; i < size; i++)
+    if (freq[i] > 0)
+      ret = Fcons (Fcons (make_int (i + 1), make_int (freq[i])),
+                  ret);
+  xfree (freq);
+  return Fnreverse (ret);
+}
+
+DEFUN ("internal--hash-table-buckets",
+       Finternal__hash_table_buckets,
+       Sinternal__hash_table_buckets,
+       1, 1, 0,
+       doc: /* (KEY . HASH) in HASH-TABLE, grouped by bucket.
+Internal use only. */)
+  (Lisp_Object hash_table)
+{
+  struct Lisp_Hash_Table *h = check_hash_table (hash_table);
+  Lisp_Object ret = Qnil;
+  ptrdiff_t index_size = h->index_size;
+  for (ptrdiff_t i = 0; i < index_size; i++)
+    {
+      Lisp_Object bucket = Qnil;
+      for (ptrdiff_t j = HASH_INDEX (h, i); j != -1; j = HASH_NEXT (h, j))
+       bucket = Fcons (Fcons (HASH_KEY (h, j), make_int (HASH_HASH (h, j))),
+                       bucket);
+      if (!NILP (bucket))
+       ret = Fcons (Fnreverse (bucket), ret);
+    }
+  return Fnreverse (ret);
+}
+
+DEFUN ("internal--hash-table-index-size",
+       Finternal__hash_table_index_size,
+       Sinternal__hash_table_index_size,
+       1, 1, 0,
+       doc: /* Index size of HASH-TABLE.  Internal use only. */)
+  (Lisp_Object hash_table)
+{
+  struct Lisp_Hash_Table *h = check_hash_table (hash_table);
+  return make_int (h->index_size);
+}
 
 
 /************************************************************************
@@ -6148,7 +6341,6 @@ Altering this copy does not change the layout of the text 
properties
 in OBJECT.  */)
   (register Lisp_Object object)
 {
-  Lisp_Object collector = Fcons (Qnil, Qnil);
   INTERVAL intervals;
 
   if (STRINGP (object))
@@ -6161,8 +6353,9 @@ in OBJECT.  */)
   if (! intervals)
     return Qnil;
 
-  traverse_intervals (intervals, 0, collect_interval, collector);
-  return CDR (collector);
+  Lisp_Object collector = Qnil;
+  traverse_intervals (intervals, 0, collect_interval, &collector);
+  return Fnreverse (collector);
 }
 
 DEFUN ("line-number-at-pos", Fline_number_at_pos,
@@ -6256,6 +6449,9 @@ syms_of_fns (void)
   defsubr (&Sremhash);
   defsubr (&Smaphash);
   defsubr (&Sdefine_hash_table_test);
+  defsubr (&Sinternal__hash_table_histogram);
+  defsubr (&Sinternal__hash_table_buckets);
+  defsubr (&Sinternal__hash_table_index_size);
   defsubr (&Sstring_search);
   defsubr (&Sobject_intervals);
   defsubr (&Sline_number_at_pos);
@@ -6343,7 +6539,7 @@ The same variable also affects the function 
`read-answer'.  See also
   DEFVAR_LISP ("yes-or-no-prompt", Vyes_or_no_prompt,
     doc: /* String to append when `yes-or-no-p' asks a question.
 For best results this should end in a space.  */);
-  Vyes_or_no_prompt = make_unibyte_string ("(yes or no) ", strlen ("(yes or 
no) "));
+  Vyes_or_no_prompt = build_unibyte_string ("(yes or no) ");
 
   defsubr (&Sidentity);
   defsubr (&Srandom);
diff --git a/src/font.c b/src/font.c
index d9367929467..0a0ac5f8030 100644
--- a/src/font.c
+++ b/src/font.c
@@ -1,6 +1,6 @@
 /* font.c -- "Font" primitives.
 
-Copyright (C) 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 2006-2024 Free Software Foundation, Inc.
 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
   National Institute of Advanced Industrial Science and Technology (AIST)
   Registration Number H13PRO009
diff --git a/src/font.h b/src/font.h
index 9c9f7952560..8ee1940be0a 100644
--- a/src/font.h
+++ b/src/font.h
@@ -1,5 +1,5 @@
 /* font.h -- Interface definition for font handling.
-   Copyright (C) 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006-2024 Free Software Foundation, Inc.
    Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H13PRO009
@@ -191,16 +191,16 @@ enum font_property_index
 
 /* Return the numeric weight value of FONT.  */
 #define FONT_WEIGHT_NUMERIC(font)              \
-  (FIXNUMP (AREF ((font), FONT_WEIGHT_INDEX))  \
-   ? (XFIXNUM (AREF ((font), FONT_WEIGHT_INDEX)) >> 8) : -1)
+  (FIXNUMP (AREF (font, FONT_WEIGHT_INDEX))    \
+   ? (XFIXNUM (AREF (font, FONT_WEIGHT_INDEX)) >> 8) : -1)
 /* Return the numeric slant value of FONT.  */
 #define FONT_SLANT_NUMERIC(font)               \
-  (FIXNUMP (AREF ((font), FONT_SLANT_INDEX))   \
-   ? (XFIXNUM (AREF ((font), FONT_SLANT_INDEX)) >> 8) : -1)
+  (FIXNUMP (AREF (font, FONT_SLANT_INDEX))     \
+   ? (XFIXNUM (AREF (font, FONT_SLANT_INDEX)) >> 8) : -1)
 /* Return the numeric width value of FONT.  */
 #define FONT_WIDTH_NUMERIC(font)               \
-  (FIXNUMP (AREF ((font), FONT_WIDTH_INDEX))   \
-   ? (XFIXNUM (AREF ((font), FONT_WIDTH_INDEX)) >> 8) : -1)
+  (FIXNUMP (AREF (font, FONT_WIDTH_INDEX))     \
+   ? (XFIXNUM (AREF (font, FONT_WIDTH_INDEX)) >> 8) : -1)
 /* Return the symbolic weight value of FONT.  */
 #define FONT_WEIGHT_SYMBOLIC(font)     \
   font_style_symbolic (font, FONT_WEIGHT_INDEX, false)
@@ -222,19 +222,19 @@ enum font_property_index
 
 /* Return the numeric weight value corresponding to the symbol NAME.  */
 #define FONT_WEIGHT_NAME_NUMERIC(name) \
-  (font_style_to_value (FONT_WEIGHT_INDEX, (name), false) >> 8)
+  (font_style_to_value (FONT_WEIGHT_INDEX, name, false) >> 8)
 /* Return the numeric slant value corresponding to the symbol NAME.  */
 #define FONT_SLANT_NAME_NUMERIC(name)  \
-  (font_style_to_value (FONT_SLANT_INDEX, (name), false) >> 8)
+  (font_style_to_value (FONT_SLANT_INDEX, name, false) >> 8)
 /* Return the numeric width value corresponding to the symbol NAME.  */
 #define FONT_WIDTH_NAME_NUMERIC(name)  \
-  (font_style_to_value (FONT_WIDTH_INDEX, (name), false) >> 8)
+  (font_style_to_value (FONT_WIDTH_INDEX, name, false) >> 8)
 
 /* Set the font property PROP of FONT to VAL.  PROP is one of
    style-related font property index (FONT_WEIGHT/SLANT/WIDTH_INDEX).
    VAL (integer or symbol) is the numeric or symbolic style value.  */
 #define FONT_SET_STYLE(font, prop, val)        \
-  ASET ((font), prop, make_fixnum (font_style_to_value (prop, val, true)))
+  ASET (font, prop, make_fixnum (font_style_to_value (prop, val, true)))
 
 #ifndef MSDOS
 #define FONT_WIDTH(f) ((f)->max_width)
@@ -549,7 +549,7 @@ GC_XFONT_OBJECT (Lisp_Object p)
   return XUNTAG (p, Lisp_Vectorlike, struct font);
 }
 
-#define XSETFONT(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_FONT))
+#define XSETFONT(a, b) XSETPSEUDOVECTOR (a, b, PVEC_FONT)
 
 INLINE struct font *
 CHECK_FONT_GET_OBJECT (Lisp_Object x)
@@ -1004,13 +1004,13 @@ extern void font_deferred_log (const char *, 
Lisp_Object, Lisp_Object);
 #define FONT_ADD_LOG(ACTION, ARG, RESULT)      \
   do {                                         \
     if (! EQ (Vfont_log, Qt))                  \
-      font_add_log ((ACTION), (ARG), (RESULT));        \
+      font_add_log (ACTION, ARG, RESULT);      \
   } while (false)
 
 #define FONT_DEFERRED_LOG(ACTION, ARG, RESULT)         \
   do {                                                 \
     if (! EQ (Vfont_log, Qt))                          \
-      font_deferred_log ((ACTION), (ARG), (RESULT));   \
+      font_deferred_log (ACTION, ARG, RESULT);         \
   } while (false)
 
 /* FIXME: This is for use in functions that can be called while
diff --git a/src/fontset.c b/src/fontset.c
index 54d1347f54f..d27fa22015e 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -1,6 +1,6 @@
 /* Fontset handler.
 
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
   2005, 2006, 2007, 2008, 2009, 2010, 2011
   National Institute of Advanced Industrial Science and Technology (AIST)
@@ -266,19 +266,19 @@ font_def_new (Lisp_Object font_spec, Lisp_Object encoding,
 
 #define RFONT_DEF_FACE(rfont_def) AREF (rfont_def, 0)
 #define RFONT_DEF_SET_FACE(rfont_def, face_id) \
-  ASET ((rfont_def), 0, make_fixnum (face_id))
+  ASET (rfont_def, 0, make_fixnum (face_id))
 #define RFONT_DEF_FONT_DEF(rfont_def) AREF (rfont_def, 1)
 #define RFONT_DEF_SPEC(rfont_def) FONT_DEF_SPEC (AREF (rfont_def, 1))
 #define RFONT_DEF_OBJECT(rfont_def) AREF (rfont_def, 2)
 #define RFONT_DEF_SET_OBJECT(rfont_def, object)        \
-  ASET ((rfont_def), 2, (object))
+  ASET (rfont_def, 2, object)
 /* Score of RFONT_DEF is an integer value; the lowest 8 bits represent
    the order of listing by font backends, the higher bits represents
    the order given by charset priority list.  The smaller value is
    preferable.  */
 #define RFONT_DEF_SCORE(rfont_def) XFIXNUM (AREF (rfont_def, 3))
 #define RFONT_DEF_SET_SCORE(rfont_def, score) \
-  ASET ((rfont_def), 3, make_fixnum (score))
+  ASET (rfont_def, 3, make_fixnum (score))
 #define RFONT_DEF_NEW(rfont_def, font_def)             \
   do {                                                 \
     (rfont_def) = make_nil_vector (4);                 \
@@ -295,7 +295,7 @@ font_def_new (Lisp_Object font_spec, Lisp_Object encoding,
 #define FONTSET_REF(fontset, c)                \
   (EQ (fontset, Vdefault_fontset)      \
    ? CHAR_TABLE_REF (fontset, c)       \
-   : fontset_ref ((fontset), (c)))
+   : fontset_ref (fontset, c))
 
 static Lisp_Object
 fontset_ref (Lisp_Object fontset, int c)
@@ -315,7 +315,7 @@ fontset_ref (Lisp_Object fontset, int c)
    specifying a range.  */
 
 #define FONTSET_SET(fontset, range, elt)       \
-  Fset_char_table_range ((fontset), (range), (elt))
+  Fset_char_table_range (fontset, range, elt)
 
 
 /* Modify the elements of FONTSET for characters in RANGE by replacing
@@ -329,7 +329,7 @@ fontset_ref (Lisp_Object fontset, int c)
    ? (NILP (range)                                                     \
       ? set_fontset_fallback (fontset, make_vector (1, elt))           \
       : (void) Fset_char_table_range (fontset, range, make_vector (1, elt))) \
-   : fontset_add ((fontset), (range), (elt), (add)))
+   : fontset_add (fontset, range, elt, add))
 
 static void
 fontset_add (Lisp_Object fontset, Lisp_Object range, Lisp_Object elt, 
Lisp_Object add)
diff --git a/src/fontset.h b/src/fontset.h
index de19138947d..62e5655ab1a 100644
--- a/src/fontset.h
+++ b/src/fontset.h
@@ -1,5 +1,5 @@
 /* Header for fontset handler.
-   Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
      2005, 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/src/frame.c b/src/frame.c
index 38ac316ce87..abd6ef00901 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1,6 +1,6 @@
 /* Generic frame functions.
 
-Copyright (C) 1993-1995, 1997, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1995, 1997, 1999-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -1040,8 +1040,7 @@ make_frame (bool mini_p)
   rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f);
 
   fset_face_hash_table
-    (f, make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE, DEFAULT_REHASH_SIZE,
-                         DEFAULT_REHASH_THRESHOLD, Qnil, false));
+    (f, make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None, false));
 
   if (mini_p)
     {
@@ -2149,7 +2148,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
       x_clipboard_manager_save_frame (frame);
 #endif
 
-      safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
+      safe_calln (Qrun_hook_with_args, Qdelete_frame_functions, frame);
     }
 
   /* delete_frame_functions may have deleted any frame, including this
@@ -2461,7 +2460,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
       = Fcons (list3 (Qrun_hook_with_args, Qafter_delete_frame_functions, 
frame),
               pending_funcalls);
   else
-    safe_call2 (Qrun_hook_with_args, Qafter_delete_frame_functions, frame);
+    safe_calln (Qrun_hook_with_args, Qafter_delete_frame_functions, frame);
 
   if (!NILP (minibuffer_child_frame))
     /* If minibuffer_child_frame is non-nil, it was FRAME's minibuffer
diff --git a/src/frame.h b/src/frame.h
index d826ae56e8b..e03362361a7 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1,5 +1,5 @@
 /* Define frame-object for GNU Emacs.
-   Copyright (C) 1993-1994, 1999-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993-1994, 1999-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -909,7 +909,7 @@ default_pixels_per_inch_y (void)
 
 #define XFRAME(p) \
   (eassert (FRAMEP (p)), XUNTAG (p, Lisp_Vectorlike, struct frame))
-#define XSETFRAME(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_FRAME))
+#define XSETFRAME(a, b) XSETPSEUDOVECTOR (a, b, PVEC_FRAME)
 
 /* Given a window, return its frame as a Lisp_Object.  */
 #define WINDOW_FRAME(w) ((w)->frame)
@@ -992,7 +992,7 @@ default_pixels_per_inch_y (void)
    FRAME_DISPLAY_INFO (f)->font_resolution)
 
 #else /* !HAVE_ANDROID */
-#define FRAME_RES(f) (FRAME_RES_Y (f))
+#define FRAME_RES(f) FRAME_RES_Y (f)
 #endif /* HAVE_ANDROID */
 
 #else /* !HAVE_WINDOW_SYSTEM */
@@ -1130,12 +1130,12 @@ default_pixels_per_inch_y (void)
 /* Height of F's bottom margin in frame lines.  */
 
 #define FRAME_BOTTOM_MARGIN(f)                 \
-  (FRAME_TOOL_BAR_BOTTOM_LINES (f))
+  FRAME_TOOL_BAR_BOTTOM_LINES (f)
 
 /* Pixel height of frame F's bottom margin.  */
 
 #define FRAME_BOTTOM_MARGIN_HEIGHT(f)          \
-  (FRAME_TOOL_BAR_BOTTOM_HEIGHT (f))
+  FRAME_TOOL_BAR_BOTTOM_HEIGHT (f)
 
 /* Size of both vertical margins combined.  */
 
@@ -1159,7 +1159,7 @@ default_pixels_per_inch_y (void)
    visible by the X server.  */
 
 #ifndef HAVE_X_WINDOWS
-#define FRAME_REDISPLAY_P(f) (FRAME_VISIBLE_P (f))
+#define FRAME_REDISPLAY_P(f) FRAME_VISIBLE_P (f)
 #else
 #define FRAME_REDISPLAY_P(f) (FRAME_VISIBLE_P (f)              \
                              || (FRAME_X_P (f)                 \
diff --git a/src/fringe.c b/src/fringe.c
index 3452c8503f0..0642de5f772 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -1,5 +1,5 @@
 /* Fringe handling (split from xdisp.c).
-   Copyright (C) 1985-1988, 1993-1995, 1997-2023 Free Software
+   Copyright (C) 1985-1988, 1993-1995, 1997-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 49564692b75..5ee375c782b 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -1,5 +1,5 @@
 /* ftcrfont.c -- FreeType font driver on cairo.
-   Copyright (C) 2015-2023 Free Software Foundation, Inc.
+   Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/ftfont.c b/src/ftfont.c
index d3c836c0f2d..0d10de5408f 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -1,5 +1,5 @@
 /* ftfont.c -- FreeType font driver.
-   Copyright (C) 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006-2024 Free Software Foundation, Inc.
    Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H13PRO009
@@ -1572,6 +1572,12 @@ ftfont_glyph_metrics (FT_Face ft_face, int c, int 
*advance, int *lbearing,
   if (FT_Load_Glyph (ft_face, c, FT_LOAD_DEFAULT) == 0)
     {
       FT_Glyph_Metrics *m = &ft_face->glyph->metrics;
+
+      /* At first glance this might appear to truncate the glyph's
+        horizontal advance, but FreeType internally rounds the
+        advance width to a pixel boundary prior to returning these
+        metrics.  */
+
       *advance = m->horiAdvance >> 6;
       *lbearing = m->horiBearingX >> 6;
       *rbearing = (m->horiBearingX + m->width) >> 6;
diff --git a/src/getpagesize.h b/src/getpagesize.h
index 692c9066fb1..d1fb9315f3a 100644
--- a/src/getpagesize.h
+++ b/src/getpagesize.h
@@ -1,5 +1,5 @@
 /* Emulate getpagesize on systems that lack it.
-   Copyright (C) 1986, 1992, 1995, 2001-2023 Free Software Foundation,
+   Copyright (C) 1986, 1992, 1995, 2001-2024 Free Software Foundation,
    Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/gfilenotify.c b/src/gfilenotify.c
index 3dd6390db10..8733db11997 100644
--- a/src/gfilenotify.c
+++ b/src/gfilenotify.c
@@ -1,5 +1,5 @@
 /* Filesystem notifications support with glib API.
-   Copyright (C) 2013-2023 Free Software Foundation, Inc.
+   Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/gmalloc.c b/src/gmalloc.c
index e655d69f660..2b29f5c6c81 100644
--- a/src/gmalloc.c
+++ b/src/gmalloc.c
@@ -1,5 +1,5 @@
 /* Declarations for `malloc' and friends.
-   Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2023 Free
+   Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2024 Free
    Software Foundation, Inc.
                  Written May 1989 by Mike Haertel.
 
diff --git a/src/gnutls.c b/src/gnutls.c
index e3f1093d977..54b7eb4c90e 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -1,5 +1,5 @@
 /* GnuTLS glue for GNU Emacs.
-   Copyright (C) 2010-2023 Free Software Foundation, Inc.
+   Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/gnutls.h b/src/gnutls.h
index 16bfebadee5..18e06027c37 100644
--- a/src/gnutls.h
+++ b/src/gnutls.h
@@ -1,5 +1,5 @@
 /* GnuTLS glue for GNU Emacs.
-   Copyright (C) 2010-2023 Free Software Foundation, Inc.
+   Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/gtkutil.c b/src/gtkutil.c
index f9d9a22a06b..c067f7b53ac 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1,6 +1,6 @@
 /* Functions for creating and updating GTK widgets.
 
-Copyright (C) 2003-2023 Free Software Foundation, Inc.
+Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -117,10 +117,10 @@ static void xg_widget_style_updated (GtkWidget *, 
gpointer);
 
 #define gtk_box_new(ori, spacing)                                       \
   ((ori) == GTK_ORIENTATION_HORIZONTAL                                  \
-   ? gtk_hbox_new (FALSE, (spacing)) : gtk_vbox_new (FALSE, (spacing)))
+   ? gtk_hbox_new (FALSE, spacing) : gtk_vbox_new (FALSE, spacing))
 #define gtk_scrollbar_new(ori, spacing)                                 \
   ((ori) == GTK_ORIENTATION_HORIZONTAL                                  \
-   ? gtk_hscrollbar_new ((spacing)) : gtk_vscrollbar_new ((spacing)))
+   ? gtk_hscrollbar_new (spacing) : gtk_vscrollbar_new (spacing))
 #endif /* HAVE_GTK3 */
 
 #define XG_BIN_CHILD(x) gtk_bin_get_child (GTK_BIN (x))
diff --git a/src/gtkutil.h b/src/gtkutil.h
index acd6a3bfc8e..b689053b4b8 100644
--- a/src/gtkutil.h
+++ b/src/gtkutil.h
@@ -1,6 +1,6 @@
 /* Definitions and headers for GTK widgets.
 
-Copyright (C) 2003-2023 Free Software Foundation, Inc.
+Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haiku.c b/src/haiku.c
index 55c2cf04729..002dfe0c4f5 100644
--- a/src/haiku.c
+++ b/src/haiku.c
@@ -1,5 +1,5 @@
 /* Haiku subroutines that are general to the Haiku operating system.
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haiku_draw_support.cc b/src/haiku_draw_support.cc
index b779b773dd5..1671eba96d0 100644
--- a/src/haiku_draw_support.cc
+++ b/src/haiku_draw_support.cc
@@ -1,5 +1,5 @@
 /* Haiku window system support.  Hey, Emacs, this is -*- C++ -*-
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haiku_font_support.cc b/src/haiku_font_support.cc
index 1403c06a614..416a7d90c29 100644
--- a/src/haiku_font_support.cc
+++ b/src/haiku_font_support.cc
@@ -1,5 +1,5 @@
 /* Haiku window system support.  Hey, Emacs, this is -*- C++ -*-
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haiku_io.c b/src/haiku_io.c
index c6d7108bf49..f0862965bd8 100644
--- a/src/haiku_io.c
+++ b/src/haiku_io.c
@@ -1,5 +1,5 @@
 /* Haiku window system support.
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haiku_select.cc b/src/haiku_select.cc
index 76e2d829204..f497eb3d24b 100644
--- a/src/haiku_select.cc
+++ b/src/haiku_select.cc
@@ -1,5 +1,5 @@
 /* Haiku window system selection support. Hey Emacs, this is -*- C++ -*-
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -18,6 +18,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <intprops.h>
+#include <stdckdint.h>
 
 #include <Application.h>
 #include <Bitmap.h>
@@ -619,8 +620,7 @@ be_display_notification (const char *title, const char 
*body,
       /* SUPERSEDES hasn't been provided, so allocate a new
         notification ID.  */
 
-      INT_ADD_WRAPV (last_notification_id, 1,
-                    &last_notification_id);
+      ckd_add (&last_notification_id, last_notification_id, 1);
       id = last_notification_id;
     }
   else
diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index 33ad5889043..1b9c5acdf14 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -1,5 +1,5 @@
 /* Haiku window system support.  Hey, Emacs, this is -*- C++ -*-
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haiku_support.h b/src/haiku_support.h
index 5c22eb3b0db..e9ac7005d75 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -1,5 +1,5 @@
 /* Haiku window system support.  Hey Emacs, this is -*- C++ -*-
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haikufns.c b/src/haikufns.c
index e6b1f618d5b..173c1e369df 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -1,5 +1,5 @@
 /* Haiku window system support
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haikufont.c b/src/haikufont.c
index c67502d3600..5d14dab3d4b 100644
--- a/src/haikufont.c
+++ b/src/haikufont.c
@@ -1,6 +1,6 @@
 /* Font support for Haiku windowing
 
-Copyright (C) 2021-2023 Free Software Foundation, Inc.
+Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haikugui.h b/src/haikugui.h
index 8b144cc5e1d..7b90435f664 100644
--- a/src/haikugui.h
+++ b/src/haikugui.h
@@ -1,5 +1,5 @@
 /* Haiku window system support
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haikuimage.c b/src/haikuimage.c
index 78c6732d94f..b54337703d0 100644
--- a/src/haikuimage.c
+++ b/src/haikuimage.c
@@ -1,5 +1,5 @@
 /* Haiku window system support.
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haikumenu.c b/src/haikumenu.c
index fab58946568..2e00b1803ae 100644
--- a/src/haikumenu.c
+++ b/src/haikumenu.c
@@ -1,5 +1,5 @@
 /* Haiku window system support
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haikuselect.c b/src/haikuselect.c
index 608b8e8fe30..9a178acf618 100644
--- a/src/haikuselect.c
+++ b/src/haikuselect.c
@@ -1,5 +1,5 @@
 /* Haiku window system selection support.
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -1189,7 +1189,7 @@ haiku_note_drag_wheel (struct input_event *ie)
   if (!NILP (Vhaiku_drag_wheel_function)
       && (haiku_dnd_allow_same_frame
          || XFRAME (ie->frame_or_window) != haiku_dnd_frame))
-    safe_call (7, Vhaiku_drag_wheel_function, ie->frame_or_window,
+    safe_calln (Vhaiku_drag_wheel_function, ie->frame_or_window,
               ie->x, ie->y, horizontal ? Qt : Qnil, up ? Qt : Qnil,
               make_int (ie->modifiers));
 
diff --git a/src/haikuselect.h b/src/haikuselect.h
index c117a2ab4f9..76c637b569a 100644
--- a/src/haikuselect.h
+++ b/src/haikuselect.h
@@ -1,5 +1,5 @@
 /* Haiku window system selection support. Hey Emacs, this is -*- C++ -*-
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haikuterm.c b/src/haikuterm.c
index bcb5055ea42..135f99dbdcb 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -1,5 +1,5 @@
 /* Haiku window system support
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/haikuterm.h b/src/haikuterm.h
index 4d8d2678e82..75c4bf0d6ef 100644
--- a/src/haikuterm.h
+++ b/src/haikuterm.h
@@ -1,5 +1,5 @@
 /* Haiku window system support
-   Copyright (C) 2021-2023 Free Software Foundation, Inc.
+   Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/hbfont.c b/src/hbfont.c
index 86ba9eea1ac..40bb44c7d04 100644
--- a/src/hbfont.c
+++ b/src/hbfont.c
@@ -1,5 +1,5 @@
 /* hbfont.c -- Platform-independent support for HarfBuzz font driver.
-   Copyright (C) 2019-2023 Free Software Foundation, Inc.
+   Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/image.c b/src/image.c
index 9c0f5f0fb37..41d72964631 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1,6 +1,6 @@
 /* Functions for image support on window system.
 
-Copyright (C) 1989-2023 Free Software Foundation, Inc.
+Copyright (C) 1989-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -1543,7 +1543,7 @@ parse_image_spec (Lisp_Object spec, struct image_keyword 
*keywords,
    if KEY is not present in SPEC.  Set *FOUND depending on whether KEY
    was found in SPEC.  */
 
-static Lisp_Object
+Lisp_Object
 image_spec_value (Lisp_Object spec, Lisp_Object key, bool *found)
 {
   Lisp_Object tail;
@@ -3561,7 +3561,7 @@ anim_prune_animation_cache (Lisp_Object clear)
     {
       struct anim_cache *cache = *pcache;
       if (EQ (clear, Qt)
-         || (EQ (clear, Qnil) && timespec_cmp (old, cache->update_time) > 0)
+         || (NILP (clear) && timespec_cmp (old, cache->update_time) > 0)
          || EQ (clear, cache->spec))
        {
          if (cache->handle)
@@ -4373,7 +4373,7 @@ slurp_image (Lisp_Object filename, ptrdiff_t *size, const 
char *image_type)
   char *result = slurp_file (fd, size);
   if (result == NULL)
     image_error ("Error loading %s image `%s'",
-                make_unibyte_string (image_type, strlen (image_type)),
+                build_unibyte_string (image_type),
                 file);
   return result;
 }
@@ -4875,7 +4875,7 @@ xbm_read_bitmap_data (struct frame *f, char *contents, 
char *end,
   while (0)
 
 #define expect_ident(IDENT)                                    \
-     if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
+     if (LA1 == XBM_TK_IDENT && strcmp (buffer, IDENT) == 0)   \
        match ();                                               \
      else                                                      \
        goto failure
@@ -6069,9 +6069,7 @@ xpm_make_color_table_h (void (**put_func) (Lisp_Object, 
const char *, int,
 {
   *put_func = xpm_put_color_table_h;
   *get_func = xpm_get_color_table_h;
-  return make_hash_table (hashtest_equal, DEFAULT_HASH_SIZE,
-                         DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
-                         Qnil, false);
+  return make_hash_table (&hashtest_equal, DEFAULT_HASH_SIZE, Weak_None, 
false);
 }
 
 static void
@@ -6081,9 +6079,10 @@ xpm_put_color_table_h (Lisp_Object color_table,
                        Lisp_Object color)
 {
   struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
-  Lisp_Object chars = make_unibyte_string (chars_start, chars_len), hash_code;
+  Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
 
-  hash_lookup (table, chars, &hash_code);
+  hash_hash_t hash_code;
+  hash_lookup_get_hash (table, chars, &hash_code);
   hash_put (table, chars, color, hash_code);
 }
 
@@ -6094,7 +6093,7 @@ xpm_get_color_table_h (Lisp_Object color_table,
 {
   struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
   ptrdiff_t i =
-    hash_lookup (table, make_unibyte_string (chars_start, chars_len), NULL);
+    hash_lookup (table, make_unibyte_string (chars_start, chars_len));
 
   return i >= 0 ? HASH_VALUE (table, i) : Qnil;
 }
@@ -6155,7 +6154,7 @@ xpm_load_image (struct frame *f,
 
 #define expect_ident(IDENT)                                    \
      if (LA1 == XPM_TK_IDENT \
-         && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0)        
\
+         && strlen (IDENT) == len && memcmp (IDENT, beg, len) == 0)    \
        match ();                                               \
      else                                                      \
        goto failure
@@ -11785,7 +11784,7 @@ svg_css_length_to_pixels (RsvgLength length, double 
dpi, int font_size)
 
         If we do set explicit width and height values in the image
         spec, this will work out correctly as librsvg will still
-        honour the percentage sizes in its final rendering no matter
+        honor the percentage sizes in its final rendering no matter
         what size we make the image.  */
       value = 0;
       break;
@@ -11804,7 +11803,17 @@ svg_css_length_to_pixels (RsvgLength length, double 
dpi, int font_size)
 
    Use librsvg to do most of the image processing.
 
-   Return true when successful.  */
+   Return true when successful.
+
+   The basic process, which is used for all versions of librsvg, is to
+   load the SVG and parse it, then extract the image dimensions.  We
+   then use those image dimensions to calculate the final size and
+   wrap the SVG data inside another SVG we build on the fly. This
+   wrapper does the necessary resizing and setting of foreground and
+   background colors and is then parsed and rasterized.
+
+   It should also be noted that setting up the SVG prior to 2.32 was
+   done differently, but the overall process is the same.  */
 static bool
 svg_load_image (struct frame *f, struct image *img, char *contents,
                ptrdiff_t size, char *filename)
@@ -11858,7 +11867,13 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
   Lisp_Object lcss = image_spec_value (img->spec, QCcss, NULL);
   if (!STRINGP (lcss))
     {
-      /* Generate the CSS for the SVG image.  */
+      /* Generate the CSS for the SVG image.
+
+         We use this to set the font (font-family in CSS lingo) and
+         the font size.  We can extend this to handle any CSS values
+         SVG supports, however it's only available in librsvg 2.48 and
+         above so some things we could set here are handled in the
+         wrapper below.  */
       /* FIXME: The below calculations leave enough space for a font
         size up to 9999, if it overflows we just throw an error but
         should probably increase the buffer size.  */
@@ -11904,7 +11919,23 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
   if (err) goto rsvg_error;
 #endif
 
-  /* Get the image dimensions.  */
+  /* Get the image dimensions.
+
+     There are a couple of approaches used here, depending on the
+     contents of the SVG, and which version of librsvg we're using.
+     With librsvg versions prior to 2.46 we ask librsvg for the size
+     of the image, however this may include pats of the image that are
+     outside of the viewbox.
+
+     librsvg 2.46 allows us to request the image's "intrinsic
+     dimensions", which are the sizes given in the SVG in CSS units.
+     So, for example, if the image defines it's width as "10mm", we
+     are given a struct that we need to translate into pixel values
+     ourself (see svg_css_length_to_pixels).
+
+     2.52 introduces a function that will give us the pixel sizes
+     directly, assuming we provide the correct screen DPI values.
+  */
 #if LIBRSVG_CHECK_VERSION (2, 46, 0)
   gdouble gviewbox_width = 0, gviewbox_height = 0;
   gboolean has_viewbox = FALSE;
@@ -12053,7 +12084,7 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
       }
 
 #if HAVE_NTGUI
-    /* Windows stores the image colours in BGR format, and SVG expects
+    /* Windows stores the image colors in BGR format, and SVG expects
        them in RGB.  */
     foreground = (foreground & 0x0000FF) << 16
       | (foreground & 0xFF0000) >> 16
@@ -12096,6 +12127,8 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
                            FRAME_DISPLAY_INFO (f)->resy);
 
 #if LIBRSVG_CHECK_VERSION (2, 48, 0)
+  /* Set the CSS for the wrapped SVG.  See the comment above the
+     previous use of 'css'.  */
   rsvg_handle_set_stylesheet (rsvg_handle, (guint8 *)css, strlen (css), NULL);
 #endif
 #else
diff --git a/src/indent.c b/src/indent.c
index 7d34d3638d9..3094a9d3089 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -1,5 +1,5 @@
 /* Indentation functions.
-   Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2023 Free Software
+   Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/indent.h b/src/indent.h
index 7bcecb3fdd5..5f8e7ecfd2c 100644
--- a/src/indent.h
+++ b/src/indent.h
@@ -1,5 +1,5 @@
 /* Definitions for interface to indent.c
-   Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/inotify.c b/src/inotify.c
index f50b9ddcaa7..2ee874530cc 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -1,6 +1,6 @@
 /* Inotify support for Emacs
 
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/insdel.c b/src/insdel.c
index b65a3fbd805..3809f8bc060 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -1,5 +1,5 @@
 /* Buffer insertion/deletion and gap motion for GNU Emacs. -*- coding: utf-8 
-*-
-   Copyright (C) 1985-1986, 1993-1995, 1997-2023 Free Software
+   Copyright (C) 1985-1986, 1993-1995, 1997-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -803,7 +803,7 @@ count_combining_before (const unsigned char *string, 
ptrdiff_t length,
   while (!CHAR_HEAD_P (*p) && p < string + length)
     p++;
 
-  return (combining_bytes < p - string ? combining_bytes : p - string);
+  return min (combining_bytes, p - string);
 }
 
 /* See if the bytes after POS/POS_BYTE combine with bytes
@@ -865,7 +865,7 @@ count_combining_after (const unsigned char *string,
   bufp++, pos_byte++;
   while (!CHAR_HEAD_P (*bufp)) bufp++, pos_byte++;
 
-  return (bytes <= pos_byte - opos_byte ? bytes : pos_byte - opos_byte);
+  return min (bytes, pos_byte - opos_byte);
 }
 
 #endif
@@ -1568,9 +1568,8 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object 
new,
 
   /* Relocate point as if it were a marker.  */
   if (from < PT)
-    adjust_point ((from + inschars - (PT < to ? PT : to)),
-                 (from_byte + outgoing_insbytes
-                  - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
+    adjust_point ((from + inschars - min (PT, to)),
+                 (from_byte + outgoing_insbytes - min (PT_BYTE, to_byte)));
 
   check_markers ();
 
@@ -1919,8 +1918,8 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
 
   /* Relocate point as if it were a marker.  */
   if (from < PT)
-    adjust_point (from - (PT < to ? PT : to),
-                 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
+    adjust_point (from - min (PT, to),
+                 from_byte - min (PT_BYTE, to_byte));
 
   offset_intervals (current_buffer, from, - nchars_del);
 
diff --git a/src/intervals.c b/src/intervals.c
index ee976fb1035..2ab19c2cc56 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -1,5 +1,5 @@
 /* Code for doing intervals.
-   Copyright (C) 1993-1995, 1997-1998, 2001-2023 Free Software
+   Copyright (C) 1993-1995, 1997-1998, 2001-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -256,7 +256,7 @@ traverse_intervals_noorder (INTERVAL tree, void (*function) 
(INTERVAL, void *),
 
 void
 traverse_intervals (INTERVAL tree, ptrdiff_t position,
-                   void (*function) (INTERVAL, Lisp_Object), Lisp_Object arg)
+                   void (*function) (INTERVAL, void *), void *arg)
 {
   while (tree)
     {
diff --git a/src/intervals.h b/src/intervals.h
index 8af92223773..610c803cc77 100644
--- a/src/intervals.h
+++ b/src/intervals.h
@@ -1,5 +1,5 @@
 /* Definitions and global variables for intervals.
-   Copyright (C) 1993-1994, 2000-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993-1994, 2000-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -245,8 +245,8 @@ extern INTERVAL create_root_interval (Lisp_Object);
 extern void copy_properties (INTERVAL, INTERVAL);
 extern bool intervals_equal (INTERVAL, INTERVAL);
 extern void traverse_intervals (INTERVAL, ptrdiff_t,
-                                void (*) (INTERVAL, Lisp_Object),
-                                Lisp_Object);
+                                void (*) (INTERVAL, void *),
+                                void *);
 extern void traverse_intervals_noorder (INTERVAL,
                                        void (*) (INTERVAL, void *), void *);
 extern INTERVAL split_interval_right (INTERVAL, ptrdiff_t)
diff --git a/src/itree.c b/src/itree.c
index 259cc99d3af..da51b3c61fd 100644
--- a/src/itree.c
+++ b/src/itree.c
@@ -1,6 +1,6 @@
 /* This file implements an efficient interval data-structure.
 
-Copyright (C) 2017-2023 Free Software Foundation, Inc.
+Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -74,7 +74,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 
    Consider the case where next-overlay-change is called at POS, all
    interval BEG positions are less than pos POS and all interval END
-   posistions are after.  These END positions have no order, and so
+   positions are after.  These END positions have no order, and so
    *every* interval must be examined.  This is at least O(N).  The
    previous-overlay-change case is similar.  The root issue is that
    the iterative "narrowing" approach is not guaranteed to reduce the
diff --git a/src/itree.h b/src/itree.h
index 79d03d31ce2..f54dbd7f07e 100644
--- a/src/itree.h
+++ b/src/itree.h
@@ -1,6 +1,6 @@
 /* This file implements an efficient interval data-structure.
 
-Copyright (C) 2017-2023 Free Software Foundation, Inc.
+Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/json.c b/src/json.c
index f7979fb446e..e849ccaf722 100644
--- a/src/json.c
+++ b/src/json.c
@@ -1,6 +1,6 @@
 /* JSON parsing and serialization.
 
-Copyright (C) 2017-2023 Free Software Foundation, Inc.
+Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -361,33 +361,29 @@ lisp_to_json_nonscalar_1 (Lisp_Object lisp,
       json = json_check (json_object ());
       count = SPECPDL_INDEX ();
       record_unwind_protect_ptr (json_release_object, json);
-      for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
+      DOHASH (h, key, v)
         {
-          Lisp_Object key = HASH_KEY (h, i);
-          if (!BASE_EQ (key, Qunbound))
-            {
-              CHECK_STRING (key);
-              Lisp_Object ekey = json_encode (key);
-              /* We can't specify the length, so the string must be
-                null-terminated.  */
-              check_string_without_embedded_nulls (ekey);
-              const char *key_str = SSDATA (ekey);
-              /* Reject duplicate keys.  These are possible if the hash
-                table test is not `equal'.  */
-              if (json_object_get (json, key_str) != NULL)
-                wrong_type_argument (Qjson_value_p, lisp);
-              int status
-                = json_object_set_new (json, key_str,
-                                       lisp_to_json (HASH_VALUE (h, i), conf));
-              if (status == -1)
-                {
-                  /* A failure can be caused either by an invalid key or
-                   by low memory.  */
-                  json_check_utf8 (ekey);
-                  json_out_of_memory ();
-                }
-            }
-        }
+         CHECK_STRING (key);
+         Lisp_Object ekey = json_encode (key);
+         /* We can't specify the length, so the string must be
+            null-terminated.  */
+         check_string_without_embedded_nulls (ekey);
+         const char *key_str = SSDATA (ekey);
+         /* Reject duplicate keys.  These are possible if the hash
+            table test is not `equal'.  */
+         if (json_object_get (json, key_str) != NULL)
+           wrong_type_argument (Qjson_value_p, lisp);
+         int status
+           = json_object_set_new (json, key_str,
+                                  lisp_to_json (v, conf));
+         if (status == -1)
+           {
+             /* A failure can be caused either by an invalid key or
+                by low memory.  */
+             json_check_utf8 (ekey);
+             json_out_of_memory ();
+           }
+       }
     }
   else if (NILP (lisp))
     return json_check (json_object ());
@@ -879,8 +875,9 @@ json_to_lisp (json_t *json, const struct json_configuration 
*conf)
               json_t *value;
               json_object_foreach (json, key_str, value)
                 {
-                 Lisp_Object key = build_string_from_utf8 (key_str), hash;
-                  ptrdiff_t i = hash_lookup (h, key, &hash);
+                 Lisp_Object key = build_string_from_utf8 (key_str);
+                 hash_hash_t hash;
+                  ptrdiff_t i = hash_lookup_get_hash (h, key, &hash);
                   /* Keys in JSON objects are unique, so the key can't
                      be present yet.  */
                   eassert (i < 0);
diff --git a/src/keyboard.c b/src/keyboard.c
index 81605e75ba2..1f7253a7da1 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1,6 +1,6 @@
 /* Keyboard and mouse input; editor command loop.
 
-Copyright (C) 1985-1989, 1993-1997, 1999-2023 Free Software Foundation,
+Copyright (C) 1985-1989, 1993-1997, 1999-2024 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
@@ -1026,7 +1026,7 @@ cmd_error_internal (Lisp_Object data, const char *context)
 {
   /* The immediate context is not interesting for Quits,
      since they are asynchronous.  */
-  if (signal_quit_p (XCAR (data)))
+  if (signal_quit_p (data))
     Vsignaling_function = Qnil;
 
   Vquit_flag = Qnil;
@@ -1163,7 +1163,18 @@ command_loop_2 (Lisp_Object handlers)
 static Lisp_Object
 top_level_2 (void)
 {
-  return Feval (Vtop_level, Qnil);
+  /* If we're in batch mode, print a backtrace unconditionally when
+     encountering an error, to help with debugging.  */
+  bool setup_handler = noninteractive;
+  if (setup_handler)
+    /* FIXME: Should we (re)use `list_of_error` from `xdisp.c`? */
+    push_handler_bind (list1 (Qerror), Qdebug_early__handler, 0);
+
+  Lisp_Object res = Feval (Vtop_level, Qt);
+
+  if (setup_handler)
+    pop_handler ();
+  return res;
 }
 
 static Lisp_Object
@@ -1355,7 +1366,6 @@ command_loop_1 (void)
        display_malloc_warning ();
 
       Vdeactivate_mark = Qnil;
-      backtrace_yet = false;
 
       /* Don't ignore mouse movements for more than a single command
         loop.  (This flag is set in xdisp.c whenever the tool bar is
@@ -2226,7 +2236,7 @@ show_help_echo (Lisp_Object help, Lisp_Object window, 
Lisp_Object object,
   if (!NILP (help) && !STRINGP (help))
     {
       if (FUNCTIONP (help))
-       help = safe_call (4, help, window, object, pos);
+       help = safe_calln (help, window, object, pos);
       else
        help = safe_eval (help);
 
@@ -4654,7 +4664,7 @@ timer_check_2 (Lisp_Object timers, Lisp_Object 
idle_timers)
     {
       Lisp_Object funcall = XCAR (pending_funcalls);
       pending_funcalls = XCDR (pending_funcalls);
-      safe_call2 (Qapply, XCAR (funcall), XCDR (funcall));
+      safe_calln (Qapply, XCAR (funcall), XCDR (funcall));
     }
 
   if (CONSP (timers) || CONSP (idle_timers))
@@ -8609,7 +8619,7 @@ menu_item_eval_property_1 (Lisp_Object arg)
 {
   /* If we got a quit from within the menu computation,
      quit all the way out of it.  This takes care of C-] in the debugger.  */
-  if (CONSP (arg) && signal_quit_p (XCAR (arg)))
+  if (signal_quit_p (arg))
     quit ();
 
   return Qnil;
@@ -9072,7 +9082,7 @@ process_tab_bar_item (Lisp_Object key, Lisp_Object def, 
Lisp_Object data, void *
 }
 
 /* Access slot with index IDX of vector tab_bar_item_properties.  */
-#define PROP(IDX) AREF (tab_bar_item_properties, (IDX))
+#define PROP(IDX) AREF (tab_bar_item_properties, IDX)
 static void
 set_prop_tab_bar (ptrdiff_t idx, Lisp_Object val)
 {
@@ -9456,7 +9466,7 @@ process_tool_bar_item (Lisp_Object key, Lisp_Object def, 
Lisp_Object data, void
 }
 
 /* Access slot with index IDX of vector tool_bar_item_properties.  */
-#define PROP(IDX) AREF (tool_bar_item_properties, (IDX))
+#define PROP(IDX) AREF (tool_bar_item_properties, IDX)
 static void
 set_prop (ptrdiff_t idx, Lisp_Object val)
 {
diff --git a/src/keyboard.h b/src/keyboard.h
index 9f6e65f9a09..68e68bc2ae3 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -1,5 +1,5 @@
 /* Declarations useful when processing input.
-   Copyright (C) 1985-1987, 1993, 2001-2023 Free Software Foundation,
+   Copyright (C) 1985-1987, 1993, 2001-2024 Free Software Foundation,
    Inc.
 
 This file is part of GNU Emacs.
@@ -396,7 +396,7 @@ extern void unuse_menu_items (void);
 /* Macros for dealing with lispy events.  */
 
 /* True if EVENT has data fields describing it (i.e. a mouse click).  */
-#define EVENT_HAS_PARAMETERS(event) (CONSP (event))
+#define EVENT_HAS_PARAMETERS(event) CONSP (event)
 
 /* Extract the head from an event.
    This works on composite and simple events.  */
@@ -414,32 +414,32 @@ extern void unuse_menu_items (void);
    : CAR_SAFE (CDR_SAFE (event)))
 
 /* This does not handle touchscreen events.  */
-#define EVENT_END(event) (CAR_SAFE (CDR_SAFE (CDR_SAFE (event))))
+#define EVENT_END(event) CAR_SAFE (CDR_SAFE (CDR_SAFE (event)))
 
 /* Extract the click count from a multi-click event.  */
-#define EVENT_CLICK_COUNT(event) (Fnth (make_fixnum (2), (event)))
+#define EVENT_CLICK_COUNT(event) Fnth (make_fixnum (2), event)
 
 /* Extract the fields of a position.  */
-#define POSN_WINDOW(posn) (CAR_SAFE (posn))
-#define POSN_POSN(posn) (CAR_SAFE (CDR_SAFE (posn)))
-#define POSN_SET_POSN(posn,x) (XSETCAR (XCDR (posn), (x)))
-#define POSN_WINDOW_POSN(posn) (CAR_SAFE (CDR_SAFE (CDR_SAFE (posn))))
-#define POSN_TIMESTAMP(posn) (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (posn)))))
-#define POSN_SCROLLBAR_PART(posn)      (Fnth (make_fixnum (4), (posn)))
+#define POSN_WINDOW(posn) CAR_SAFE (posn)
+#define POSN_POSN(posn) CAR_SAFE (CDR_SAFE (posn))
+#define POSN_SET_POSN(posn,x) XSETCAR (XCDR (posn), x)
+#define POSN_WINDOW_POSN(posn) CAR_SAFE (CDR_SAFE (CDR_SAFE (posn)))
+#define POSN_TIMESTAMP(posn) CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (posn))))
+#define POSN_SCROLLBAR_PART(posn) Fnth (make_fixnum (4), posn)
 
 /* A cons (STRING . STRING-CHARPOS), or nil in mouse-click events.
    It's a cons if the click is over a string in the mode line.  */
 
-#define POSN_STRING(posn) (Fnth (make_fixnum (4), (posn)))
+#define POSN_STRING(posn) Fnth (make_fixnum (4), posn)
 
 /* If POSN_STRING is nil, event refers to buffer location.  */
 
-#define POSN_INBUFFER_P(posn) (NILP (POSN_STRING (posn)))
-#define POSN_BUFFER_POSN(posn) (Fnth (make_fixnum (5), (posn)))
+#define POSN_INBUFFER_P(posn) NILP (POSN_STRING (posn))
+#define POSN_BUFFER_POSN(posn) Fnth (make_fixnum (5), posn)
 
 /* Getting the kind of an event head.  */
 #define EVENT_HEAD_KIND(event_head) \
-  (Fget ((event_head), Qevent_kind))
+  Fget (event_head, Qevent_kind)
 
 /* Address (if not 0) of struct timespec to zero out if a SIGIO interrupt
    happens.  */
diff --git a/src/keymap.c b/src/keymap.c
index d710bae02e0..10378767c65 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -1,5 +1,5 @@
 /* Manipulation of keymaps
-   Copyright (C) 1985-1988, 1993-1995, 1998-2023 Free Software
+   Copyright (C) 1985-1988, 1993-1995, 1998-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -610,7 +610,7 @@ map_keymap_canonical (Lisp_Object map, 
map_keymap_function_t fun, Lisp_Object ar
 {
   /* map_keymap_canonical may be used from redisplay (e.g. when building menus)
      so be careful to ignore errors and to inhibit redisplay.  */
-  map = safe_call1 (Qkeymap_canonicalize, map);
+  map = safe_calln (Qkeymap_canonicalize, map);
   /* No need to use `map_keymap' here because canonical map has no parent.  */
   map_keymap_internal (map, fun, args, data);
 }
diff --git a/src/keymap.h b/src/keymap.h
index 65be3addbdb..e79e0af9d36 100644
--- a/src/keymap.h
+++ b/src/keymap.h
@@ -1,5 +1,5 @@
 /* Functions to manipulate keymaps.
-   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/kqueue.c b/src/kqueue.c
index 43d5f40624b..4693e130208 100644
--- a/src/kqueue.c
+++ b/src/kqueue.c
@@ -1,6 +1,6 @@
 /* Filesystem notifications support with kqueue API.
 
-Copyright (C) 2015-2023 Free Software Foundation, Inc.
+Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/lastfile.c b/src/lastfile.c
index b80cdbc8fa6..48d3ac78634 100644
--- a/src/lastfile.c
+++ b/src/lastfile.c
@@ -1,5 +1,5 @@
 /* Mark end of data space to dump as pure, for GNU Emacs.
-   Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/lcms.c b/src/lcms.c
index e603573043e..52dff9afc97 100644
--- a/src/lcms.c
+++ b/src/lcms.c
@@ -1,5 +1,5 @@
 /* Interface to Little CMS
-   Copyright (C) 2017-2023 Free Software Foundation, Inc.
+   Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/lisp.h b/src/lisp.h
index 60034ddd4cd..d6f99c96bff 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1,6 +1,6 @@
 /* Fundamental definitions for GNU Emacs Lisp interpreter. -*- coding: utf-8 
-*-
 
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -303,6 +303,9 @@ DEFINE_GDB_SYMBOL_END (VALMASK)
 
 #define LISP_WORDS_ARE_POINTERS (EMACS_INT_MAX == INTPTR_MAX)
 #if LISP_WORDS_ARE_POINTERS
+/* TAG_PTR_INITIALLY casts to Lisp_Word and can be used in static initializers
+   so this typedef assumes static initializers can contain casts to pointers.
+   All Emacs targets support this extension to the C standard.  */
 typedef struct Lisp_X *Lisp_Word;
 #else
 typedef EMACS_INT Lisp_Word;
@@ -369,11 +372,11 @@ typedef EMACS_INT Lisp_Word;
 # define lisp_h_Qnil {0}
 #endif
 
-#define lisp_h_PSEUDOVECTORP(a,code)                            \
-  (lisp_h_VECTORLIKEP((a)) &&                                   \
-   ((XUNTAG ((a), Lisp_Vectorlike, union vectorlike_header)->size     \
-     & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))                    \
-    == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_AREA_BITS))))
+#define lisp_h_PSEUDOVECTORP(a,code)                                   \
+  (lisp_h_VECTORLIKEP (a)                                              \
+   && ((XUNTAG (a, Lisp_Vectorlike, union vectorlike_header)->size     \
+       & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))                         \
+       == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_AREA_BITS))))
 
 #define lisp_h_CHECK_FIXNUM(x) CHECK_TYPE (FIXNUMP (x), Qfixnump, x)
 #define lisp_h_CHECK_SYMBOL(x) CHECK_TYPE (SYMBOLP (x), Qsymbolp, x)
@@ -391,17 +394,17 @@ typedef EMACS_INT Lisp_Word;
  * What about keeping the part after `symbols_with_pos_enabled` in
  * a separate function?  */
 #define lisp_h_EQ(x, y)                                     \
-  ((XLI ((x)) == XLI ((y)))                                 \
+  (XLI (x) == XLI (y)                                      \
    || (symbols_with_pos_enabled                             \
-       && (SYMBOL_WITH_POS_P ((x))                          \
-           ? (BARE_SYMBOL_P ((y))                           \
-              ? XLI (XSYMBOL_WITH_POS((x))->sym) == XLI (y) \
-              : SYMBOL_WITH_POS_P((y))                      \
-                && (XLI (XSYMBOL_WITH_POS((x))->sym)        \
-                    == XLI (XSYMBOL_WITH_POS((y))->sym)))   \
-           : (SYMBOL_WITH_POS_P ((y))                       \
-              && BARE_SYMBOL_P ((x))                        \
-              && (XLI (x) == XLI ((XSYMBOL_WITH_POS ((y)))->sym))))))
+       && (SYMBOL_WITH_POS_P (x)                           \
+           ? (BARE_SYMBOL_P (y)                                    \
+              ? XLI (XSYMBOL_WITH_POS (x)->sym) == XLI (y)  \
+              : (SYMBOL_WITH_POS_P (y)                     \
+                && (XLI (XSYMBOL_WITH_POS (x)->sym)        \
+                    == XLI (XSYMBOL_WITH_POS (y)->sym))))  \
+           : (SYMBOL_WITH_POS_P (y)                        \
+              && BARE_SYMBOL_P (x)                         \
+              && (XLI (x) == XLI (XSYMBOL_WITH_POS (y)->sym))))))
 
 #define lisp_h_FIXNUMP(x) \
    (! (((unsigned) (XLI (x) >> (USE_LSB_TAG ? 0 : FIXNUM_BITS)) \
@@ -417,10 +420,10 @@ typedef EMACS_INT Lisp_Word;
 #define lisp_h_SYMBOL_TRAPPED_WRITE_P(sym) (XSYMBOL (sym)->u.s.trapped_write)
 #define lisp_h_SYMBOL_VAL(sym) \
    (eassert ((sym)->u.s.redirect == SYMBOL_PLAINVAL), (sym)->u.s.val.value)
-#define lisp_h_SYMBOL_WITH_POS_P(x) PSEUDOVECTORP ((x), PVEC_SYMBOL_WITH_POS)
-#define lisp_h_BARE_SYMBOL_P(x) TAGGEDP ((x), Lisp_Symbol)
-#define lisp_h_SYMBOLP(x) ((BARE_SYMBOL_P ((x)) ||               \
-                            (symbols_with_pos_enabled && (SYMBOL_WITH_POS_P 
((x))))))
+#define lisp_h_SYMBOL_WITH_POS_P(x) PSEUDOVECTORP (x, PVEC_SYMBOL_WITH_POS)
+#define lisp_h_BARE_SYMBOL_P(x) TAGGEDP (x, Lisp_Symbol)
+#define lisp_h_SYMBOLP(x) \
+   (BARE_SYMBOL_P (x) || (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (x)))
 #define lisp_h_TAGGEDP(a, tag) \
    (! (((unsigned) (XLI (a) >> (USE_LSB_TAG ? 0 : VALBITS)) \
        - (unsigned) (tag)) \
@@ -931,14 +934,16 @@ typedef EMACS_UINT Lisp_Word_tag;
 #define LISP_WORD_TAG(tag) \
   ((Lisp_Word_tag) (tag) << (USE_LSB_TAG ? 0 : VALBITS))
 
-/* An initializer for a Lisp_Object that contains TAG along with PTR.  */
-#define TAG_PTR(tag, ptr) \
-  LISP_INITIALLY ((Lisp_Word) ((uintptr_t) (ptr) + LISP_WORD_TAG (tag)))
+/* An initializer for a Lisp_Object that contains TAG along with P.
+   P can be a pointer or an integer.  The result is usable in a static
+   initializer if TAG and P are both integer constant expressions.  */
+#define TAG_PTR_INITIALLY(tag, p) \
+  LISP_INITIALLY ((Lisp_Word) ((uintptr_t) (p) + LISP_WORD_TAG (tag)))
 
 /* LISPSYM_INITIALLY (Qfoo) is equivalent to Qfoo except it is
-   designed for use as an initializer, even for a constant initializer.  */
+   designed for use as a (possibly static) initializer.  */
 #define LISPSYM_INITIALLY(name) \
-  TAG_PTR (Lisp_Symbol, (char *) (intptr_t) ((i##name) * sizeof *lispsym))
+  TAG_PTR_INITIALLY (Lisp_Symbol, (intptr_t) ((i##name) * sizeof *lispsym))
 
 /* Declare extern constants for Lisp symbols.  These can be helpful
    when using a debugger like GDB, on older platforms where the debug
@@ -1145,7 +1150,7 @@ XSYMBOL_WITH_POS (Lisp_Object a)
 }
 
 INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED
-(XBARE_SYMBOL) (Lisp_Object a)
+XBARE_SYMBOL (Lisp_Object a)
 {
   eassert (BARE_SYMBOL_P (a));
   intptr_t i = (intptr_t) XUNTAG (a, Lisp_Symbol, struct Lisp_Symbol);
@@ -1154,29 +1159,41 @@ INLINE struct Lisp_Symbol * 
ATTRIBUTE_NO_SANITIZE_UNDEFINED
 }
 
 INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED
-(XSYMBOL) (Lisp_Object a)
+XSYMBOL (Lisp_Object a)
 {
-  eassert (SYMBOLP ((a)));
-  if (!symbols_with_pos_enabled || BARE_SYMBOL_P (a))
-    return XBARE_SYMBOL (a);
-  return XBARE_SYMBOL (XSYMBOL_WITH_POS (a)->sym);
+  if (!BARE_SYMBOL_P (a))
+    {
+      eassert (symbols_with_pos_enabled);
+      a = XSYMBOL_WITH_POS (a)->sym;
+    }
+  return XBARE_SYMBOL (a);
 }
 
+/* Internal use only.  */
 INLINE Lisp_Object
-make_lisp_symbol (struct Lisp_Symbol *sym)
+make_lisp_symbol_internal (struct Lisp_Symbol *sym)
 {
   /* GCC 7 x86-64 generates faster code if lispsym is
-     cast to char * rather than to intptr_t.  */
+     cast to char * rather than to intptr_t.
+     Do not use eassert here, so that builtin symbols like Qnil compile to
+     constants; this is needed for some circa-2024 GCCs even with -O2.  */
   char *symoffset = (char *) ((char *) sym - (char *) lispsym);
-  Lisp_Object a = TAG_PTR (Lisp_Symbol, symoffset);
-  eassert (XSYMBOL (a) == sym);
+  Lisp_Object a = TAG_PTR_INITIALLY (Lisp_Symbol, symoffset);
+  return a;
+}
+
+INLINE Lisp_Object
+make_lisp_symbol (struct Lisp_Symbol *sym)
+{
+  Lisp_Object a = make_lisp_symbol_internal (sym);
+  eassert (XBARE_SYMBOL (a) == sym);
   return a;
 }
 
 INLINE Lisp_Object
 builtin_lisp_symbol (int index)
 {
-  return make_lisp_symbol (&lispsym[index]);
+  return make_lisp_symbol_internal (&lispsym[index]);
 }
 
 INLINE bool
@@ -1362,7 +1379,7 @@ clip_to_bounds (intmax_t lower, intmax_t num, intmax_t 
upper)
 INLINE Lisp_Object
 make_lisp_ptr (void *ptr, enum Lisp_Type type)
 {
-  Lisp_Object a = TAG_PTR (type, ptr);
+  Lisp_Object a = TAG_PTR_INITIALLY (type, ptr);
   eassert (TAGGEDP (a, type) && XUNTAG (a, type, char) == ptr);
   return a;
 }
@@ -1407,19 +1424,19 @@ dead_object (void)
            == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_AREA_BITS))))
 
 #define XSETWINDOW_CONFIGURATION(a, b) \
-  (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION))
-#define XSETPROCESS(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_PROCESS))
-#define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW))
-#define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL))
-#define XSETSUBR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUBR))
-#define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER))
-#define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE))
-#define XSETBOOL_VECTOR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR))
-#define XSETSUB_CHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUB_CHAR_TABLE))
-#define XSETTHREAD(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_THREAD))
-#define XSETMUTEX(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_MUTEX))
-#define XSETCONDVAR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CONDVAR))
-#define XSETNATIVE_COMP_UNIT(a, b) (XSETPSEUDOVECTOR (a, b, 
PVEC_NATIVE_COMP_UNIT))
+  XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION)
+#define XSETPROCESS(a, b) XSETPSEUDOVECTOR (a, b, PVEC_PROCESS)
+#define XSETWINDOW(a, b) XSETPSEUDOVECTOR (a, b, PVEC_WINDOW)
+#define XSETTERMINAL(a, b) XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL)
+#define XSETSUBR(a, b) XSETPSEUDOVECTOR (a, b, PVEC_SUBR)
+#define XSETBUFFER(a, b) XSETPSEUDOVECTOR (a, b, PVEC_BUFFER)
+#define XSETCHAR_TABLE(a, b) XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE)
+#define XSETBOOL_VECTOR(a, b) XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR)
+#define XSETSUB_CHAR_TABLE(a, b) XSETPSEUDOVECTOR (a, b, PVEC_SUB_CHAR_TABLE)
+#define XSETTHREAD(a, b) XSETPSEUDOVECTOR (a, b, PVEC_THREAD)
+#define XSETMUTEX(a, b) XSETPSEUDOVECTOR (a, b, PVEC_MUTEX)
+#define XSETCONDVAR(a, b) XSETPSEUDOVECTOR (a, b, PVEC_CONDVAR)
+#define XSETNATIVE_COMP_UNIT(a, b) XSETPSEUDOVECTOR (a, b, 
PVEC_NATIVE_COMP_UNIT)
 
 /* Efficiently convert a pointer to a Lisp object and back.  The
    pointer is represented as a fixnum, so the garbage collector
@@ -1435,7 +1452,7 @@ XFIXNUMPTR (Lisp_Object a)
 INLINE Lisp_Object
 make_pointer_integer_unsafe (void *p)
 {
-  Lisp_Object a = TAG_PTR (Lisp_Int0, p);
+  Lisp_Object a = TAG_PTR_INITIALLY (Lisp_Int0, p);
   return a;
 }
 
@@ -2385,10 +2402,23 @@ INLINE int
 
 struct Lisp_Hash_Table;
 
+/* The type of a hash value stored in the table.
+   It's unsigned and a subtype of EMACS_UINT.  */
+typedef uint32_t hash_hash_t;
+
+typedef enum {
+  Test_eql,
+  Test_eq,
+  Test_equal,
+} hash_table_std_test_t;
+
 struct hash_table_test
 {
-  /* Name of the function used to compare keys.  */
-  Lisp_Object name;
+  /* C function to compute hash code.  */
+  hash_hash_t (*hashfn) (Lisp_Object, struct Lisp_Hash_Table *);
+
+  /* C function to compare two keys.  */
+  Lisp_Object (*cmpfn) (Lisp_Object, Lisp_Object, struct Lisp_Hash_Table *);
 
   /* User-supplied hash function, or nil.  */
   Lisp_Object user_hash_function;
@@ -2396,49 +2426,99 @@ struct hash_table_test
   /* User-supplied key comparison function, or nil.  */
   Lisp_Object user_cmp_function;
 
-  /* C function to compare two keys.  */
-  Lisp_Object (*cmpfn) (Lisp_Object, Lisp_Object, struct Lisp_Hash_Table *);
-
-  /* C function to compute hash code.  */
-  Lisp_Object (*hashfn) (Lisp_Object, struct Lisp_Hash_Table *);
+  /* Function used to compare keys; always a bare symbol.  */
+  Lisp_Object name;
 };
 
+typedef enum {
+  Weak_None,            /* No weak references.  */
+  Weak_Key,             /* Reference to key is weak.  */
+  Weak_Value,           /* Reference to value is weak.  */
+  Weak_Key_Or_Value,    /* References to key or value are weak:
+                           element kept as long as strong reference to
+                           either key or value remains.  */
+  Weak_Key_And_Value,   /* References to key and value are weak:
+                           element kept as long as strong references to
+                           both key and value remain.  */
+} hash_table_weakness_t;
+
+/* The type of a hash table index, both for table indices and index
+   (hash) indices.  It's signed and a subtype of ptrdiff_t.  */
+typedef int32_t hash_idx_t;
+
 struct Lisp_Hash_Table
 {
-  /* Change pdumper.c if you change the fields here.  */
-
-  /* This is for Lisp; the hash table code does not refer to it.  */
   union vectorlike_header header;
 
-  /* Nil if table is non-weak.  Otherwise a symbol describing the
-     weakness of the table.  */
-  Lisp_Object weak;
+  /* Hash table internal structure:
+
+     Lisp key         index                  table
+         |            vector
+         | hash fn                  hash    key   value  next
+         v             +--+       +------+-------+------+----+
+     hash value        |-1|       | C351 |  cow  | moo  | -1 |<-
+         |             +--+       +------+-------+------+----+  |
+          ------------>| -------->| 07A8 |  cat  | meow | -1 |  |
+            range      +--+       +------+-------+------+----+  |
+          reduction    |-1|     ->| 91D2 |  dog  | woof |   ----
+                       +--+    |  +------+-------+------+----+
+                       | ------   |  ?   |unbound|  ?   | -1 |<-
+                       +--+       +------+-------+------+----+  |
+                       | -------->| F6B0 | duck  |quack | -1 |  |
+                       +--+       +------+-------+------+----+  |
+                       |-1|     ->|  ?   |unbound|  ?   |   ----
+                       +--+    |  +------+-------+------+----+
+                       :  :    |  :      :       :     :    :
+                               |
+                           next_free
+
+     The table is physically split into three vectors (hash, next,
+     key_and_value) which may or may not be beneficial.  */
+
+  hash_idx_t index_size;   /* Size of the index vector.  */
+  hash_idx_t table_size;   /* Size of the next and hash vectors.  */
 
-  /* Vector of hash codes, or nil if the table needs rehashing.
-     If the I-th entry is unused, then hash[I] should be nil.  */
-  Lisp_Object hash;
+  /* Bucket vector.  An entry of -1 indicates no item is present,
+     and a nonnegative entry is the index of the first item in
+     a collision chain.
+     This vector is index_size entries long.
+     If index_size is 1 (and table_size is 0), then this is the
+     constant read-only vector {-1}, shared between all instances.
+     Otherwise it is heap-allocated.  */
+  hash_idx_t *index;
+
+  /* Vector of hash codes.  Unused entries have undefined values.
+     This vector is table_size entries long.  */
+  hash_hash_t *hash;
+
+  /* Vector of keys and values.  The key of item I is found at index
+     2 * I, the value is found at index 2 * I + 1.
+     If the key is HASH_UNUSED_ENTRY_KEY, then this slot is unused.
+     This is gc_marked specially if the table is weak.
+     This vector is 2 * table_size entries long.  */
+  Lisp_Object *key_and_value;
+
+  /* The comparison and hash functions.  */
+  const struct hash_table_test *test;
 
   /* Vector used to chain entries.  If entry I is free, next[I] is the
      entry number of the next free item.  If entry I is non-free,
      next[I] is the index of the next entry in the collision chain,
-     or -1 if there is such entry.  */
-  Lisp_Object next;
-
-  /* Bucket vector.  An entry of -1 indicates no item is present,
-     and a nonnegative entry is the index of the first item in
-     a collision chain.  This vector's size can be larger than the
-     hash table size to reduce collisions.  */
-  Lisp_Object index;
-
-  /* Only the fields above are traced normally by the GC.  The ones after
-     'index' are special and are either ignored by the GC or traced in
-     a special way (e.g. because of weakness).  */
+     or -1 if there is no such entry.
+     This vector is table_size entries long.  */
+  hash_idx_t *next;
 
   /* Number of key/value entries in the table.  */
-  ptrdiff_t count;
+  hash_idx_t count;
 
   /* Index of first free entry in free list, or -1 if none.  */
-  ptrdiff_t next_free;
+  hash_idx_t next_free;
+
+  /* Weakness of the table.  */
+  hash_table_weakness_t weakness : 8;
+
+  /* Hash table test (only used when frozen in dump)  */
+  hash_table_std_test_t frozen_test : 8;
 
   /* True if the table can be purecopied.  The table cannot be
      changed afterwards.  */
@@ -2449,34 +2529,26 @@ struct Lisp_Hash_Table
      immutable for recursive attempts to mutate it.  */
   bool mutable;
 
-  /* Resize hash table when number of entries / table size is >= this
-     ratio.  */
-  float rehash_threshold;
-
-  /* Used when the table is resized.  If equal to a negative integer,
-     the user rehash-size is the integer -REHASH_SIZE, and the new
-     size is the old size plus -REHASH_SIZE.  If positive, the user
-     rehash-size is the floating-point value REHASH_SIZE + 1, and the
-     new size is the old size times REHASH_SIZE + 1.  */
-  float rehash_size;
-
-  /* Vector of keys and values.  The key of item I is found at index
-     2 * I, the value is found at index 2 * I + 1.
-     If the key is equal to Qunbound, then this slot is unused.
-     This is gc_marked specially if the table is weak.  */
-  Lisp_Object key_and_value;
-
-  /* The comparison and hash functions.  */
-  struct hash_table_test test;
-
   /* Next weak hash table if this is a weak hash table.  The head of
      the list is in weak_hash_tables.  Used only during garbage
      collection --- at other times, it is NULL.  */
   struct Lisp_Hash_Table *next_weak;
 } GCALIGNED_STRUCT;
 
-/* Sanity-check pseudovector layout.  */
-verify (offsetof (struct Lisp_Hash_Table, weak) == header_size);
+/* A specific Lisp_Object that is not a valid Lisp value.
+   We need to be careful not to leak this value into machinery
+   where it may be treated as one; we'd get a segfault if lucky.  */
+#define INVALID_LISP_VALUE make_lisp_ptr (NULL, Lisp_Float)
+
+/* Key value that marks an unused hash table entry.  */
+#define HASH_UNUSED_ENTRY_KEY INVALID_LISP_VALUE
+
+/* KEY is a key of an unused hash table entry.  */
+INLINE bool
+hash_unused_entry_key_p (Lisp_Object key)
+{
+  return BASE_EQ (key, HASH_UNUSED_ENTRY_KEY);
+}
 
 INLINE bool
 HASH_TABLE_P (Lisp_Object a)
@@ -2492,53 +2564,85 @@ XHASH_TABLE (Lisp_Object a)
 }
 
 #define XSET_HASH_TABLE(VAR, PTR) \
-     (XSETPSEUDOVECTOR (VAR, PTR, PVEC_HASH_TABLE))
+  XSETPSEUDOVECTOR (VAR, PTR, PVEC_HASH_TABLE)
 
 /* Value is the key part of entry IDX in hash table H.  */
 INLINE Lisp_Object
 HASH_KEY (const struct Lisp_Hash_Table *h, ptrdiff_t idx)
 {
-  return AREF (h->key_and_value, 2 * idx);
+  eassert (idx >= 0 && idx < h->table_size);
+  return h->key_and_value[2 * idx];
 }
 
 /* Value is the value part of entry IDX in hash table H.  */
 INLINE Lisp_Object
 HASH_VALUE (const struct Lisp_Hash_Table *h, ptrdiff_t idx)
 {
-  return AREF (h->key_and_value, 2 * idx + 1);
+  eassert (idx >= 0 && idx < h->table_size);
+  return h->key_and_value[2 * idx + 1];
 }
 
 /* Value is the hash code computed for entry IDX in hash table H.  */
-INLINE Lisp_Object
+INLINE hash_hash_t
 HASH_HASH (const struct Lisp_Hash_Table *h, ptrdiff_t idx)
 {
-  return AREF (h->hash, idx);
+  eassert (idx >= 0 && idx < h->table_size);
+  return h->hash[idx];
 }
 
 /* Value is the size of hash table H.  */
 INLINE ptrdiff_t
 HASH_TABLE_SIZE (const struct Lisp_Hash_Table *h)
 {
-  ptrdiff_t size = ASIZE (h->next);
-  eassume (0 < size);
-  return size;
-}
-
-void hash_table_rehash (Lisp_Object);
+  return h->table_size;
+}
+
+/* Hash value for KEY in hash table H.  */
+INLINE hash_hash_t
+hash_from_key (struct Lisp_Hash_Table *h, Lisp_Object key)
+{
+  return h->test->hashfn (key, h);
+}
+
+/* Iterate K and V as key and value of valid entries in hash table H.
+   The body may remove the current entry or alter its value slot, but not
+   mutate TABLE in any other way.  */
+#define DOHASH(h, k, v)                                                        
\
+  for (Lisp_Object *dohash_##k##_##v##_kv = (h)->key_and_value,                
\
+                   *dohash_##k##_##v##_end = dohash_##k##_##v##_kv     \
+                                             + 2 * HASH_TABLE_SIZE (h),        
\
+                  *dohash_##k##_##v##_base = dohash_##k##_##v##_kv,    \
+                   k, v;                                               \
+       dohash_##k##_##v##_kv < dohash_##k##_##v##_end                  \
+       && (k = dohash_##k##_##v##_kv[0],                               \
+           v = dohash_##k##_##v##_kv[1], /*maybe unused*/ (void)v,      \
+           true);                                                      \
+       eassert (dohash_##k##_##v##_base == (h)->key_and_value          \
+               && dohash_##k##_##v##_end                               \
+                  == dohash_##k##_##v##_base                           \
+                     + 2 * HASH_TABLE_SIZE (h)),                       \
+       dohash_##k##_##v##_kv += 2)                                     \
+    if (hash_unused_entry_key_p (k))                                   \
+      ;                                                                        
\
+    else
+
+/* Iterate I as index of valid entries in hash table H.
+   Unlike DOHASH, this construct copes with arbitrary table mutations
+   in the body.  The consequences of such mutations are limited to
+   whether and in what order entries are encountered by the loop
+   (which is usually bad enough), but not crashing or corrupting the
+   Lisp state.  */
+#define DOHASH_SAFE(h, i)                                      \
+  for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); i++)          \
+    if (hash_unused_entry_key_p (HASH_KEY (h, i)))             \
+      ;                                                                \
+    else
+
+void hash_table_thaw (Lisp_Object hash_table);
 
 /* Default size for hash tables if not specified.  */
 
-enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE = 65 };
-
-/* Default threshold specifying when to resize a hash table.  The
-   value gives the ratio of current entries in the hash table and the
-   size of the hash table.  */
-
-static float const DEFAULT_REHASH_THRESHOLD = 0.8125;
-
-/* Default factor by which to increase the size of a hash table, minus 1.  */
-
-static float const DEFAULT_REHASH_SIZE = 1.5 - 1;
+enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE = 0 };
 
 /* Combine two integers X and Y for hashing.  The result might exceed
    INTMASK.  */
@@ -2641,7 +2745,7 @@ extern Lisp_Object make_misc_ptr (void *);
 INLINE Lisp_Object
 make_mint_ptr (void *a)
 {
-  Lisp_Object val = TAG_PTR (Lisp_Int0, a);
+  Lisp_Object val = TAG_PTR_INITIALLY (Lisp_Int0, a);
   return FIXNUMP (val) && XFIXNUMPTR (val) == a ? val : make_misc_ptr (a);
 }
 
@@ -3233,77 +3337,25 @@ enum maxargs
    empty initializers), and is overkill for simple usages like
    'Finsert (1, &text);'.  */
 #define CALLN(f, ...) CALLMANY (f, ((Lisp_Object []) {__VA_ARGS__}))
-
-/* Call function fn on no arguments.  */
+#define calln(...) CALLN (Ffuncall, __VA_ARGS__)
+/* Compatibility aliases.  */
+#define call1 calln
+#define call2 calln
+#define call3 calln
+#define call4 calln
+#define call5 calln
+#define call6 calln
+#define call7 calln
+#define call8 calln
+
+/* Define 'call0' as a function rather than a CPP macro because we
+   sometimes want to pass it as a first class function.  */
 INLINE Lisp_Object
 call0 (Lisp_Object fn)
 {
   return Ffuncall (1, &fn);
 }
 
-/* Call function fn with 1 argument arg1.  */
-INLINE Lisp_Object
-call1 (Lisp_Object fn, Lisp_Object arg1)
-{
-  return CALLN (Ffuncall, fn, arg1);
-}
-
-/* Call function fn with 2 arguments arg1, arg2.  */
-INLINE Lisp_Object
-call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
-{
-  return CALLN (Ffuncall, fn, arg1, arg2);
-}
-
-/* Call function fn with 3 arguments arg1, arg2, arg3.  */
-INLINE Lisp_Object
-call3 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3)
-{
-  return CALLN (Ffuncall, fn, arg1, arg2, arg3);
-}
-
-/* Call function fn with 4 arguments arg1, arg2, arg3, arg4.  */
-INLINE Lisp_Object
-call4 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
-       Lisp_Object arg4)
-{
-  return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4);
-}
-
-/* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5.  */
-INLINE Lisp_Object
-call5 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
-       Lisp_Object arg4, Lisp_Object arg5)
-{
-  return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5);
-}
-
-/* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6.  */
-INLINE Lisp_Object
-call6 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
-       Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6)
-{
-  return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6);
-}
-
-/* Call function fn with 7 arguments arg1, arg2, arg3, arg4, arg5, arg6, arg7. 
 */
-INLINE Lisp_Object
-call7 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
-       Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7)
-{
-  return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
-}
-
-/* Call function fn with 8 arguments arg1, arg2, arg3, arg4, arg5,
-   arg6, arg7, arg8.  */
-INLINE Lisp_Object
-call8 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
-       Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7,
-       Lisp_Object arg8)
-{
-  return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
-}
-
 extern void defvar_lisp (struct Lisp_Objfwd const *, char const *);
 extern void defvar_lisp_nopro (struct Lisp_Objfwd const *, char const *);
 extern void defvar_bool (struct Lisp_Boolfwd const *, char const *);
@@ -3595,7 +3647,8 @@ record_in_backtrace (Lisp_Object function, Lisp_Object 
*args, ptrdiff_t nargs)
 }
 
 /* This structure helps implement the `catch/throw' and `condition-case/signal'
-   control structures.  A struct handler contains all the information needed to
+   control structures as well as 'handler-bind'.
+   A struct handler contains all the information needed to
    restore the state of the interpreter after a non-local jump.
 
    Handler structures are chained together in a doubly linked list; the `next'
@@ -3616,9 +3669,41 @@ record_in_backtrace (Lisp_Object function, Lisp_Object 
*args, ptrdiff_t nargs)
    state.
 
    Members are volatile if their values need to survive _longjmp when
-   a 'struct handler' is a local variable.  */
-
-enum handlertype { CATCHER, CONDITION_CASE, CATCHER_ALL };
+   a 'struct handler' is a local variable.
+
+   When running the HANDLER of a 'handler-bind', we need to
+   temporarily "mute" the CONDITION_CASEs and HANDLERs that are "below"
+   the current handler, but without hiding any CATCHERs.  We do that by
+   installing a SKIP_CONDITIONS which tells the search to skip the
+   N next conditions.  */
+
+enum handlertype {
+  CATCHER,                      /* Entry for 'catch'.
+                                   'tag_or_ch' holds the catch's tag.
+                                   'val' holds the retval during longjmp.  */
+  CONDITION_CASE,               /* Entry for 'condition-case'.
+                                   'tag_or_ch' holds the list of conditions.
+                                   'val' holds the retval during longjmp.  */
+  CATCHER_ALL,                  /* Wildcard which catches all 'throw's.
+                                   'tag_or_ch' is unused.
+                                   'val' holds the retval during longjmp.  */
+  HANDLER_BIND,                 /* Entry for 'handler-bind'.
+                                   'tag_or_ch' holds the list of conditions.
+                                   'val' holds the handler function.
+                                   The rest of the handler is unused,
+                                   except for 'bytecode_dest' that holds
+                                   the number of preceding HANDLER_BIND
+                                   entries which belong to the same
+                                   'handler-bind' (and hence need to
+                                   be muted together).  */
+  SKIP_CONDITIONS               /* Mask out the N preceding entries.
+                                   Used while running the handler of
+                                   a HANDLER_BIND to hides the condition
+                                   handlers underneath (and including)
+                                   the 'handler-bind'.
+                                   'tag_or_ch' holds that number, the rest
+                                   is unused.  */
+};
 
 enum nonlocal_exit
 {
@@ -3764,13 +3849,15 @@ vcopy (Lisp_Object v, ptrdiff_t offset, Lisp_Object 
const *args,
 INLINE void
 set_hash_key_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val)
 {
-  gc_aset (h->key_and_value, 2 * idx, val);
+  eassert (idx >= 0 && idx < h->table_size);
+  h->key_and_value[2 * idx] = val;
 }
 
 INLINE void
 set_hash_value_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, Lisp_Object val)
 {
-  gc_aset (h->key_and_value, 2 * idx + 1, val);
+  eassert (idx >= 0 && idx < h->table_size);
+  h->key_and_value[2 * idx + 1] = val;;
 }
 
 /* Use these functions to set Lisp_Object
@@ -4002,6 +4089,7 @@ extern ptrdiff_t multibyte_chars_in_text (const unsigned 
char *, ptrdiff_t);
 extern void syms_of_character (void);
 
 /* Defined in charset.c.  */
+extern void mark_charset (void);
 extern void init_charset (void);
 extern void init_charset_once (void);
 extern void syms_of_charset (void);
@@ -4022,12 +4110,14 @@ extern void hexbuf_digest (char *, void const *, int);
 extern char *extract_data_from_object (Lisp_Object, ptrdiff_t *, ptrdiff_t *);
 EMACS_UINT hash_string (char const *, ptrdiff_t);
 EMACS_UINT sxhash (Lisp_Object);
-Lisp_Object hashfn_user_defined (Lisp_Object, struct Lisp_Hash_Table *);
-Lisp_Object make_hash_table (struct hash_table_test, EMACS_INT, float, float,
-                             Lisp_Object, bool);
-ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object *);
+Lisp_Object make_hash_table (const struct hash_table_test *, EMACS_INT,
+                             hash_table_weakness_t, bool);
+Lisp_Object hash_table_weakness_symbol (hash_table_weakness_t weak);
+ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object);
+ptrdiff_t hash_lookup_get_hash (struct Lisp_Hash_Table *h, Lisp_Object key,
+                               hash_hash_t *phash);
 ptrdiff_t hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object,
-                   Lisp_Object);
+                   hash_hash_t);
 void hash_remove_from_table (struct Lisp_Hash_Table *, Lisp_Object);
 extern struct hash_table_test const hashtest_eq, hashtest_eql, hashtest_equal;
 extern void validate_subarray (Lisp_Object, Lisp_Object, Lisp_Object,
@@ -4054,6 +4144,7 @@ extern Lisp_Object plist_put (Lisp_Object plist, 
Lisp_Object prop,
                              Lisp_Object val);
 extern Lisp_Object plist_member (Lisp_Object plist, Lisp_Object prop);
 extern void syms_of_fns (void);
+extern void mark_fns (void);
 
 /* Defined in sort.c  */
 extern void tim_sort (Lisp_Object, Lisp_Object *, const ptrdiff_t);
@@ -4435,6 +4526,9 @@ extern void syms_of_alloc (void);
 extern struct buffer *allocate_buffer (void) ATTRIBUTE_RETURNS_NONNULL;
 extern int valid_lisp_object_p (Lisp_Object);
 
+void *hash_table_alloc_bytes (ptrdiff_t nbytes) ATTRIBUTE_MALLOC_SIZE ((1));
+void hash_table_free_bytes (void *p, ptrdiff_t nbytes);
+
 /* Defined in gmalloc.c.  */
 #if !defined DOUG_LEA_MALLOC && !defined HYBRID_MALLOC && !defined 
SYSTEM_MALLOC
 extern size_t __malloc_extra_blocks;
@@ -4548,7 +4642,6 @@ extern Lisp_Object Vrun_hooks;
 extern Lisp_Object Vsignaling_function;
 extern Lisp_Object inhibit_lisp_code;
 extern bool signal_quit_p (Lisp_Object);
-extern bool backtrace_yet;
 
 /* To run a normal hook, use the appropriate function from the list below.
    The calling convention:
@@ -4589,6 +4682,8 @@ extern Lisp_Object internal_condition_case_n
 extern Lisp_Object internal_catch_all (Lisp_Object (*) (void *), void *, 
Lisp_Object (*) (enum nonlocal_exit, Lisp_Object));
 extern struct handler *push_handler (Lisp_Object, enum handlertype)
   ATTRIBUTE_RETURNS_NONNULL;
+extern void pop_handler (void);
+extern void push_handler_bind (Lisp_Object, Lisp_Object, int);
 extern struct handler *push_handler_nosignal (Lisp_Object, enum handlertype);
 extern void specbind (Lisp_Object, Lisp_Object);
 extern void record_unwind_protect (void (*) (Lisp_Object), Lisp_Object);
@@ -4618,14 +4713,15 @@ extern Lisp_Object load_with_autoload_queue
             Lisp_Object nosuffix, Lisp_Object must_suffix);
 extern Lisp_Object call_debugger (Lisp_Object arg);
 extern void init_eval_once (void);
-extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...);
-extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object);
-extern Lisp_Object safe_call2 (Lisp_Object, Lisp_Object, Lisp_Object);
+extern Lisp_Object safe_funcall (ptrdiff_t, Lisp_Object*);
+#define safe_calln(...) \
+  CALLMANY (safe_funcall, ((Lisp_Object []) {__VA_ARGS__}))
+
 extern void init_eval (void);
 extern void syms_of_eval (void);
 extern void prog_ignore (Lisp_Object);
 extern void mark_specpdl (union specbinding *first, union specbinding *ptr);
-extern void get_backtrace (Lisp_Object array);
+extern void get_backtrace (Lisp_Object *array, ptrdiff_t size);
 Lisp_Object backtrace_top_function (void);
 extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol);
 void do_debug_on_call (Lisp_Object code, specpdl_ref count);
@@ -4715,7 +4811,6 @@ extern void report_overlay_modification (Lisp_Object, 
Lisp_Object, bool,
                                          Lisp_Object, Lisp_Object, 
Lisp_Object);
 extern bool overlay_touches_p (ptrdiff_t);
 extern Lisp_Object other_buffer_safely (Lisp_Object);
-extern Lisp_Object get_truename_buffer (Lisp_Object);
 extern void init_buffer_once (void);
 extern void init_buffer (void);
 extern void syms_of_buffer (void);
@@ -5243,6 +5338,7 @@ void syms_of_dbusbind (void);
 extern bool profiler_memory_running;
 extern void malloc_probe (size_t);
 extern void syms_of_profiler (void);
+extern void mark_profiler (void);
 
 
 #ifdef DOS_NT
diff --git a/src/lread.c b/src/lread.c
index 1a3b7308021..0952b2b9fbb 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1,6 +1,6 @@
 /* Lisp parsing and input streams.
 
-Copyright (C) 1985-1989, 1993-1995, 1997-2023 Free Software Foundation,
+Copyright (C) 1985-1989, 1993-1995, 1997-2024 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
@@ -124,7 +124,7 @@ static struct android_fd_or_asset invalid_file_stream =
 
 #define file_stream            struct android_fd_or_asset
 #define file_offset            off_t
-#define file_tell(n)           (android_asset_lseek ((n), 0, SEEK_CUR))
+#define file_tell(n)           android_asset_lseek (n, 0, SEEK_CUR)
 #define file_seek              android_asset_lseek
 #define file_stream_valid_p(p) ((p).asset || (p).fd >= 0)
 #define file_stream_close      android_close_asset
@@ -2678,15 +2678,11 @@ readevalloop (Lisp_Object readcharfun,
       if (! HASH_TABLE_P (read_objects_map)
          || XHASH_TABLE (read_objects_map)->count)
        read_objects_map
-         = make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE,
-                            DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
-                            Qnil, false);
+         = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None, false);
       if (! HASH_TABLE_P (read_objects_completed)
          || XHASH_TABLE (read_objects_completed)->count)
        read_objects_completed
-         = make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE,
-                            DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
-                            Qnil, false);
+         = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None, false);
       if (!NILP (Vpurify_flag) && c == '(')
        val = read0 (readcharfun, 0);
       else
@@ -3014,13 +3010,11 @@ read_internal_start (Lisp_Object stream, Lisp_Object 
start, Lisp_Object end,
   if (! HASH_TABLE_P (read_objects_map)
       || XHASH_TABLE (read_objects_map)->count)
     read_objects_map
-      = make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE, DEFAULT_REHASH_SIZE,
-                        DEFAULT_REHASH_THRESHOLD, Qnil, false);
+      = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None, false);
   if (! HASH_TABLE_P (read_objects_completed)
       || XHASH_TABLE (read_objects_completed)->count)
     read_objects_completed
-      = make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE, DEFAULT_REHASH_SIZE,
-                        DEFAULT_REHASH_THRESHOLD, Qnil, false);
+      = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None, false);
 
   if (STRINGP (stream)
       || ((CONSP (stream) && STRINGP (XCAR (stream)))))
@@ -3630,7 +3624,7 @@ read_string_literal (Lisp_Object readcharfun)
 static Lisp_Object
 hash_table_from_plist (Lisp_Object plist)
 {
-  Lisp_Object params[12];
+  Lisp_Object params[4 * 2];
   Lisp_Object *par = params;
 
   /* This is repetitive but fast and simple.  */
@@ -3644,31 +3638,30 @@ hash_table_from_plist (Lisp_Object plist)
       }                                                        \
   } while (0)
 
-  ADDPARAM (size);
   ADDPARAM (test);
   ADDPARAM (weakness);
-  ADDPARAM (rehash_size);
-  ADDPARAM (rehash_threshold);
   ADDPARAM (purecopy);
 
   Lisp_Object data = plist_get (plist, Qdata);
+  if (!(NILP (data) || CONSP (data)))
+    error ("Hash table data is not a list");
+  ptrdiff_t data_len = list_length (data);
+  if (data_len & 1)
+    error ("Hash table data length is odd");
+  *par++ = QCsize;
+  *par++ = make_fixnum (data_len / 2);
 
   /* Now use params to make a new hash table and fill it.  */
   Lisp_Object ht = Fmake_hash_table (par - params, params);
 
-  Lisp_Object last = data;
-  FOR_EACH_TAIL_SAFE (data)
+  while (!NILP (data))
     {
       Lisp_Object key = XCAR (data);
       data = XCDR (data);
-      if (!CONSP (data))
-       break;
       Lisp_Object val = XCAR (data);
-      last = XCDR (data);
       Fputhash (key, val, ht);
+      data = XCDR (data);
     }
-  if (!NILP (last))
-    error ("Hash table data is not a list of even length");
 
   return ht;
 }
@@ -3706,6 +3699,8 @@ vector_from_rev_list (Lisp_Object elems)
   return obj;
 }
 
+static Lisp_Object get_lazy_string (Lisp_Object val);
+
 static Lisp_Object
 bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun)
 {
@@ -3713,49 +3708,50 @@ bytecode_from_rev_list (Lisp_Object elems, Lisp_Object 
readcharfun)
   Lisp_Object *vec = XVECTOR (obj)->contents;
   ptrdiff_t size = ASIZE (obj);
 
+  if (size >= COMPILED_CONSTANTS)
+    {
+      /* Always read 'lazily-loaded' bytecode (generated by the
+         `byte-compile-dynamic' feature prior to Emacs 30) eagerly, to
+         avoid code in the fast path during execution.  */
+      if (CONSP (vec[COMPILED_BYTECODE])
+          && FIXNUMP (XCDR (vec[COMPILED_BYTECODE])))
+        vec[COMPILED_BYTECODE] = get_lazy_string (vec[COMPILED_BYTECODE]);
+
+      /* Lazily-loaded bytecode is represented by the constant slot being nil
+         and the bytecode slot a (lazily loaded) string containing the
+         print representation of (BYTECODE . CONSTANTS).  Unpack the
+         pieces by coerceing the string to unibyte and reading the result.  */
+      if (NILP (vec[COMPILED_CONSTANTS]) && STRINGP (vec[COMPILED_BYTECODE]))
+        {
+          Lisp_Object enc = vec[COMPILED_BYTECODE];
+          Lisp_Object pair = Fread (Fcons (enc, readcharfun));
+          if (!CONSP (pair))
+           invalid_syntax ("Invalid byte-code object", readcharfun);
+
+          vec[COMPILED_BYTECODE] = XCAR (pair);
+          vec[COMPILED_CONSTANTS] = XCDR (pair);
+        }
+    }
+
   if (!(size >= COMPILED_STACK_DEPTH + 1 && size <= COMPILED_INTERACTIVE + 1
        && (FIXNUMP (vec[COMPILED_ARGLIST])
            || CONSP (vec[COMPILED_ARGLIST])
            || NILP (vec[COMPILED_ARGLIST]))
+       && STRINGP (vec[COMPILED_BYTECODE])
+       && VECTORP (vec[COMPILED_CONSTANTS])
        && FIXNATP (vec[COMPILED_STACK_DEPTH])))
     invalid_syntax ("Invalid byte-code object", readcharfun);
 
-  if (load_force_doc_strings
-      && NILP (vec[COMPILED_CONSTANTS])
-      && STRINGP (vec[COMPILED_BYTECODE]))
-    {
-      /* Lazily-loaded bytecode is represented by the constant slot being nil
-        and the bytecode slot a (lazily loaded) string containing the
-        print representation of (BYTECODE . CONSTANTS).  Unpack the
-        pieces by coerceing the string to unibyte and reading the result.  */
-      Lisp_Object enc = vec[COMPILED_BYTECODE];
-      Lisp_Object pair = Fread (Fcons (enc, readcharfun));
-      if (!CONSP (pair))
-       invalid_syntax ("Invalid byte-code object", readcharfun);
+  if (STRING_MULTIBYTE (vec[COMPILED_BYTECODE]))
+    /* BYTESTR must have been produced by Emacs 20.2 or earlier
+       because it produced a raw 8-bit string for byte-code and
+       now such a byte-code string is loaded as multibyte with
+       raw 8-bit characters converted to multibyte form.
+       Convert them back to the original unibyte form.  */
+    vec[COMPILED_BYTECODE] = Fstring_as_unibyte (vec[COMPILED_BYTECODE]);
 
-      vec[COMPILED_BYTECODE] = XCAR (pair);
-      vec[COMPILED_CONSTANTS] = XCDR (pair);
-    }
-
-  if (!((STRINGP (vec[COMPILED_BYTECODE])
-        && VECTORP (vec[COMPILED_CONSTANTS]))
-       || CONSP (vec[COMPILED_BYTECODE])))
-    invalid_syntax ("Invalid byte-code object", readcharfun);
-
-  if (STRINGP (vec[COMPILED_BYTECODE]))
-    {
-      if (STRING_MULTIBYTE (vec[COMPILED_BYTECODE]))
-       {
-         /* BYTESTR must have been produced by Emacs 20.2 or earlier
-            because it produced a raw 8-bit string for byte-code and
-            now such a byte-code string is loaded as multibyte with
-            raw 8-bit characters converted to multibyte form.
-            Convert them back to the original unibyte form.  */
-         vec[COMPILED_BYTECODE] = Fstring_as_unibyte (vec[COMPILED_BYTECODE]);
-       }
-      /* Bytecode must be immovable.  */
-      pin_string (vec[COMPILED_BYTECODE]);
-    }
+  /* Bytecode must be immovable.  */
+  pin_string (vec[COMPILED_BYTECODE]);
 
   XSETPVECTYPE (XVECTOR (obj), PVEC_COMPILED);
   return obj;
@@ -4522,8 +4518,8 @@ read0 (Lisp_Object readcharfun, ptrdiff_t loc_syms)
                        struct Lisp_Hash_Table *h
                          = XHASH_TABLE (read_objects_map);
                        Lisp_Object number = make_fixnum (n);
-                       Lisp_Object hash;
-                       ptrdiff_t i = hash_lookup (h, number, &hash);
+                       hash_hash_t hash;
+                       ptrdiff_t i = hash_lookup_get_hash (h, number, &hash);
                        if (i >= 0)
                          /* Not normal, but input could be malformed.  */
                          set_hash_value_slot (h, i, placeholder);
@@ -4543,7 +4539,7 @@ read0 (Lisp_Object readcharfun, ptrdiff_t loc_syms)
                        /* #N# -- reference to numbered object */
                        struct Lisp_Hash_Table *h
                          = XHASH_TABLE (read_objects_map);
-                       ptrdiff_t i = hash_lookup (h, make_fixnum (n), NULL);
+                       ptrdiff_t i = hash_lookup (h, make_fixnum (n));
                        if (i < 0)
                          invalid_syntax ("#", readcharfun);
                        obj = HASH_VALUE (h, i);
@@ -4870,8 +4866,8 @@ read0 (Lisp_Object readcharfun, ptrdiff_t loc_syms)
 
                struct Lisp_Hash_Table *h2
                  = XHASH_TABLE (read_objects_completed);
-               Lisp_Object hash;
-               ptrdiff_t i = hash_lookup (h2, placeholder, &hash);
+               hash_hash_t hash;
+               ptrdiff_t i = hash_lookup_get_hash (h2, placeholder, &hash);
                eassert (i < 0);
                hash_put (h2, placeholder, Qnil, hash);
                obj = placeholder;
@@ -4885,8 +4881,8 @@ read0 (Lisp_Object readcharfun, ptrdiff_t loc_syms)
                  {
                    struct Lisp_Hash_Table *h2
                      = XHASH_TABLE (read_objects_completed);
-                   Lisp_Object hash;
-                   ptrdiff_t i = hash_lookup (h2, obj, &hash);
+                   hash_hash_t hash;
+                   ptrdiff_t i = hash_lookup_get_hash (h2, obj, &hash);
                    eassert (i < 0);
                    hash_put (h2, obj, Qnil, hash);
                  }
@@ -4897,8 +4893,9 @@ read0 (Lisp_Object readcharfun, ptrdiff_t loc_syms)
 
                /* ...and #n# will use the real value from now on.  */
                struct Lisp_Hash_Table *h = XHASH_TABLE (read_objects_map);
-               Lisp_Object hash;
-               ptrdiff_t i = hash_lookup (h, e->u.numbered.number, &hash);
+               hash_hash_t hash;
+               ptrdiff_t i = hash_lookup_get_hash (h, e->u.numbered.number,
+                                                   &hash);
                eassert (i >= 0);
                set_hash_value_slot (h, i, obj);
              }
@@ -4952,7 +4949,7 @@ substitute_object_recurse (struct subst *subst, 
Lisp_Object subtree)
      by #n=, which means that we can find it as a value in
      COMPLETED.  */
   if (EQ (subst->completed, Qt)
-      || hash_lookup (XHASH_TABLE (subst->completed), subtree, NULL) >= 0)
+      || hash_lookup (XHASH_TABLE (subst->completed), subtree) >= 0)
     subst->seen = Fcons (subtree, subst->seen);
 
   /* Recurse according to subtree's type.
@@ -6340,8 +6337,6 @@ that are loaded before your customizations are read!  */);
   DEFSYM (Qsize, "size");
   DEFSYM (Qpurecopy, "purecopy");
   DEFSYM (Qweakness, "weakness");
-  DEFSYM (Qrehash_size, "rehash-size");
-  DEFSYM (Qrehash_threshold, "rehash-threshold");
 
   DEFSYM (Qchar_from_name, "char-from-name");
   DEFSYM (Qbyte_compile_current_buffer, "byte-compile-current-buffer");
diff --git a/src/macfont.h b/src/macfont.h
index 8afba70e711..45cb1eaa7e4 100644
--- a/src/macfont.h
+++ b/src/macfont.h
@@ -1,5 +1,5 @@
 /* Interface definition for macOS Core text font backend.
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -75,7 +75,7 @@ enum {
 #define kCTVersionNumber10_9 0x00060000
 #endif
 #define MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE \
-  (CFSTR ("MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE"))
+  CFSTR ("MAC_FONT_CHARACTER_SET_STRING_ATTRIBUTE")
 
 typedef const struct _EmacsScreenFont *ScreenFontRef; /* opaque */
 
@@ -85,4 +85,4 @@ extern void macfont_update_antialias_threshold (void);
 
 /* This is an undocumented function. */
 extern void CGContextSetFontSmoothingStyle(CGContextRef, int)
-  __attribute__((weak_import));
+  __attribute__ ((weak_import));
diff --git a/src/macfont.m b/src/macfont.m
index 9f9f6f4efaf..e3b3d40df43 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -1,5 +1,5 @@
 /* Font driver on macOS Core text.
-   Copyright (C) 2009-2023 Free Software Foundation, Inc.
+   Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -855,21 +855,42 @@ macfont_store_descriptor_attributes (CTFontDescriptorRef 
desc,
       struct {
         enum font_property_index index;
         CFStringRef trait;
-        CGPoint points[6];
-       CGFloat (*adjust_func) (CTFontDescriptorRef, CGFloat);
-      } numeric_traits[] =
-          {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
-            {{-0.4, 50},       /* light */
-             {-0.24, 87.5},    /* (semi-light + normal) / 2 */
-             {0, 80},          /* normal */
-             {0.24, 140},      /* (semi-bold + normal) / 2 */
-             {0.4, 200},       /* bold */
-             {CGFLOAT_MAX, CGFLOAT_MAX}},
-           mac_font_descriptor_get_adjusted_weight},
-           {FONT_SLANT_INDEX, kCTFontSlantTrait,
-            {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL},
-           {FONT_WIDTH_INDEX, kCTFontWidthTrait,
-            {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL}};
+        CGPoint points[12];
+        CGFloat (*adjust_func) (CTFontDescriptorRef, CGFloat);
+      } numeric_traits[] = {
+        { FONT_WEIGHT_INDEX,
+          kCTFontWeightTrait,
+          { { -0.6, 0 },    /* thin */
+            { -0.4, 40 },   /* ultra-light, ultralight, extra-light, 
extralight  */
+            { -0.23, 50 },  /* light */
+            { -0.115, 55 }, /* semi-light, semilight, demilight */
+            { 0, 80 },      /* regular, normal, unspecified, book */
+            { 0.2, 100 },   /* medium */
+            { 0.3, 180 },   /* semi-bold, semibold, demibold, demi-bold, demi 
*/
+            { 0.4, 200 },   /* bold */
+            { 0.6, 205 },   /* extra-bold, extrabold, ultra-bold, ultrabold */
+            { 0.8, 210 },   /* black, heavy */
+            { 1, 250 },     /* ultra-heavy, ultraheavy */
+            { CGFLOAT_MAX, CGFLOAT_MAX } },
+          mac_font_descriptor_get_adjusted_weight },
+        { FONT_SLANT_INDEX,
+          kCTFontSlantTrait,
+          { { 0, 100 }, { 0.1, 200 }, { CGFLOAT_MAX, CGFLOAT_MAX } },
+          NULL },
+        { FONT_WIDTH_INDEX,
+          kCTFontWidthTrait,
+          { { -0.4, 50 }, /* ultra-condensed, ultracondensed */
+            { -0.3, 63 }, /* extra-condensed, extracondensed */
+            { -0.2, 75 }, /* condensed, compressed, narrow */
+            { -0.1, 87 }, /* semi-condensed, semicondensed, demicondensed */
+            { 0, 100 },   /* normal, medium, regular, unspecified */
+            { 0.1, 113 }, /* semi-expanded, semiexpanded, demiexpanded */
+            { 0.2, 125 }, /* expanded */
+            { 0.3, 150 }, /* extra-expanded, extraexpanded */
+            { 0.4, 200 }, /* ultra-expanded, ultraexpanded, wide */
+            { CGFLOAT_MAX, CGFLOAT_MAX } },
+          NULL }
+      };
       int i;
 
       for (i = 0; i < ARRAYELTS (numeric_traits); i++)
@@ -980,7 +1001,7 @@ macfont_invalidate_family_cache (void)
       ptrdiff_t i, size = HASH_TABLE_SIZE (h);
 
       for (i = 0; i < size; ++i)
-       if (!NILP (HASH_HASH (h, i)))
+       if (!hash_unused_entry_key_p (HASH_KEY (h, i)))
          {
            Lisp_Object value = HASH_VALUE (h, i);
 
@@ -997,7 +1018,7 @@ macfont_get_family_cache_if_present (Lisp_Object symbol, 
CFStringRef *string)
   if (HASH_TABLE_P (macfont_family_cache))
     {
       struct Lisp_Hash_Table *h = XHASH_TABLE (macfont_family_cache);
-      ptrdiff_t i = hash_lookup (h, symbol, NULL);
+      ptrdiff_t i = hash_lookup (h, symbol);
 
       if (i >= 0)
        {
@@ -1017,13 +1038,14 @@ macfont_set_family_cache (Lisp_Object symbol, 
CFStringRef string)
 {
   struct Lisp_Hash_Table *h;
   ptrdiff_t i;
-  Lisp_Object hash, value;
+  Lisp_Object value;
 
   if (!HASH_TABLE_P (macfont_family_cache))
     macfont_family_cache = CALLN (Fmake_hash_table, QCtest, Qeq);
 
   h = XHASH_TABLE (macfont_family_cache);
-  i = hash_lookup (h, symbol, &hash);
+  hash_hash_t hash;
+  i = hash_lookup_get_hash (h, symbol, &hash);
   value = string ? make_mint_ptr ((void *) CFRetain (string)) : Qnil;
   if (i >= 0)
     {
@@ -1940,19 +1962,38 @@ macfont_create_attributes_with_spec (Lisp_Object spec)
   struct {
     enum font_property_index index;
     CFStringRef trait;
-    CGPoint points[6];
-  } numeric_traits[] =
-      {{FONT_WEIGHT_INDEX, kCTFontWeightTrait,
-        {{-0.4, 50},           /* light */
-         {-0.24, 87.5},                /* (semi-light + normal) / 2 */
-         {0, 100},             /* normal */
-         {0.24, 140},          /* (semi-bold + normal) / 2 */
-         {0.4, 200},           /* bold */
-         {CGFLOAT_MAX, CGFLOAT_MAX}}},
-       {FONT_SLANT_INDEX, kCTFontSlantTrait,
-        {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}},
-       {FONT_WIDTH_INDEX, kCTFontWidthTrait,
-        {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}};
+    CGPoint points[12];
+  } numeric_traits[] = {
+    { FONT_WEIGHT_INDEX,
+      kCTFontWeightTrait,
+      { { -0.6, 0 },    /* thin */
+        { -0.4, 40 },   /* ultra-light, ultralight, extra-light, extralight  */
+        { -0.23, 50 },  /* light */
+        { -0.115, 55 }, /* semi-light, semilight, demilight */
+        { 0, 80 },      /* regular, normal, unspecified, book */
+        { 0.2, 100 },   /* medium */
+        { 0.3, 180 },   /* semi-bold, semibold, demibold, demi-bold, demi */
+        { 0.4, 200 },   /* bold */
+        { 0.6, 205 },   /* extra-bold, extrabold, ultra-bold, ultrabold */
+        { 0.8, 210 },   /* black, heavy */
+        { 1, 250 },     /* ultra-heavy, ultraheavy */
+        { CGFLOAT_MAX, CGFLOAT_MAX } } },
+    { FONT_SLANT_INDEX,
+      kCTFontSlantTrait,
+      { { 0, 100 }, { 0.1, 200 }, { CGFLOAT_MAX, CGFLOAT_MAX } } },
+    { FONT_WIDTH_INDEX,
+      kCTFontWidthTrait,
+      { { -0.4, 50 }, /* ultra-condensed, ultracondensed */
+        { -0.3, 63 }, /* extra-condensed, extracondensed */
+        { -0.2, 75 }, /* condensed, compressed, narrow */
+        { -0.1, 87 }, /* semi-condensed, semicondensed, demicondensed */
+        { 0, 100 },   /* normal, medium, regular, unspecified */
+        { 0.1, 113 }, /* semi-expanded, semiexpanded, demiexpanded */
+        { 0.2, 125 }, /* expanded */
+        { 0.3, 150 }, /* extra-expanded, extraexpanded */
+        { 0.4, 200 }, /* ultra-expanded, ultraexpanded, wide */
+        { CGFLOAT_MAX, CGFLOAT_MAX } } }
+  };
 
   registry = AREF (spec, FONT_REGISTRY_INDEX);
   if (NILP (registry)
diff --git a/src/macros.c b/src/macros.c
index d1541d2817f..5f71bcbd361 100644
--- a/src/macros.c
+++ b/src/macros.c
@@ -1,6 +1,6 @@
 /* Keyboard macros.
 
-Copyright (C) 1985-1986, 1993, 2000-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-1986, 1993, 2000-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/macros.h b/src/macros.h
index a7c42f753b4..51599a29bcd 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -1,5 +1,5 @@
 /* Definitions for keyboard macro interpretation in GNU Emacs.
-   Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/marker.c b/src/marker.c
index 7b15cd62f1e..0101e144b4d 100644
--- a/src/marker.c
+++ b/src/marker.c
@@ -1,5 +1,5 @@
 /* Markers: examining, setting and deleting.
-   Copyright (C) 1985, 1997-1998, 2001-2023 Free Software Foundation,
+   Copyright (C) 1985, 1997-1998, 2001-2024 Free Software Foundation,
    Inc.
 
 This file is part of GNU Emacs.
@@ -20,6 +20,11 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
+/* Work around GCC bug 113253.  */
+#if 13 <= __GNUC__
+# pragma GCC diagnostic ignored "-Wanalyzer-deref-before-check"
+#endif
+
 #include "lisp.h"
 #include "character.h"
 #include "buffer.h"
diff --git a/src/menu.c b/src/menu.c
index 6ab34a16996..de4d0964e9c 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -1,6 +1,6 @@
 /* Platform-independent code for terminal communications.
 
-Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2023 Free Software
+Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/menu.h b/src/menu.h
index ff27509da44..8b4065dad53 100644
--- a/src/menu.h
+++ b/src/menu.h
@@ -1,5 +1,5 @@
 /* Functions to manipulate menus.
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/minibuf.c b/src/minibuf.c
index 58adde1bf66..7c0c9799a60 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -1,6 +1,6 @@
 /* Minibuffer input and completion.
 
-Copyright (C) 1985-1986, 1993-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-1986, 1993-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -1680,8 +1680,8 @@ or from one of the possible completions.  */)
       else /* if (type == hash_table) */
        {
          while (idx < HASH_TABLE_SIZE (XHASH_TABLE (collection))
-                && BASE_EQ (HASH_KEY (XHASH_TABLE (collection), idx),
-                            Qunbound))
+                && hash_unused_entry_key_p (HASH_KEY (XHASH_TABLE (collection),
+                                                      idx)))
            idx++;
          if (idx >= HASH_TABLE_SIZE (XHASH_TABLE (collection)))
            break;
@@ -1918,8 +1918,8 @@ with a space are ignored unless STRING itself starts with 
a space.  */)
       else /* if (type == 3) */
        {
          while (idx < HASH_TABLE_SIZE (XHASH_TABLE (collection))
-                && BASE_EQ (HASH_KEY (XHASH_TABLE (collection), idx),
-                            Qunbound))
+                && hash_unused_entry_key_p (HASH_KEY (XHASH_TABLE (collection),
+                                                      idx)))
            idx++;
          if (idx >= HASH_TABLE_SIZE (XHASH_TABLE (collection)))
            break;
@@ -2059,8 +2059,7 @@ If COLLECTION is a function, it is called with three 
arguments:
 the values STRING, PREDICATE and `lambda'.  */)
   (Lisp_Object string, Lisp_Object collection, Lisp_Object predicate)
 {
-  Lisp_Object tail, tem = Qnil;
-  ptrdiff_t i = 0;
+  Lisp_Object tail, tem = Qnil, arg = Qnil;
 
   CHECK_STRING (string);
 
@@ -2079,7 +2078,7 @@ the values STRING, PREDICATE and `lambda'.  */)
                      SBYTES (string));
       if (completion_ignore_case && !SYMBOLP (tem))
        {
-         for (i = ASIZE (collection) - 1; i >= 0; i--)
+         for (ptrdiff_t i = ASIZE (collection) - 1; i >= 0; i--)
            {
              tail = AREF (collection, i);
              if (SYMBOLP (tail))
@@ -2107,24 +2106,27 @@ the values STRING, PREDICATE and `lambda'.  */)
   else if (HASH_TABLE_P (collection))
     {
       struct Lisp_Hash_Table *h = XHASH_TABLE (collection);
-      i = hash_lookup (h, string, NULL);
+      ptrdiff_t i = hash_lookup (h, string);
       if (i >= 0)
         {
           tem = HASH_KEY (h, i);
+          arg = HASH_VALUE (h, i);
           goto found_matching_key;
         }
       else
-       for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
+       DOHASH (h, k, v)
           {
-            tem = HASH_KEY (h, i);
-            if (BASE_EQ (tem, Qunbound)) continue;
+            tem = k;
             Lisp_Object strkey = (SYMBOLP (tem) ? Fsymbol_name (tem) : tem);
             if (!STRINGP (strkey)) continue;
             if (BASE_EQ (Fcompare_strings (string, Qnil, Qnil,
                                           strkey, Qnil, Qnil,
                                           completion_ignore_case ? Qt : Qnil),
-                    Qt))
-              goto found_matching_key;
+                        Qt))
+             {
+                arg = v;
+                goto found_matching_key;
+              }
           }
       return Qnil;
     found_matching_key: ;
@@ -2141,7 +2143,7 @@ the values STRING, PREDICATE and `lambda'.  */)
   if (!NILP (predicate))
     {
       return HASH_TABLE_P (collection)
-       ? call2 (predicate, tem, HASH_VALUE (XHASH_TABLE (collection), i))
+       ? call2 (predicate, tem, arg)
        : call1 (predicate, tem);
     }
   else
@@ -2320,7 +2322,6 @@ syms_of_minibuf (void)
 
   DEFSYM (Qcurrent_input_method, "current-input-method");
   DEFSYM (Qactivate_input_method, "activate-input-method");
-  DEFSYM (Qcase_fold_search, "case-fold-search");
   DEFSYM (Qmetadata, "metadata");
   DEFSYM (Qcycle_sort_function, "cycle-sort-function");
 
diff --git a/src/msdos.c b/src/msdos.c
index 5dd7c1573c4..7e78c35027e 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -1,6 +1,6 @@
 /* MS-DOS specific C utilities.          -*- coding: cp850 -*-
 
-Copyright (C) 1993-1997, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1997, 1999-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -2811,14 +2811,10 @@ IT_menu_make_room (XMenu *menu)
   else if (menu->allocated == menu->count)
     {
       int count = menu->allocated = menu->allocated + 10;
-      menu->text
-       = (char **) xrealloc (menu->text, count * sizeof (char *));
-      menu->submenu
-       = (XMenu **) xrealloc (menu->submenu, count * sizeof (XMenu *));
-      menu->panenumber
-       = (int *) xrealloc (menu->panenumber, count * sizeof (int));
-      menu->help_text
-       = (const char **) xrealloc (menu->help_text, count * sizeof (char *));
+      menu->text = xrealloc (menu->text, count * sizeof (char *));
+      menu->submenu = xrealloc (menu->submenu, count * sizeof (XMenu *));
+      menu->panenumber = xrealloc (menu->panenumber, count * sizeof (int));
+      menu->help_text = xrealloc (menu->help_text, count * sizeof (char *));
     }
 }
 
@@ -2869,7 +2865,7 @@ IT_menu_calc_size (XMenu *menu, int *width, int *height)
   do                                                      \
     {                                                     \
       (GLYPH).type = CHAR_GLYPH;                          \
-      SET_CHAR_GLYPH ((GLYPH), CODE, FACE_ID, PADDING_P);  \
+      SET_CHAR_GLYPH (GLYPH, CODE, FACE_ID, PADDING_P);           \
       (GLYPH).charpos = -1;                               \
     }                                                     \
   while (0)
diff --git a/src/msdos.h b/src/msdos.h
index 94878d25b35..b245d9ea761 100644
--- a/src/msdos.h
+++ b/src/msdos.h
@@ -1,5 +1,5 @@
 /* MS-DOS specific C utilities, interface.
-   Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/nsfns.m b/src/nsfns.m
index 33c6020ad51..c521140bd68 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -1,6 +1,6 @@
 /* Functions for the NeXT/Open/GNUstep and macOS window system.
 
-Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2023 Free Software
+Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/nsfont.m b/src/nsfont.m
index eaa5c771457..4e1d85a5c4a 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -1,6 +1,6 @@
 /* Font back-end driver for the GNUstep window system.
    See font.h
-   Copyright (C) 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -601,7 +601,7 @@ static NSString
 {
     Lisp_Object script = assq_no_quit (XCAR (otf), Votf_script_alist);
     return CONSP (script)
-       ? [NSString stringWithLispString: SYMBOL_NAME (XCDR ((script)))]
+       ? [NSString stringWithLispString: SYMBOL_NAME (XCDR (script))]
        : @"";
 }
 
@@ -1035,7 +1035,7 @@ nsfont_open (struct frame *f, Lisp_Object font_entity, 
int pixel_size)
     font->underline_position = lrint (font_info->underpos);
     font->underline_thickness = lrint (font_info->underwidth);
 
-    font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
+    font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil, Qnil);
     font->props[FONT_FULLNAME_INDEX] = build_unibyte_string (font_info->name);
   }
   unblock_input ();
diff --git a/src/nsgui.h b/src/nsgui.h
index 469aef13070..de679075d2b 100644
--- a/src/nsgui.h
+++ b/src/nsgui.h
@@ -1,5 +1,5 @@
 /* Definitions and headers for communication on the NeXT/Open/GNUstep API.
-   Copyright (C) 1995, 2005, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 1995, 2005, 2008-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/nsimage.m b/src/nsimage.m
index b33124900bb..ee72d6e0ea1 100644
--- a/src/nsimage.m
+++ b/src/nsimage.m
@@ -1,5 +1,5 @@
 /* Image support for the NeXT/Open/GNUstep and macOS window system.
-   Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2023 Free Software
+   Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/nsmenu.m b/src/nsmenu.m
index fb356c6b861..0d21f7d03d3 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -1,5 +1,5 @@
 /* NeXT/Open/GNUstep and macOS Cocoa menu and toolbar module.
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/nsselect.m b/src/nsselect.m
index 120bce75bce..bb6679cd2ab 100644
--- a/src/nsselect.m
+++ b/src/nsselect.m
@@ -1,5 +1,5 @@
 /* NeXT/Open/GNUstep / macOS Cocoa selection processing for emacs.
-   Copyright (C) 1993-1994, 2005-2006, 2008-2023 Free Software
+   Copyright (C) 1993-1994, 2005-2006, 2008-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/nsterm.h b/src/nsterm.h
index cb162039ad8..ae940ec5b4f 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -1,6 +1,6 @@
 /* -*- objc -*- */
 /* Definitions and headers for communication with NeXT/Open/GNUstep API.
-   Copyright (C) 1989, 1993, 2005, 2008-2023 Free Software Foundation,
+   Copyright (C) 1989, 1993, 2005, 2008-2024 Free Software Foundation,
    Inc.
 
 This file is part of GNU Emacs.
@@ -278,9 +278,9 @@ char const * nstrace_fullscreen_type_name (int);
 
 
 #define NSTRACE_WHEN(cond, ...)                                         \
-  __attribute__((cleanup(nstrace_restore_global_trace_state)))          \
+  __attribute__ ((cleanup (nstrace_restore_global_trace_state)))        \
   int nstrace_saved_enabled_global = nstrace_enabled_global;            \
-  __attribute__((cleanup(nstrace_leave)))                               \
+  __attribute__ ((cleanup (nstrace_leave)))                             \
   int nstrace_enabled = nstrace_enabled_global && (cond);               \
   if (nstrace_enabled) { ++nstrace_depth; }                             \
   else { nstrace_enabled_global = 0; }                                  \
@@ -1180,6 +1180,7 @@ extern void  ns_retain_object (void *obj);
 extern void *ns_alloc_autorelease_pool (void);
 extern void ns_release_autorelease_pool (void *);
 extern const char *ns_get_defaults_value (const char *key);
+extern void ns_init_pool (void);
 extern void ns_init_locale (void);
 
 /* in nsmenu */
@@ -1289,7 +1290,7 @@ extern char gnustep_base_version[];  /* version tracking 
*/
 /* Little utility macros */
 #define IN_BOUND(min, x, max) (((x) < (min)) \
                                 ? (min) : (((x)>(max)) ? (max) : (x)))
-#define SCREENMAXBOUND(x) (IN_BOUND (-SCREENMAX, x, SCREENMAX))
+#define SCREENMAXBOUND(x) IN_BOUND (-SCREENMAX, x, SCREENMAX)
 
 
 #ifdef NS_IMPL_COCOA
diff --git a/src/nsterm.m b/src/nsterm.m
index 46a5e8870e8..f094b145fe3 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1,6 +1,6 @@
 /* NeXT/Open/GNUstep / macOS communication module.      -*- coding: utf-8 -*-
 
-Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2023 Free Software
+Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -549,6 +549,15 @@ ns_relocate (const char *epath)
 }
 
 
+void
+ns_init_pool (void)
+/* Initialize the 'outerpool' autorelease pool.  This should be called
+   from main before any Objective C code is run.  */
+{
+  outerpool = [[NSAutoreleasePool alloc] init];
+}
+
+
 void
 ns_init_locale (void)
 /* macOS doesn't set any environment variables for the locale when run
@@ -7058,13 +7067,9 @@ ns_create_font_panel_buttons (id target, SEL select, SEL 
cancel_action)
 static Lisp_Object
 ns_in_echo_area_1 (void *ptr)
 {
-  Lisp_Object in_echo_area;
-  specpdl_ref count;
-
-  count = SPECPDL_INDEX ();
+  const specpdl_ref count = SPECPDL_INDEX ();
   specbind (Qinhibit_quit, Qt);
-  in_echo_area = safe_call (1, Qns_in_echo_area);
-
+  const Lisp_Object in_echo_area = safe_calln (Qns_in_echo_area);
   return unbind_to (count, in_echo_area);
 }
 
@@ -8829,8 +8834,8 @@ ns_in_echo_area (void)
      so call this function instead.  */
   XSETFRAME (frame, emacsframe);
 
-  safe_call (4, Vns_drag_motion_function, frame,
-            make_fixnum (x), make_fixnum (y));
+  safe_calln (Vns_drag_motion_function, frame,
+             make_fixnum (x), make_fixnum (y));
 
   redisplay ();
 #endif
diff --git a/src/nsxwidget.h b/src/nsxwidget.h
index 2b5596f905e..e26564b3a96 100644
--- a/src/nsxwidget.h
+++ b/src/nsxwidget.h
@@ -1,6 +1,6 @@
 /* Header for NS Cocoa part of xwidget and webkit widget.
 
-Copyright (C) 2019-2023 Free Software Foundation, Inc.
+Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/nsxwidget.m b/src/nsxwidget.m
index 0e00589bb7f..2d83e8815a2 100644
--- a/src/nsxwidget.m
+++ b/src/nsxwidget.m
@@ -1,6 +1,6 @@
 /* NS Cocoa part implementation of xwidget and webkit widget.
 
-Copyright (C) 2019-2023 Free Software Foundation, Inc.
+Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/pdumper.c b/src/pdumper.c
index 831267cdd18..ee554cda55a 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2023 Free Software Foundation, Inc.
+/* Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -1226,7 +1226,7 @@ dump_queue_dequeue (struct dump_queue *dump_queue, 
dump_off basis)
      dump_tailq_length (&dump_queue->zero_weight_objects),
      dump_tailq_length (&dump_queue->one_weight_normal_objects),
      dump_tailq_length (&dump_queue->one_weight_strong_objects),
-     XHASH_TABLE (dump_queue->link_weights)->count);
+     (ptrdiff_t) XHASH_TABLE (dump_queue->link_weights)->count);
 
   static const int nr_candidates = 3;
   struct candidate
@@ -1331,13 +1331,7 @@ dump_queue_dequeue (struct dump_queue *dump_queue, 
dump_off basis)
 static bool
 dump_object_needs_dumping_p (Lisp_Object object)
 {
-  /* Some objects, like symbols, are self-representing because they
-     have invariant bit patterns, but sometimes these objects have
-     associated data too, and these data-carrying objects need to be
-     included in the dump despite all references to them being
-     bitwise-invariant.  */
-  return (!dump_object_self_representing_p (object)
-         || dump_object_emacs_ptr (object));
+  return !(FIXNUMP (object));
 }
 
 static void
@@ -1864,11 +1858,10 @@ dump_field_lv_or_rawptr (struct dump_context *ctx,
 
 /* Set a pointer field on an output object during dump.
 
-   CTX is the dump context.  OFFSET is the offset at which the current
-   object starts.  OUT is a pointer to the dump output object.
-   IN_START is the start of the current Emacs object.  IN_FIELD is a
-   pointer to the field in that object.  TYPE is the type of pointer
-   to which IN_FIELD points.
+   CTX is the dump context.  OUT is a pointer to the dump output
+   object.  IN_START is the start of the current Emacs object.
+   IN_FIELD is a pointer to the field in that object.  TYPE is the
+   type of pointer to which IN_FIELD points.
  */
 static void
 dump_field_lv_rawptr (struct dump_context *ctx,
@@ -1883,8 +1876,7 @@ dump_field_lv_rawptr (struct dump_context *ctx,
 
 /* Set a Lisp_Object field on an output object during dump.
 
-   CTX is a dump context.  OFFSET is the offset at which the current
-   object starts.  OUT is a pointer to the dump output object.
+   CTX is a dump context.  OUT is a pointer to the dump output object.
    IN_START is the start of the current Emacs object.  IN_FIELD is a
    pointer to a Lisp_Object field in that object.
 
@@ -2646,73 +2638,88 @@ dump_vectorlike_generic (struct dump_context *ctx,
   return offset;
 }
 
-/* Return a vector of KEY, VALUE pairs in the given hash table H.  The
-   first H->count pairs are valid, and the rest are unbound.  */
-static Lisp_Object
+/* Return a vector of KEY, VALUE pairs in the given hash table H.
+   No room for growth is included.  */
+static Lisp_Object *
 hash_table_contents (struct Lisp_Hash_Table *h)
 {
-  if (h->test.hashfn == hashfn_user_defined)
-    error ("cannot dump hash tables with user-defined tests");  /* Bug#36769 */
-
-  ptrdiff_t size = HASH_TABLE_SIZE (h);
-  Lisp_Object key_and_value = make_uninit_vector (2 * size);
+  ptrdiff_t size = h->count;
+  Lisp_Object *key_and_value = hash_table_alloc_bytes (2 * size
+                                                      * sizeof *key_and_value);
   ptrdiff_t n = 0;
 
-  /* Make sure key_and_value ends up in the same order; charset.c
-     relies on it by expecting hash table indices to stay constant
-     across the dump.  */
-  for (ptrdiff_t i = 0; i < size; i++)
-    if (!NILP (HASH_HASH (h, i)))
-      {
-       ASET (key_and_value, n++, HASH_KEY (h, i));
-       ASET (key_and_value, n++, HASH_VALUE (h, i));
-      }
-
-  while (n < 2 * size)
+  DOHASH (h, k, v)
     {
-      ASET (key_and_value, n++, Qunbound);
-      ASET (key_and_value, n++, Qnil);
+      key_and_value[n++] = k;
+      key_and_value[n++] = v;
     }
 
   return key_and_value;
 }
 
-static dump_off
+static void
 dump_hash_table_list (struct dump_context *ctx)
 {
   if (!NILP (ctx->hash_tables))
-    return dump_object (ctx, CALLN (Fapply, Qvector, ctx->hash_tables));
-  else
-    return 0;
+    dump_object (ctx, CALLN (Fvconcat, ctx->hash_tables));
 }
 
+static hash_table_std_test_t
+hash_table_std_test (const struct hash_table_test *t)
+{
+  if (BASE_EQ (t->name, Qeq))
+    return Test_eq;
+  if (BASE_EQ (t->name, Qeql))
+    return Test_eql;
+  if (BASE_EQ (t->name, Qequal))
+    return Test_equal;
+  error ("cannot dump hash tables with user-defined tests");  /* Bug#36769 */
+}
+
+/* Compact contents and discard inessential information from a hash table,
+   preparing it for dumping.
+   See `hash_table_thaw' for the code that restores the object to a usable
+   state. */
 static void
 hash_table_freeze (struct Lisp_Hash_Table *h)
 {
-  ptrdiff_t npairs = ASIZE (h->key_and_value) / 2;
   h->key_and_value = hash_table_contents (h);
-  h->next = h->hash = make_fixnum (npairs);
-  h->index = make_fixnum (ASIZE (h->index));
-  h->next_free = (npairs == h->count ? -1 : h->count);
+  h->next = NULL;
+  h->hash = NULL;
+  h->index = NULL;
+  h->table_size = 0;
+  h->index_size = 0;
+  h->frozen_test = hash_table_std_test (h->test);
+  h->test = NULL;
 }
 
-static void
-hash_table_thaw (Lisp_Object hash)
+static dump_off
+dump_hash_table_contents (struct dump_context *ctx, struct Lisp_Hash_Table *h)
 {
-  struct Lisp_Hash_Table *h = XHASH_TABLE (hash);
-  h->hash = make_nil_vector (XFIXNUM (h->hash));
-  h->next = Fmake_vector (h->next, make_fixnum (-1));
-  h->index = Fmake_vector (h->index, make_fixnum (-1));
+  dump_align_output (ctx, DUMP_ALIGNMENT);
+  dump_off start_offset = ctx->offset;
+  ptrdiff_t n = 2 * h->count;
+
+  struct dump_flags old_flags = ctx->flags;
+  ctx->flags.pack_objects = true;
+
+  for (ptrdiff_t i = 0; i < n; i++)
+    {
+      Lisp_Object out;
+      const Lisp_Object *slot = &h->key_and_value[i];
+      dump_object_start (ctx, &out, sizeof out);
+      dump_field_lv (ctx, &out, slot, slot, WEIGHT_STRONG);
+      dump_object_finish (ctx, &out, sizeof out);
+    }
 
-  hash_table_rehash (hash);
+  ctx->flags = old_flags;
+  return start_offset;
 }
 
 static dump_off
-dump_hash_table (struct dump_context *ctx,
-                 Lisp_Object object,
-                 dump_off offset)
+dump_hash_table (struct dump_context *ctx, Lisp_Object object)
 {
-#if CHECK_STRUCTS && !defined HASH_Lisp_Hash_Table_6D63EDB618
+#if CHECK_STRUCTS && !defined HASH_Lisp_Hash_Table_313A489F0A
 # error "Lisp_Hash_Table changed. See CHECK_STRUCTS comment in config.h."
 #endif
   const struct Lisp_Hash_Table *hash_in = XHASH_TABLE (object);
@@ -2724,30 +2731,27 @@ dump_hash_table (struct dump_context *ctx,
 
   START_DUMP_PVEC (ctx, &hash->header, struct Lisp_Hash_Table, out);
   dump_pseudovector_lisp_fields (ctx, &out->header, &hash->header);
-  /* TODO: dump the hash bucket vectors synchronously here to keep
-     them as close to the hash table as possible.  */
   DUMP_FIELD_COPY (out, hash, count);
-  DUMP_FIELD_COPY (out, hash, next_free);
+  DUMP_FIELD_COPY (out, hash, weakness);
   DUMP_FIELD_COPY (out, hash, purecopy);
   DUMP_FIELD_COPY (out, hash, mutable);
-  DUMP_FIELD_COPY (out, hash, rehash_threshold);
-  DUMP_FIELD_COPY (out, hash, rehash_size);
-  dump_field_lv (ctx, out, hash, &hash->key_and_value, WEIGHT_STRONG);
-  dump_field_lv (ctx, out, hash, &hash->test.name, WEIGHT_STRONG);
-  dump_field_lv (ctx, out, hash, &hash->test.user_hash_function,
-                 WEIGHT_STRONG);
-  dump_field_lv (ctx, out, hash, &hash->test.user_cmp_function,
-                 WEIGHT_STRONG);
-  dump_field_emacs_ptr (ctx, out, hash, &hash->test.cmpfn);
-  dump_field_emacs_ptr (ctx, out, hash, &hash->test.hashfn);
+  DUMP_FIELD_COPY (out, hash, frozen_test);
+  if (hash->key_and_value)
+    dump_field_fixup_later (ctx, out, hash, &hash->key_and_value);
   eassert (hash->next_weak == NULL);
-  return finish_dump_pvec (ctx, &out->header);
+  dump_off offset = finish_dump_pvec (ctx, &out->header);
+  if (hash->key_and_value)
+    dump_remember_fixup_ptr_raw
+      (ctx,
+       offset + dump_offsetof (struct Lisp_Hash_Table, key_and_value),
+       dump_hash_table_contents (ctx, hash));
+  return offset;
 }
 
 static dump_off
 dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
 {
-#if CHECK_STRUCTS && !defined HASH_buffer_EB0A5191C5
+#if CHECK_STRUCTS && !defined HASH_buffer_EBBA38AEFA
 # error "buffer changed. See CHECK_STRUCTS comment in config.h."
 #endif
   struct buffer munged_buffer = *in_buffer;
@@ -3026,7 +3030,7 @@ dump_vectorlike (struct dump_context *ctx,
     case PVEC_BOOL_VECTOR:
       return dump_bool_vector(ctx, v);
     case PVEC_HASH_TABLE:
-      return dump_hash_table (ctx, lv, offset);
+      return dump_hash_table (ctx, lv);
     case PVEC_BUFFER:
       return dump_buffer (ctx, XBUFFER (lv));
     case PVEC_SUBR:
@@ -3205,37 +3209,42 @@ dump_object_for_offset (struct dump_context *ctx, 
Lisp_Object object)
 static dump_off
 dump_charset (struct dump_context *ctx, int cs_i)
 {
-#if CHECK_STRUCTS && !defined (HASH_charset_317C49E291)
+#if CHECK_STRUCTS && !defined (HASH_charset_E31F4B5D96)
 # error "charset changed. See CHECK_STRUCTS comment in config.h."
 #endif
-  dump_align_output (ctx, alignof (struct charset));
+  /* We can't change the alignment here, because ctx->offset is what
+     will be used for the whole array.  */
+  eassert (ctx->offset % alignof (struct charset) == 0);
   const struct charset *cs = charset_table + cs_i;
   struct charset out;
   dump_object_start (ctx, &out, sizeof (out));
-  DUMP_FIELD_COPY (&out, cs, id);
-  DUMP_FIELD_COPY (&out, cs, hash_index);
-  DUMP_FIELD_COPY (&out, cs, dimension);
-  memcpy (out.code_space, &cs->code_space, sizeof (cs->code_space));
-  if (cs_i < charset_table_used && cs->code_space_mask)
-    dump_field_fixup_later (ctx, &out, cs, &cs->code_space_mask);
-  DUMP_FIELD_COPY (&out, cs, code_linear_p);
-  DUMP_FIELD_COPY (&out, cs, iso_chars_96);
-  DUMP_FIELD_COPY (&out, cs, ascii_compatible_p);
-  DUMP_FIELD_COPY (&out, cs, supplementary_p);
-  DUMP_FIELD_COPY (&out, cs, compact_codes_p);
-  DUMP_FIELD_COPY (&out, cs, unified_p);
-  DUMP_FIELD_COPY (&out, cs, iso_final);
-  DUMP_FIELD_COPY (&out, cs, iso_revision);
-  DUMP_FIELD_COPY (&out, cs, emacs_mule_id);
-  DUMP_FIELD_COPY (&out, cs, method);
-  DUMP_FIELD_COPY (&out, cs, min_code);
-  DUMP_FIELD_COPY (&out, cs, max_code);
-  DUMP_FIELD_COPY (&out, cs, char_index_offset);
-  DUMP_FIELD_COPY (&out, cs, min_char);
-  DUMP_FIELD_COPY (&out, cs, max_char);
-  DUMP_FIELD_COPY (&out, cs, invalid_code);
-  memcpy (out.fast_map, &cs->fast_map, sizeof (cs->fast_map));
-  DUMP_FIELD_COPY (&out, cs, code_offset);
+  if (cs_i < charset_table_used) /* Don't look at uninitialized data.  */
+    {
+      DUMP_FIELD_COPY (&out, cs, id);
+      dump_field_lv (ctx, &out, cs, &cs->attributes, WEIGHT_NORMAL);
+      DUMP_FIELD_COPY (&out, cs, dimension);
+      memcpy (out.code_space, &cs->code_space, sizeof (cs->code_space));
+      if (cs->code_space_mask)
+        dump_field_fixup_later (ctx, &out, cs, &cs->code_space_mask);
+      DUMP_FIELD_COPY (&out, cs, code_linear_p);
+      DUMP_FIELD_COPY (&out, cs, iso_chars_96);
+      DUMP_FIELD_COPY (&out, cs, ascii_compatible_p);
+      DUMP_FIELD_COPY (&out, cs, supplementary_p);
+      DUMP_FIELD_COPY (&out, cs, compact_codes_p);
+      DUMP_FIELD_COPY (&out, cs, unified_p);
+      DUMP_FIELD_COPY (&out, cs, iso_final);
+      DUMP_FIELD_COPY (&out, cs, iso_revision);
+      DUMP_FIELD_COPY (&out, cs, emacs_mule_id);
+      DUMP_FIELD_COPY (&out, cs, method);
+      DUMP_FIELD_COPY (&out, cs, min_code);
+      DUMP_FIELD_COPY (&out, cs, max_code);
+      DUMP_FIELD_COPY (&out, cs, char_index_offset);
+      DUMP_FIELD_COPY (&out, cs, min_char);
+      DUMP_FIELD_COPY (&out, cs, max_char);
+      DUMP_FIELD_COPY (&out, cs, invalid_code);
+      memcpy (out.fast_map, &cs->fast_map, sizeof (cs->fast_map));
+      DUMP_FIELD_COPY (&out, cs, code_offset);
+    }
   dump_off offset = dump_object_finish (ctx, &out, sizeof (out));
   if (cs_i < charset_table_used && cs->code_space_mask)
     dump_remember_cold_op (ctx, COLD_OP_CHARSET,
@@ -3249,14 +3258,17 @@ dump_charset_table (struct dump_context *ctx)
 {
   struct dump_flags old_flags = ctx->flags;
   ctx->flags.pack_objects = true;
-  dump_align_output (ctx, DUMP_ALIGNMENT);
+  dump_align_output (ctx, alignof (struct charset));
   dump_off offset = ctx->offset;
+  if (dump_set_referrer (ctx))
+    ctx->current_referrer = build_string ("charset_table");
   /* We are dumping the entire table, not just the used slots, because
      otherwise when we restore from the pdump file, the actual size of
      the table will be smaller than charset_table_size, and we will
      crash if/when a new charset is defined.  */
   for (int i = 0; i < charset_table_size; ++i)
     dump_charset (ctx, i);
+  dump_clear_referrer (ctx);
   dump_emacs_reloc_to_dump_ptr_raw (ctx, &charset_table, offset);
   ctx->flags = old_flags;
   return offset;
@@ -4212,22 +4224,19 @@ types.  */)
       dump_drain_deferred_symbols (ctx);
       dump_drain_normal_queue (ctx);
     }
-  while (!dump_queue_empty_p (&ctx->dump_queue)
-        || !NILP (ctx->deferred_hash_tables)
-        || !NILP (ctx->deferred_symbols));
+  while (!(dump_queue_empty_p (&ctx->dump_queue)
+          && NILP (ctx->deferred_hash_tables)
+          && NILP (ctx->deferred_symbols)));
 
   ctx->header.hash_list = ctx->offset;
   dump_hash_table_list (ctx);
 
-  do
-    {
-      dump_drain_deferred_hash_tables (ctx);
-      dump_drain_deferred_symbols (ctx);
-      dump_drain_normal_queue (ctx);
-    }
-  while (!dump_queue_empty_p (&ctx->dump_queue)
-        || !NILP (ctx->deferred_hash_tables)
-        || !NILP (ctx->deferred_symbols));
+  /* dump_hash_table_list just adds a new vector to the dump but all
+     its content should already have been in the dump, so it doesn't
+     add anything to any queue.  */
+  eassert (dump_queue_empty_p (&ctx->dump_queue)
+          && NILP (ctx->deferred_hash_tables)
+          && NILP (ctx->deferred_symbols));
 
   dump_sort_copied_objects (ctx);
 
diff --git a/src/pdumper.h b/src/pdumper.h
index 44985e26b3e..0d5e4c2d45f 100644
--- a/src/pdumper.h
+++ b/src/pdumper.h
@@ -1,6 +1,6 @@
 /* Header file for the portable dumper.
 
-Copyright (C) 2016, 2018-2023 Free Software Foundation, Inc.
+Copyright (C) 2016, 2018-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -128,7 +128,7 @@ pdumper_do_now_and_after_late_load (pdumper_hook hook)
     if (dumped_with_pdumper_p ())                 \
       (variable) = (value);                       \
     else                                          \
-      eassert (EQ ((variable), (value)));         \
+      eassert (EQ (variable, value));            \
   } while (0)
 
 /* Actually load a dump.  */
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 13ac61de960..f43eed6ad23 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1,6 +1,6 @@
 /* Functions for the pure Gtk+-3.
 
-Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2020, 2022-2023 Free
+Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2020, 2022-2024 Free
 Software Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/pgtkgui.h b/src/pgtkgui.h
index 4d38e0abc63..c44bd6ceb97 100644
--- a/src/pgtkgui.h
+++ b/src/pgtkgui.h
@@ -1,5 +1,5 @@
 /* Definitions and headers for communication on the pure Gtk+3.
-   Copyright (C) 1995, 2005, 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 1995, 2005, 2008-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/pgtkim.c b/src/pgtkim.c
index 9123186cf57..f7a79caa5b3 100644
--- a/src/pgtkim.c
+++ b/src/pgtkim.c
@@ -1,6 +1,6 @@
 /* Pure Gtk+-3 communication module.
 
-Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2023 Free Software
+Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c
index 31572f738c4..7666d04b098 100644
--- a/src/pgtkmenu.c
+++ b/src/pgtkmenu.c
@@ -1,5 +1,5 @@
 /* Pure GTK3 menu and toolbar module.
-   Copyright (C) 2019-2023 Free Software Foundation, Inc.
+   Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/pgtkselect.c b/src/pgtkselect.c
index 58d5035abed..b0ab15c6069 100644
--- a/src/pgtkselect.c
+++ b/src/pgtkselect.c
@@ -1,5 +1,5 @@
 /* Gtk selection processing for emacs.
-   Copyright (C) 1993-1994, 2005-2006, 2008-2023 Free Software
+   Copyright (C) 1993-1994, 2005-2006, 2008-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index 461c9d6d899..b731f52983d 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -1,6 +1,6 @@
 /* Communication module for window systems using GTK.
 
-Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2023 Free Software
+Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -3471,9 +3471,7 @@ pgtk_define_fringe_bitmap (int which, unsigned short 
*bits, int h, int wd)
       i = max_fringe_bmp;
       max_fringe_bmp = which + 20;
       fringe_bmp
-       = (cairo_pattern_t **) xrealloc (fringe_bmp,
-                                        max_fringe_bmp *
-                                        sizeof (cairo_pattern_t *));
+       = xrealloc (fringe_bmp, max_fringe_bmp * sizeof (cairo_pattern_t *));
       while (i < max_fringe_bmp)
        fringe_bmp[i++] = 0;
     }
@@ -6259,7 +6257,7 @@ symbol_to_drag_action (Lisp_Object act)
   if (NILP (act))
     return GDK_ACTION_DEFAULT;
 
-  signal_error ("Invalid drag acction", act);
+  signal_error ("Invalid drag action", act);
 }
 
 static Lisp_Object
@@ -7180,8 +7178,7 @@ If set to a non-float value, there will be no wait at 
all.  */);
 
   DEFVAR_LISP ("pgtk-keysym-table", Vpgtk_keysym_table,
     doc: /* Hash table of character codes indexed by X keysym codes.  */);
-  Vpgtk_keysym_table = make_hash_table (hashtest_eql, 900, DEFAULT_REHASH_SIZE,
-                                       DEFAULT_REHASH_THRESHOLD, Qnil, false);
+  Vpgtk_keysym_table = make_hash_table (&hashtest_eql, 900, Weak_None, false);
 
   window_being_scrolled = Qnil;
   staticpro (&window_being_scrolled);
diff --git a/src/pgtkterm.h b/src/pgtkterm.h
index 069e425fd9c..8072d963691 100644
--- a/src/pgtkterm.h
+++ b/src/pgtkterm.h
@@ -1,5 +1,5 @@
 /* Definitions and headers for communication with pure Gtk+3.
-   Copyright (C) 1989, 1993, 2005, 2008-2023 Free Software Foundation,
+   Copyright (C) 1989, 1993, 2005, 2008-2024 Free Software Foundation,
    Inc.
 
 This file is part of GNU Emacs.
@@ -462,7 +462,7 @@ enum
 #define FRAME_X_WINDOW(f)          FRAME_GTK_OUTER_WIDGET (f)
 #define FRAME_NATIVE_WINDOW(f)     GTK_WINDOW (FRAME_X_WINDOW (f))
 #define FRAME_GDK_WINDOW(f)                    \
-  (gtk_widget_get_window (FRAME_GTK_WIDGET (f)))
+  gtk_widget_get_window (FRAME_GTK_WIDGET (f))
 
 #define FRAME_X_DISPLAY(f)        (FRAME_DISPLAY_INFO (f)->gdpy)
 
diff --git a/src/print.c b/src/print.c
index a5d57adbd3b..e2252562915 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1,6 +1,6 @@
 /* Lisp object printing and output streams.
 
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -87,7 +87,7 @@ static struct print_buffer print_buffer;
    print_number_index holds the largest N already used.
    N has to be strictly larger than 0 since we need to distinguish -N.  */
 static ptrdiff_t print_number_index;
-static void print_interval (INTERVAL interval, Lisp_Object printcharfun);
+static void print_interval (INTERVAL interval, void *pprintcharfun);
 
 /* GDB resets this to zero on W32 to disable OutputDebugString calls.  */
 bool print_output_debug_flag EXTERNALLY_VISIBLE = 1;
@@ -1094,7 +1094,7 @@ print_error_message (Lisp_Object data, Lisp_Object 
stream, const char *context,
          /* `substitute-command-keys' may bug out, which would lead
             to infinite recursion when we're called from
             skip_debugger, so ignore errors.  */
-         Lisp_Object subs = safe_call1 (Qsubstitute_command_keys, errmsg);
+         Lisp_Object subs = safe_calln (Qsubstitute_command_keys, errmsg);
          if (!NILP (subs))
            errmsg = subs;
        }
@@ -1285,15 +1285,9 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool 
escapeflag)
        { /* Remove unnecessary objects, which appear only once in OBJ;
             that is, whose status is Qt.  */
          struct Lisp_Hash_Table *h = XHASH_TABLE (Vprint_number_table);
-         ptrdiff_t i;
-
-         for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
-            {
-              Lisp_Object key =  HASH_KEY (h, i);
-             if (!BASE_EQ (key, Qunbound)
-                 && EQ (HASH_VALUE (h, i), Qt))
-               Fremhash (key, Vprint_number_table);
-            }
+         DOHASH (h, k, v)
+           if (EQ (v, Qt))
+             Fremhash (k, Vprint_number_table);
        }
     }
 
@@ -1397,6 +1391,9 @@ static void
 print_preprocess (Lisp_Object obj)
 {
   eassert (!NILP (Vprint_circle));
+  /* The ppstack may contain HASH_UNUSED_ENTRY_KEY which is an invalid
+     Lisp value.  Make sure that our filter stops us from traversing it.  */
+  eassert (!PRINT_CIRCLE_CANDIDATE_P (HASH_UNUSED_ENTRY_KEY));
   ptrdiff_t base_sp = ppstack.sp;
 
   for (;;)
@@ -1415,7 +1412,7 @@ print_preprocess (Lisp_Object obj)
                  && SYMBOLP (obj)
                  && !SYMBOL_INTERNED_P (obj)))
            { /* OBJ appears more than once.  Let's remember that.  */
-             if (!FIXNUMP (num))
+             if (SYMBOLP (num)) /* In practice, nil or t.  */
                {
                  print_number_index++;
                  /* Negative number indicates it hasn't been printed yet.  */
@@ -1455,8 +1452,10 @@ print_preprocess (Lisp_Object obj)
                    if (HASH_TABLE_P (obj))
                      {
                        struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
-                       obj = h->key_and_value;
-                       continue;
+                       /* The values pushed here may include
+                          HASH_UNUSED_ENTRY_KEY; see top of this function.  */
+                       pp_stack_push_values (h->key_and_value,
+                                             2 * h->table_size);
                      }
                    break;
                  }
@@ -1493,8 +1492,6 @@ print_preprocess_string (INTERVAL interval, void *arg)
   print_preprocess (interval->plist);
 }
 
-static void print_check_string_charset_prop (INTERVAL interval, Lisp_Object 
string);
-
 #define PRINT_STRING_NON_CHARSET_FOUND 1
 #define PRINT_STRING_UNSAFE_CHARSET_FOUND 2
 
@@ -1502,7 +1499,7 @@ static void print_check_string_charset_prop (INTERVAL 
interval, Lisp_Object stri
 static int print_check_string_result;
 
 static void
-print_check_string_charset_prop (INTERVAL interval, Lisp_Object string)
+print_check_string_charset_prop (INTERVAL interval, void *pstring)
 {
   Lisp_Object val;
 
@@ -1526,6 +1523,7 @@ print_check_string_charset_prop (INTERVAL interval, 
Lisp_Object string)
   if (! (print_check_string_result & PRINT_STRING_UNSAFE_CHARSET_FOUND))
     {
       ptrdiff_t charpos = interval->position;
+      Lisp_Object string = *(Lisp_Object *)pstring;
       ptrdiff_t bytepos = string_char_to_byte (string, charpos);
       Lisp_Object charset = XCAR (XCDR (val));
 
@@ -1550,7 +1548,7 @@ print_prune_string_charset (Lisp_Object string)
 {
   print_check_string_result = 0;
   traverse_intervals (string_intervals (string), 0,
-                     print_check_string_charset_prop, string);
+                     print_check_string_charset_prop, &string);
   if (NILP (Vprint_charset_text_property)
       || ! (print_check_string_result & PRINT_STRING_UNSAFE_CHARSET_FOUND))
     {
@@ -1618,7 +1616,7 @@ print_bool_vector (Lisp_Object obj, Lisp_Object 
printcharfun)
   ptrdiff_t real_size_in_bytes = size_in_bytes;
   unsigned char *data = bool_vector_uchar_data (obj);
 
-  char buf[sizeof "#&" + INT_STRLEN_BOUND (ptrdiff_t)];
+  char buf[sizeof "#&\"" + INT_STRLEN_BOUND (ptrdiff_t)];
   int len = sprintf (buf, "#&%"pI"d\"", size);
   strout (buf, len, len, printcharfun);
 
@@ -2267,6 +2265,11 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, 
bool escapeflag)
              goto next_obj;
            }
        }
+      else if (STRINGP (num))
+       {
+         strout (SSDATA (num), SCHARS (num), SBYTES (num), printcharfun);
+         goto next_obj;
+       }
     }
 
   print_depth++;
@@ -2401,8 +2404,9 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, 
bool escapeflag)
 
          if (string_intervals (obj))
            {
+             Lisp_Object pcf = printcharfun;
              traverse_intervals (string_intervals (obj),
-                                 0, print_interval, printcharfun);
+                                 0, print_interval, &pcf);
              printchar (')', printcharfun);
            }
        }
@@ -2555,11 +2559,6 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, 
bool escapeflag)
          goto next_obj;
        case PVEC_SUB_CHAR_TABLE:
          {
-           /* Make each lowest sub_char_table start a new line.
-              Otherwise we'll make a line extremely long, which
-              results in slow redisplay.  */
-           if (XSUB_CHAR_TABLE (obj)->depth == 3)
-             printchar ('\n', printcharfun);
            print_c_string ("#^^[", printcharfun);
            int n = sprintf (buf, "%d %d",
                             XSUB_CHAR_TABLE (obj)->depth,
@@ -2574,50 +2573,49 @@ print_object (Lisp_Object obj, Lisp_Object 
printcharfun, bool escapeflag)
          {
            struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
            /* Implement a readable output, e.g.:
-              #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
-           /* Always print the size.  */
-           int len = sprintf (buf, "#s(hash-table size %"pD"d",
-                              HASH_TABLE_SIZE (h));
-           strout (buf, len, len, printcharfun);
+              #s(hash-table test equal data (k1 v1 k2 v2)) */
+           print_c_string ("#s(hash-table", printcharfun);
 
-           if (!NILP (h->test.name))
+           if (!BASE_EQ (h->test->name, Qeql))
              {
                print_c_string (" test ", printcharfun);
-               print_object (h->test.name, printcharfun, escapeflag);
+               print_object (h->test->name, printcharfun, escapeflag);
              }
 
-           if (!NILP (h->weak))
+           if (h->weakness != Weak_None)
              {
                print_c_string (" weakness ", printcharfun);
-               print_object (h->weak, printcharfun, escapeflag);
+               print_object (hash_table_weakness_symbol (h->weakness),
+                             printcharfun, escapeflag);
              }
 
-           print_c_string (" rehash-size ", printcharfun);
-           print_object (Fhash_table_rehash_size (obj),
-                         printcharfun, escapeflag);
-
-           print_c_string (" rehash-threshold ", printcharfun);
-           print_object (Fhash_table_rehash_threshold (obj),
-                         printcharfun, escapeflag);
-
            if (h->purecopy)
              print_c_string (" purecopy t", printcharfun);
 
-           print_c_string (" data (", printcharfun);
-
            ptrdiff_t size = h->count;
-           /* Don't print more elements than the specified maximum.  */
-           if (FIXNATP (Vprint_length) && XFIXNAT (Vprint_length) < size)
-             size = XFIXNAT (Vprint_length);
-
-           print_stack_push ((struct print_stack_entry){
-               .type = PE_hash,
-               .u.hash.obj = obj,
-               .u.hash.nobjs = size * 2,
-               .u.hash.idx = 0,
-               .u.hash.printed = 0,
-               .u.hash.truncated = (size < h->count),
-             });
+           if (size > 0)
+             {
+               print_c_string (" data (", printcharfun);
+
+               /* Don't print more elements than the specified maximum.  */
+               if (FIXNATP (Vprint_length) && XFIXNAT (Vprint_length) < size)
+                 size = XFIXNAT (Vprint_length);
+
+               print_stack_push ((struct print_stack_entry){
+                   .type = PE_hash,
+                   .u.hash.obj = obj,
+                   .u.hash.nobjs = size * 2,
+                   .u.hash.idx = 0,
+                   .u.hash.printed = 0,
+                   .u.hash.truncated = (size < h->count),
+                 });
+             }
+           else
+             {
+               /* Empty table: we can omit the data entirely.  */
+               printchar (')', printcharfun);
+               --print_depth;   /* Done with this.  */
+             }
            goto next_obj;
          }
 
@@ -2666,7 +2664,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, 
bool escapeflag)
                    /* With the print-circle feature.  */
                    Lisp_Object num = Fgethash (next, Vprint_number_table,
                                                Qnil);
-                   if (FIXNUMP (num))
+                   if (!(NILP (num) || EQ (num, Qt)))
                      {
                        print_c_string (" . ", printcharfun);
                        obj = next;
@@ -2770,7 +2768,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, 
bool escapeflag)
            {
              Lisp_Object key;
              ptrdiff_t idx = e->u.hash.idx;
-             while (BASE_EQ ((key = HASH_KEY (h, idx)), Qunbound))
+             while (hash_unused_entry_key_p ((key = HASH_KEY (h, idx))))
                idx++;
              e->u.hash.idx = idx;
              obj = key;
@@ -2793,10 +2791,11 @@ print_object (Lisp_Object obj, Lisp_Object 
printcharfun, bool escapeflag)
    This is part of printing a string that has text properties.  */
 
 static void
-print_interval (INTERVAL interval, Lisp_Object printcharfun)
+print_interval (INTERVAL interval, void *pprintcharfun)
 {
   if (NILP (interval->plist))
     return;
+  Lisp_Object printcharfun = *(Lisp_Object *)pprintcharfun;
   printchar (' ', printcharfun);
   print_object (make_fixnum (interval->position), printcharfun, 1);
   printchar (' ', printcharfun);
@@ -2929,7 +2928,10 @@ This variable should not be set with `setq'; bind it 
with a `let' instead.  */);
   DEFVAR_LISP ("print-number-table", Vprint_number_table,
               doc: /* A vector used internally to produce `#N=' labels and 
`#N#' references.
 The Lisp printer uses this vector to detect Lisp objects referenced more
-than once.
+than once.  If an entry contains a number, then the corresponding key is
+referenced more than once: a positive sign indicates that it's already been
+printed, and the absolute value indicates the number to use when printing.
+If an entry contains a string, that string is printed instead.
 
 When you bind `print-continuous-numbering' to t, you should probably
 also bind `print-number-table' to nil.  This ensures that the value of
diff --git a/src/process.c b/src/process.c
index bde87b78701..ddab9ed6c01 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1,6 +1,6 @@
 /* Asynchronous subprocess control for GNU Emacs.
 
-Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2023 Free Software
+Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -7520,7 +7520,7 @@ handle_child_signal (int sig)
 
                   emacs_unlink is not async signal safe because
                   deleting files from content providers must proceed
-                  through Java code.  Consequentially, if XCDR (head)
+                  through Java code.  Consequently, if XCDR (head)
                   lies on a content provider it will not be removed,
                   which is a bug.  */
                unlink (SSDATA (XCDR (head)));
diff --git a/src/process.h b/src/process.h
index bbe4528dc31..3f56b087084 100644
--- a/src/process.h
+++ b/src/process.h
@@ -1,5 +1,5 @@
 /* Definitions for asynchronous process control in GNU Emacs.
-   Copyright (C) 1985, 1994, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1994, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/profiler.c b/src/profiler.c
index b494ad783dc..5a6a8b48f6b 100644
--- a/src/profiler.c
+++ b/src/profiler.c
@@ -1,6 +1,6 @@
 /* Profiler implementation.
 
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -34,23 +34,152 @@ saturated_add (EMACS_INT a, EMACS_INT b)
 
 /* Logs.  */
 
-typedef struct Lisp_Hash_Table log_t;
+/* A fully associative cache of size SIZE, mapping vectors of DEPTH
+   Lisp objects to counts.  */
+typedef struct {
+  /* We use `int' throughout for table indices because anything bigger
+     is overkill.  (Maybe we should make a typedef, but int is short.)  */
+  int size;                    /* number of entries */
+  int depth;                   /* elements in each key vector */
+  int index_size;              /* size of index */
+  Lisp_Object *trace;          /* working trace, `depth' elements */
+  int *index;                  /* `index_size' indices or -1 if nothing */
+  int *next;                   /* `size' indices to next bucket or -1 */
+  EMACS_UINT *hash;            /* `size' hash values */
+  Lisp_Object *keys;           /* `size' keys of `depth' objects each */
+  EMACS_INT *counts;           /* `size' entries, 0 indicates unused entry */
+  int next_free;               /* next free entry, -1 if all taken */
+} log_t;
 
-static Lisp_Object cmpfn_profiler (Lisp_Object, Lisp_Object,
-                                  struct Lisp_Hash_Table *);
-static Lisp_Object hashfn_profiler (Lisp_Object, struct Lisp_Hash_Table *);
+static void
+mark_log (log_t *log)
+{
+  if (log == NULL)
+    return;
+  int size = log->size;
+  int depth = log->depth;
+  for (int i = 0; i < size; i++)
+    if (log->counts[i] > 0)    /* Only mark valid keys.  */
+      mark_objects (log->keys + i * depth, depth);
+}
+
+static log_t *
+make_log (int size, int depth)
+{
+  log_t *log = xmalloc (sizeof *log);
+  log->size = size;
+  log->depth = depth;
+
+  /* The index size is arbitrary but for there to be any point it should be
+     bigger than SIZE.  FIXME: make it a power of 2 or a (pseudo)prime.  */
+  int index_size = size * 2 + 1;
+  log->index_size = index_size;
+
+  log->trace = xmalloc (depth * sizeof *log->trace);
+
+  log->index = xmalloc (index_size * sizeof *log->index);
+  for (int i = 0; i < index_size; i++)
+    log->index[i] = -1;
+
+  log->next = xmalloc (size * sizeof *log->next);
+  for (int i = 0; i < size - 1; i++)
+    log->next[i] = i + 1;
+  log->next[size - 1] = -1;
+  log->next_free = 0;
+
+  log->hash = xmalloc (size * sizeof *log->hash);
+  log->keys = xzalloc (size * depth * sizeof *log->keys);
+  log->counts = xzalloc (size * sizeof *log->counts);
+
+  return log;
+}
+
+static void
+free_log (log_t *log)
+{
+  xfree (log->trace);
+  xfree (log->index);
+  xfree (log->next);
+  xfree (log->hash);
+  xfree (log->keys);
+  xfree (log->counts);
+  xfree (log);
+}
+
+static inline EMACS_INT
+get_log_count (log_t *log, int idx)
+{
+  eassume (idx >= 0 && idx < log->size);
+  return log->counts[idx];
+}
+
+static inline void
+set_log_count (log_t *log, int idx, EMACS_INT val)
+{
+  eassume (idx >= 0 && idx < log->size && val >= 0);
+  log->counts[idx] = val;
+}
+
+static inline Lisp_Object *
+get_key_vector (log_t *log, int idx)
+{
+  eassume (idx >= 0 && idx < log->size);
+  return log->keys + idx * log->depth;
+}
+
+static inline int
+log_hash_index (log_t *log, EMACS_UINT hash)
+{
+  /* FIXME: avoid division.  */
+  return hash % log->index_size;
+}
+
+static void
+remove_log_entry (log_t *log, int idx)
+{
+  eassume (idx >= 0 && idx < log->size);
+  /* Remove from index.  */
+  int hidx = log_hash_index (log, log->hash[idx]);
+  int *p = &log->index[hidx];
+  while (*p != idx)
+    {
+      eassert (*p >= 0 && *p < log->size);
+      p = &log->next[*p];
+    }
+  *p = log->next[*p];
+  /* Invalidate entry and put it on the free list.  */
+  log->counts[idx] = 0;
+  log->next[idx] = log->next_free;
+  log->next_free = idx;
+}
 
-static const struct hash_table_test hashtest_profiler =
-  {
-   LISPSYM_INITIALLY (Qprofiler_backtrace_equal),
-   LISPSYM_INITIALLY (Qnil) /* user_hash_function */,
-   LISPSYM_INITIALLY (Qnil) /* user_cmp_function */,
-   cmpfn_profiler,
-   hashfn_profiler,
-  };
+static bool
+trace_equal (Lisp_Object *bt1, Lisp_Object *bt2, int depth)
+{
+  for (int i = 0; i < depth; i++)
+    if (!BASE_EQ (bt1[i], bt2[i]) && NILP (Ffunction_equal (bt1[i], bt2[i])))
+      return false;
+  return true;
+}
+
+static EMACS_UINT
+trace_hash (Lisp_Object *trace, int depth)
+{
+  EMACS_UINT hash = 0;
+  for (int i = 0; i < depth; i++)
+    {
+      Lisp_Object f = trace[i];
+      EMACS_UINT hash1
+       = (COMPILEDP (f) ? XHASH (AREF (f, COMPILED_BYTECODE))
+          : (CONSP (f) && CONSP (XCDR (f)) && BASE_EQ (Qclosure, XCAR (f)))
+          ? XHASH (XCDR (XCDR (f))) : XHASH (f));
+      hash = sxhash_combine (hash, hash1);
+    }
+  return hash;
+}
 
 struct profiler_log {
-  Lisp_Object log;
+  log_t *log;
   EMACS_INT gc_count;  /* Samples taken during GC.  */
   EMACS_INT discarded; /* Samples evicted during table overflow.  */
 };
@@ -58,32 +187,22 @@ struct profiler_log {
 static Lisp_Object export_log (struct profiler_log *);
 
 static struct profiler_log
-make_log (void)
-{
-  /* We use a standard Elisp hash-table object, but we use it in
-     a special way.  This is OK as long as the object is not exposed
-     to Elisp, i.e. until it is returned by *-profiler-log, after which
-     it can't be used any more.  */
-  EMACS_INT heap_size
-    = clip_to_bounds (0, profiler_log_size, MOST_POSITIVE_FIXNUM);
-  ptrdiff_t max_stack_depth
-    = clip_to_bounds (0, profiler_max_stack_depth, PTRDIFF_MAX);;
-  struct profiler_log log
-    = { make_hash_table (hashtest_profiler, heap_size,
-                        DEFAULT_REHASH_SIZE,
-                        DEFAULT_REHASH_THRESHOLD,
-                        Qnil, false),
-       0, 0 };
-  struct Lisp_Hash_Table *h = XHASH_TABLE (log.log);
-
-  /* What is special about our hash-tables is that the values are pre-filled
-     with the vectors we'll use as keys.  */
-  ptrdiff_t i = ASIZE (h->key_and_value) >> 1;
-  while (i > 0)
-    set_hash_value_slot (h, --i, make_nil_vector (max_stack_depth));
-  return log;
+make_profiler_log (void)
+{
+  int size = clip_to_bounds (0, profiler_log_size,
+                            min (MOST_POSITIVE_FIXNUM, INT_MAX));
+  int max_stack_depth = clip_to_bounds (0, profiler_max_stack_depth, INT_MAX);
+  return (struct profiler_log){make_log (size, max_stack_depth), 0, 0};
 }
 
+static void
+free_profiler_log (struct profiler_log *plog)
+{
+  free_log (plog->log);
+  plog->log = NULL;
+}
+
+
 /* Evict the least used half of the hash_table.
 
    When the table is full, we have to evict someone.
@@ -100,22 +219,22 @@ make_log (void)
    cost of O(1) and we get O(N) time for a new entry to grow larger
    than the other least counts before a new round of eviction.  */
 
-static EMACS_INT approximate_median (log_t *log,
-                                    ptrdiff_t start, ptrdiff_t size)
+static EMACS_INT
+approximate_median (log_t *log, int start, int size)
 {
   eassert (size > 0);
   if (size < 2)
-    return XFIXNUM (HASH_VALUE (log, start));
+    return get_log_count (log, start);
   if (size < 3)
     /* Not an actual median, but better for our application than
        choosing either of the two numbers.  */
-    return ((XFIXNUM (HASH_VALUE (log, start))
-            + XFIXNUM (HASH_VALUE (log, start + 1)))
+    return ((get_log_count (log, start)
+            + get_log_count (log, start + 1))
            / 2);
   else
     {
-      ptrdiff_t newsize = size / 3;
-      ptrdiff_t start2 = start + newsize;
+      int newsize = size / 3;
+      int start2 = start + newsize;
       EMACS_INT i1 = approximate_median (log, start, newsize);
       EMACS_INT i2 = approximate_median (log, start2, newsize);
       EMACS_INT i3 = approximate_median (log, start2 + newsize,
@@ -126,34 +245,24 @@ static EMACS_INT approximate_median (log_t *log,
     }
 }
 
-static void evict_lower_half (struct profiler_log *plog)
+static void
+evict_lower_half (struct profiler_log *plog)
 {
-  log_t *log = XHASH_TABLE (plog->log);
-  ptrdiff_t size = ASIZE (log->key_and_value) / 2;
+  log_t *log = plog->log;
+  int size = log->size;
   EMACS_INT median = approximate_median (log, 0, size);
 
-  for (ptrdiff_t i = 0; i < size; i++)
-    /* Evict not only values smaller but also values equal to the median,
-       so as to make sure we evict something no matter what.  */
-    if (XFIXNUM (HASH_VALUE (log, i)) <= median)
-      {
-       Lisp_Object key = HASH_KEY (log, i);
-       EMACS_INT count = XFIXNUM (HASH_VALUE (log, i));
-       plog->discarded = saturated_add (plog->discarded, count);
-       { /* FIXME: we could make this more efficient.  */
-         Lisp_Object tmp;
-         XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr.  */
-         Fremhash (key, tmp);
+  for (int i = 0; i < size; i++)
+    {
+      EMACS_INT count = get_log_count (log, i);
+      /* Evict not only values smaller but also values equal to the median,
+        so as to make sure we evict something no matter what.  */
+      if (count <= median)
+       {
+         plog->discarded = saturated_add (plog->discarded, count);
+         remove_log_entry (log, i);
        }
-        eassert (BASE_EQ (Qunbound, HASH_KEY (log, i)));
-       eassert (log->next_free == i);
-
-       eassert (VECTORP (key));
-       for (ptrdiff_t j = 0; j < ASIZE (key); j++)
-         ASET (key, j, Qnil);
-
-       set_hash_value_slot (log, i, key);
-      }
+    }
 }
 
 /* Record the current backtrace in LOG.  COUNT is the weight of this
@@ -163,54 +272,52 @@ static void evict_lower_half (struct profiler_log *plog)
 static void
 record_backtrace (struct profiler_log *plog, EMACS_INT count)
 {
-  eassert (HASH_TABLE_P (plog->log));
-  log_t *log = XHASH_TABLE (plog->log);
+  log_t *log = plog->log;
+  get_backtrace (log->trace, log->depth);
+  EMACS_UINT hash = trace_hash (log->trace, log->depth);
+  int hidx = log_hash_index (log, hash);
+  int idx = log->index[hidx];
+  while (idx >= 0)
+    {
+      if (log->hash[idx] == hash
+         && trace_equal (log->trace, get_key_vector (log, idx), log->depth))
+       {
+         /* Found existing entry.  */
+         set_log_count (log, idx,
+                        saturated_add (get_log_count (log, idx), count));
+         return;
+       }
+      idx = log->next[idx];
+    }
+
+  /* Add new entry.  */
   if (log->next_free < 0)
     evict_lower_half (plog);
-  ptrdiff_t index = log->next_free;
-
-  /* Get a "working memory" vector.  */
-  Lisp_Object backtrace = HASH_VALUE (log, index);
-  eassert (BASE_EQ (Qunbound, HASH_KEY (log, index)));
-  get_backtrace (backtrace);
-
-  { /* We basically do a `gethash+puthash' here, except that we have to be
-       careful to avoid memory allocation since we're in a signal
-       handler, and we optimize the code to try and avoid computing the
-       hash+lookup twice.  See fns.c:Fputhash for reference.  */
-    Lisp_Object hash;
-    ptrdiff_t j = hash_lookup (log, backtrace, &hash);
-    if (j >= 0)
-      {
-       EMACS_INT old_val = XFIXNUM (HASH_VALUE (log, j));
-       EMACS_INT new_val = saturated_add (old_val, count);
-       set_hash_value_slot (log, j, make_fixnum (new_val));
-      }
-    else
-      { /* BEWARE!  hash_put in general can allocate memory.
-          But currently it only does that if log->next_free is -1.  */
-       eassert (0 <= log->next_free);
-       ptrdiff_t j = hash_put (log, backtrace, make_fixnum (count), hash);
-       /* Let's make sure we've put `backtrace' right where it
-          already was to start with.  */
-       eassert (index == j);
-
-       /* FIXME: If the hash-table is almost full, we should set
-          some global flag so that some Elisp code can offload its
-          data elsewhere, so as to avoid the eviction code.
-          There are 2 ways to do that, AFAICT:
-          - Set a flag checked in maybe_quit, such that maybe_quit can then
-            call Fprofiler_cpu_log and stash the full log for later use.
-          - Set a flag check in post-gc-hook, so that Elisp code can call
-            profiler-cpu-log.  That gives us more flexibility since that
-            Elisp code can then do all kinds of fun stuff like write
-            the log to disk.  Or turn it right away into a call tree.
-          Of course, using Elisp is generally preferable, but it may
-          take longer until we get a chance to run the Elisp code, so
-          there's more risk that the table will get full before we
-          get there.  */
-      }
-  }
+  idx = log->next_free;
+  eassert (idx >= 0);
+  log->next_free = log->next[idx];
+  log->next[idx] = log->index[hidx];
+  log->index[hidx] = idx;
+  eassert (log->counts[idx] == 0);
+  log->hash[idx] = hash;
+  memcpy (get_key_vector (log, idx), log->trace,
+         log->depth * sizeof *log->trace);
+  log->counts[idx] = count;
+
+  /* FIXME: If the hash-table is almost full, we should set
+     some global flag so that some Elisp code can offload its
+     data elsewhere, so as to avoid the eviction code.
+     There are 2 ways to do that:
+     - Set a flag checked in maybe_quit, such that maybe_quit can then
+     call Fprofiler_cpu_log and stash the full log for later use.
+     - Set a flag check in post-gc-hook, so that Elisp code can call
+     profiler-cpu-log.  That gives us more flexibility since that
+     Elisp code can then do all kinds of fun stuff like write
+     the log to disk.  Or turn it right away into a call tree.
+     Of course, using Elisp is generally preferable, but it may
+     take longer until we get a chance to run the Elisp code, so
+     there's more risk that the table will get full before we
+     get there.  */
 }
 
 /* Sampling profiler.  */
@@ -234,6 +341,9 @@ add_sample (struct profiler_log *plog, EMACS_INT count)
 
 #ifdef PROFILER_CPU_SUPPORT
 
+/* The sampling interval specified.  */
+static Lisp_Object profiler_cpu_interval = LISPSYM_INITIALLY (Qnil);
+
 /* The profiler timer and whether it was properly initialized, if
    POSIX timers are available.  */
 #ifdef HAVE_ITIMERSPEC
@@ -356,8 +466,8 @@ See also `profiler-log-size' and 
`profiler-max-stack-depth'.  */)
   if (profiler_cpu_running)
     error ("CPU profiler is already running");
 
-  if (NILP (cpu.log))
-    cpu = make_log ();
+  if (cpu.log == NULL)
+    cpu = make_profiler_log ();
 
   int status = setup_cpu_timer (sampling_interval);
   if (status < 0)
@@ -367,6 +477,7 @@ See also `profiler-log-size' and 
`profiler-max-stack-depth'.  */)
     }
   else
     {
+      profiler_cpu_interval = sampling_interval;
       profiler_cpu_running = status;
       if (! profiler_cpu_running)
        error ("Unable to start profiler timer");
@@ -428,30 +539,49 @@ of functions, where the last few elements may be nil.
 Before returning, a new log is allocated for future samples.  */)
   (void)
 {
-  return (export_log (&cpu));
+  /* Temporarily stop profiling to avoid it interfering with our data
+     access.  */
+  bool prof_cpu = profiler_cpu_running;
+  if (prof_cpu)
+    Fprofiler_cpu_stop ();
+
+  Lisp_Object ret = export_log (&cpu);
+
+  if (prof_cpu)
+    Fprofiler_cpu_start (profiler_cpu_interval);
+
+  return ret;
 }
 #endif /* PROFILER_CPU_SUPPORT */
 
+/* Extract log data to a Lisp hash table.  The log data is then erased.  */
 static Lisp_Object
-export_log (struct profiler_log *log)
+export_log (struct profiler_log *plog)
 {
-  Lisp_Object result = log->log;
-  if (log->gc_count)
+  log_t *log = plog->log;
+  /* The returned hash table uses `equal' as key equivalence predicate
+     which is more discriminating than the `function-equal' used by
+     the log but close enough, and will never confuse two distinct
+     keys in the log.  */
+  Lisp_Object h = make_hash_table (&hashtest_equal, DEFAULT_HASH_SIZE,
+                                  Weak_None, false);
+  for (int i = 0; i < log->size; i++)
+    {
+      int count = get_log_count (log, i);
+      if (count > 0)
+       Fputhash (Fvector (log->depth, get_key_vector (log, i)),
+                 make_fixnum (count), h);
+    }
+  if (plog->gc_count)
     Fputhash (CALLN (Fvector, QAutomatic_GC, Qnil),
-             make_fixnum (log->gc_count),
-             result);
-  if (log->discarded)
+             make_fixnum (plog->gc_count),
+             h);
+  if (plog->discarded)
     Fputhash (CALLN (Fvector, QDiscarded_Samples, Qnil),
-             make_fixnum (log->discarded),
-             result);
-#ifdef PROFILER_CPU_SUPPORT
-  /* Here we're making the log visible to Elisp, so it's not safe any
-     more for our use afterwards since we can't rely on its special
-     pre-allocated keys anymore.  So we have to allocate a new one.  */
-  if (profiler_cpu_running)
-    *log = make_log ();
-#endif /* PROFILER_CPU_SUPPORT */
-  return result;
+             make_fixnum (plog->discarded),
+             h);
+  free_profiler_log (plog);
+  return h;
 }
 
 /* Memory profiler.  */
@@ -474,8 +604,8 @@ See also `profiler-log-size' and 
`profiler-max-stack-depth'.  */)
   if (profiler_memory_running)
     error ("Memory profiler is already running");
 
-  if (NILP (memory.log))
-    memory = make_log ();
+  if (memory.log == NULL)
+    memory = make_profiler_log ();
 
   profiler_memory_running = true;
 
@@ -514,7 +644,16 @@ of functions, where the last few elements may be nil.
 Before returning, a new log is allocated for future samples.  */)
   (void)
 {
-  return (export_log (&memory));
+  bool prof_mem = profiler_memory_running;
+  if (prof_mem)
+    Fprofiler_memory_stop ();
+
+  Lisp_Object ret = export_log (&memory);
+
+  if (prof_mem)
+    Fprofiler_memory_start ();
+
+  return ret;
 }
 
 
@@ -547,50 +686,15 @@ the same lambda expression, or are really unrelated 
function.  */)
   return res ? Qt : Qnil;
 }
 
-static Lisp_Object
-cmpfn_profiler (Lisp_Object bt1, Lisp_Object bt2, struct Lisp_Hash_Table *h)
-{
-  if (EQ (bt1, bt2))
-    return Qt;
-  else if (VECTORP (bt1) && VECTORP (bt2))
-    {
-      ptrdiff_t l = ASIZE (bt1);
-      if (l != ASIZE (bt2))
-       return Qnil;
-      for (ptrdiff_t i = 0; i < l; i++)
-       if (NILP (Ffunction_equal (AREF (bt1, i), AREF (bt2, i))))
-         return Qnil;
-      return Qt;
-    }
-  else
-    return Qnil;
-}
-
-static Lisp_Object
-hashfn_profiler (Lisp_Object bt, struct Lisp_Hash_Table *h)
+void
+mark_profiler (void)
 {
-  EMACS_UINT hash;
-  if (VECTORP (bt))
-    {
-      hash = 0;
-      ptrdiff_t l = ASIZE (bt);
-      for (ptrdiff_t i = 0; i < l; i++)
-       {
-         Lisp_Object f = AREF (bt, i);
-         EMACS_UINT hash1
-           = (COMPILEDP (f) ? XHASH (AREF (f, COMPILED_BYTECODE))
-              : (CONSP (f) && CONSP (XCDR (f)) && EQ (Qclosure, XCAR (f)))
-              ? XHASH (XCDR (XCDR (f))) : XHASH (f));
-         hash = sxhash_combine (hash, hash1);
-       }
-    }
-  else
-    hash = XHASH (bt);
-  return make_ufixnum (SXHASH_REDUCE (hash));
+#ifdef PROFILER_CPU_SUPPORT
+  mark_log (cpu.log);
+#endif
+  mark_log (memory.log);
 }
 
-static void syms_of_profiler_for_pdumper (void);
-
 void
 syms_of_profiler (void)
 {
@@ -603,47 +707,20 @@ If the log gets full, some of the least-seen call-stacks 
will be evicted
 to make room for new entries.  */);
   profiler_log_size = 10000;
 
-  DEFSYM (Qprofiler_backtrace_equal, "profiler-backtrace-equal");
   DEFSYM (QDiscarded_Samples, "Discarded Samples");
 
   defsubr (&Sfunction_equal);
 
 #ifdef PROFILER_CPU_SUPPORT
   profiler_cpu_running = NOT_RUNNING;
-  cpu.log = Qnil;
-  staticpro (&cpu.log);
   defsubr (&Sprofiler_cpu_start);
   defsubr (&Sprofiler_cpu_stop);
   defsubr (&Sprofiler_cpu_running_p);
   defsubr (&Sprofiler_cpu_log);
 #endif
   profiler_memory_running = false;
-  memory.log = Qnil;
-  staticpro (&memory.log);
   defsubr (&Sprofiler_memory_start);
   defsubr (&Sprofiler_memory_stop);
   defsubr (&Sprofiler_memory_running_p);
   defsubr (&Sprofiler_memory_log);
-
-  pdumper_do_now_and_after_load (syms_of_profiler_for_pdumper);
-}
-
-static void
-syms_of_profiler_for_pdumper (void)
-{
-  if (dumped_with_pdumper_p ())
-    {
-#ifdef PROFILER_CPU_SUPPORT
-      cpu.log = Qnil;
-#endif
-      memory.log = Qnil;
-    }
-  else
-    {
-#ifdef PROFILER_CPU_SUPPORT
-      eassert (NILP (cpu.log));
-#endif
-      eassert (NILP (memory.log));
-    }
-
 }
diff --git a/src/puresize.h b/src/puresize.h
index d5463c81a09..ac5d2da30dc 100644
--- a/src/puresize.h
+++ b/src/puresize.h
@@ -1,5 +1,5 @@
 /* How much read-only Lisp storage a dumped Emacs needs.
-   Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/ralloc.c b/src/ralloc.c
index 1b8d26d1244..5724ae65d33 100644
--- a/src/ralloc.c
+++ b/src/ralloc.c
@@ -1,5 +1,5 @@
 /* Block-relocating memory allocator.
-   Copyright (C) 1993, 1995, 2000-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1995, 2000-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/regex-emacs.c b/src/regex-emacs.c
index cb4fbd58faa..0ec0c6eb63f 100644
--- a/src/regex-emacs.c
+++ b/src/regex-emacs.c
@@ -1,6 +1,6 @@
 /* Emacs regular expression matching and search
 
-   Copyright (C) 1993-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -99,7 +99,7 @@
 #define IS_REAL_ASCII(c) ((c) < 0200)
 
 /* 1 if C is a unibyte character.  */
-#define ISUNIBYTE(c) (SINGLE_BYTE_CHAR_P ((c)))
+#define ISUNIBYTE(c) SINGLE_BYTE_CHAR_P (c)
 
 /* The Emacs definitions should not be directly affected by locales.  */
 
@@ -1345,7 +1345,7 @@ struct range_table_work_area
 /* Set a range (RANGE_START, RANGE_END) to WORK_AREA.  */
 #define SET_RANGE_TABLE_WORK_AREA(work_area, range_start, range_end)   \
   do {                                                                 \
-    EXTEND_RANGE_TABLE ((work_area), 2);                               \
+    EXTEND_RANGE_TABLE (work_area, 2);                                 \
     (work_area).table[(work_area).used++] = (range_start);             \
     (work_area).table[(work_area).used++] = (range_end);               \
   } while (false)
@@ -1380,7 +1380,7 @@ struct range_table_work_area
 
 
 /* Set the bit for character C in a list.  */
-#define SET_LIST_BIT(c) (b[((c)) / BYTEWIDTH] |= 1 << ((c) % BYTEWIDTH))
+#define SET_LIST_BIT(c) (b[(c) / BYTEWIDTH] |= 1 << ((c) % BYTEWIDTH))
 
 
 /* Store characters in the range FROM to TO in the bitmap at B (for
@@ -1403,7 +1403,7 @@ struct range_table_work_area
        C1 = TRANSLATE (C0);                                    \
        if (! ASCII_CHAR_P (C1))                                \
          {                                                     \
-           SET_RANGE_TABLE_WORK_AREA ((work_area), C1, C1);    \
+           SET_RANGE_TABLE_WORK_AREA (work_area, C1, C1);      \
            if ((C1 = RE_CHAR_TO_UNIBYTE (C1)) < 0)             \
              C1 = C0;                                          \
          }                                                     \
@@ -1446,7 +1446,7 @@ struct range_table_work_area
                  }                                                            \
              }                                                                \
            if (I < USED)                                                      \
-             SET_RANGE_TABLE_WORK_AREA ((work_area), C2, C2);                 \
+             SET_RANGE_TABLE_WORK_AREA (work_area, C2, C2);                   \
          }                                                                    \
       }                                                                        
       \
   } while (false)
@@ -1458,7 +1458,7 @@ struct range_table_work_area
   do {                                                                    \
     int C0, C1, C2, I, USED = RANGE_TABLE_WORK_USED (work_area);          \
                                                                           \
-    SET_RANGE_TABLE_WORK_AREA ((work_area), (FROM), (TO));                \
+    SET_RANGE_TABLE_WORK_AREA (work_area, FROM, TO);                      \
     for (C0 = (FROM); C0 <= (TO); C0++)                                        
   \
       {                                                                        
   \
        C1 = TRANSLATE (C0);                                               \
@@ -1482,7 +1482,7 @@ struct range_table_work_area
              }                                                            \
          }                                                                \
        if (I < USED)                                                      \
-         SET_RANGE_TABLE_WORK_AREA ((work_area), C1, C1);                 \
+         SET_RANGE_TABLE_WORK_AREA (work_area, C1, C1);                   \
       }                                                                        
   \
   } while (false)
 
@@ -2824,7 +2824,7 @@ group_in_compile_stack (compile_stack_type compile_stack, 
regnum_t regnum)
 
 /* Iterate through all the char-matching operations directly reachable from P.
    This is the inner loop of `forall_firstchar`, which see.
-   LOOP_BEG..LOOP_END delimit the currentl "block" of code (we assume
+   LOOP_BEG..LOOP_END delimit the currently "block" of code (we assume
    the code is made of syntactically nested loops).
    LOOP_END is blindly assumed to be "safe".
    To guarantee termination, at each iteration, either LOOP_BEG should
@@ -2923,8 +2923,18 @@ forall_firstchar_1 (re_char *p, re_char *pend,
                forward over a subsequent `jump`.  Recognize this pattern
                since that subsequent `jump` is the one that jumps to the
                loop-entry.  */
-           newp2 = ((re_opcode_t) *newp2 == jump)
-                   ? extract_address (newp2 + 1) : newp2;
+           if ((re_opcode_t) *newp2 == jump)
+             {
+               re_char *p3 = extract_address (newp2 + 1);
+               /* Only recognize this pattern if one of the two destinations
+                  is going forward, otherwise we'll fall into the pessimistic
+                  "Both destinations go backward" below.
+                  This is important if the `jump` at newp2 is the end of an
+                  outer loop while the `on_failure_jump` is the end of an
+                  inner loop.  */
+               if (p3 > p_orig || newp1 > p_orig)
+                 newp2 = p3;
+             }
 
          do_twoway_jump:
            /* We have to check that both destinations are safe.
@@ -3755,7 +3765,7 @@ execute_charset (re_char **pp, int c, int corig, bool 
unibyte,
       int count;
       rtp = CHARSET_RANGE_TABLE (p);
       EXTRACT_NUMBER_AND_INCR (count, rtp);
-      *pp = CHARSET_RANGE_TABLE_END ((rtp), (count));
+      *pp = CHARSET_RANGE_TABLE_END (rtp, count);
     }
   else
     *pp += 2 + CHARSET_BITMAP_SIZE (p);
diff --git a/src/regex-emacs.h b/src/regex-emacs.h
index d9adcc69443..2402e539e64 100644
--- a/src/regex-emacs.h
+++ b/src/regex-emacs.h
@@ -1,6 +1,6 @@
 /* Emacs regular expression API
 
-   Copyright (C) 1985, 1989-1993, 1995, 2000-2023 Free Software
+   Copyright (C) 1985, 1989-1993, 1995, 2000-2024 Free Software
    Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
diff --git a/src/region-cache.c b/src/region-cache.c
index cbf6b7b1cee..089cb280a24 100644
--- a/src/region-cache.c
+++ b/src/region-cache.c
@@ -1,6 +1,6 @@
 /* Caching facts about regions of the buffer, for optimization.
 
-Copyright (C) 1985-1989, 1993, 1995, 2001-2023 Free Software Foundation,
+Copyright (C) 1985-1989, 1993, 1995, 2001-2024 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/region-cache.h b/src/region-cache.h
index bdf132dc2d8..686f865a05b 100644
--- a/src/region-cache.h
+++ b/src/region-cache.h
@@ -1,6 +1,6 @@
 /* Header file: Caching facts about regions of the buffer, for optimization.
 
-Copyright (C) 1985-1986, 1993, 1995, 2001-2023 Free Software Foundation,
+Copyright (C) 1985-1986, 1993, 1995, 2001-2024 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/scroll.c b/src/scroll.c
index 1f530dc5c95..fd2a9e71207 100644
--- a/src/scroll.c
+++ b/src/scroll.c
@@ -1,6 +1,6 @@
 /* Calculate what line insertion or deletion to do, and do it
 
-Copyright (C) 1985-1986, 1990, 1993-1994, 2001-2023 Free Software
+Copyright (C) 1985-1986, 1990, 1993-1994, 2001-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/search.c b/src/search.c
index 2996d32fca1..f2d1f1f5449 100644
--- a/src/search.c
+++ b/src/search.c
@@ -1,6 +1,6 @@
 /* String search routines for GNU Emacs.
 
-Copyright (C) 1985-1987, 1993-1994, 1997-1999, 2001-2023 Free Software
+Copyright (C) 1985-1987, 1993-1994, 1997-1999, 2001-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -281,7 +281,7 @@ looking_at_1 (Lisp_Object string, bool posix, bool 
modify_data)
   struct regexp_cache *cache_entry = compile_pattern (
     string,
     modify_match_data ? &search_regs : NULL,
-    (!NILP (BVAR (current_buffer, case_fold_search))
+    (!NILP (Vcase_fold_search)
      ? BVAR (current_buffer, case_canon_table) : Qnil),
     posix,
     !NILP (BVAR (current_buffer, enable_multibyte_characters)));
@@ -402,7 +402,7 @@ string_match_1 (Lisp_Object regexp, Lisp_Object string, 
Lisp_Object start,
   struct regexp_cache *cache_entry
     = compile_pattern (regexp,
                       modify_match_data ? &search_regs : NULL,
-                      (!NILP (BVAR (current_buffer, case_fold_search))
+                      (!NILP (Vcase_fold_search)
                        ? BVAR (current_buffer, case_canon_table)
                        : Qnil),
                       posix,
@@ -1068,10 +1068,10 @@ search_command (Lisp_Object string, Lisp_Object bound, 
Lisp_Object noerror,
                         BVAR (current_buffer, case_eqv_table));
 
   np = search_buffer (string, PT, PT_BYTE, lim, lim_byte, n, RE,
-                     (!NILP (BVAR (current_buffer, case_fold_search))
+                     (!NILP (Vcase_fold_search)
                       ? BVAR (current_buffer, case_canon_table)
                       : Qnil),
-                     (!NILP (BVAR (current_buffer, case_fold_search))
+                     (!NILP (Vcase_fold_search)
                       ? BVAR (current_buffer, case_eqv_table)
                       : Qnil),
                      posix);
@@ -3402,7 +3402,7 @@ If RAW is non-nil, just return the actual bytecode.  */)
 {
   struct regexp_cache *cache_entry
     = compile_pattern (regexp, NULL,
-                       (!NILP (BVAR (current_buffer, case_fold_search))
+                       (!NILP (Vcase_fold_search)
                         ? BVAR (current_buffer, case_canon_table) : Qnil),
                        false,
                        !NILP (BVAR (current_buffer,
diff --git a/src/sfnt.c b/src/sfnt.c
index 8ec19290859..6df43af4293 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -1,6 +1,6 @@
 /* TrueType format font support for GNU Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -27,6 +27,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include <fcntl.h>
 #include <intprops.h>
 #include <inttypes.h>
+#include <stdckdint.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -67,6 +68,19 @@ xmalloc (size_t size)
   return ptr;
 }
 
+MAYBE_UNUSED static void *
+xzalloc (size_t size)
+{
+  void *ptr;
+
+  ptr = calloc (1, size);
+
+  if (!ptr)
+    abort ();
+
+  return ptr;
+}
+
 static void *
 xrealloc (void *ptr, size_t size)
 {
@@ -650,14 +664,13 @@ sfnt_read_cmap_format_8 (int fd,
   min_size = SFNT_ENDOF (struct sfnt_cmap_format_8, num_groups,
                         uint32_t);
 
-  if (INT_MULTIPLY_WRAPV (format8->num_groups, sizeof *format8->groups,
-                         &temp))
+  if (ckd_mul (&temp, format8->num_groups, sizeof *format8->groups))
     {
       xfree (format8);
       return NULL;
     }
 
-  if (INT_ADD_WRAPV (min_size, temp, &min_size))
+  if (ckd_add (&min_size, min_size, temp))
     {
       xfree (format8);
       return NULL;
@@ -742,14 +755,13 @@ sfnt_read_cmap_format_12 (int fd,
   min_size = SFNT_ENDOF (struct sfnt_cmap_format_12, num_groups,
                         uint32_t);
 
-  if (INT_MULTIPLY_WRAPV (format12->num_groups, sizeof *format12->groups,
-                         &temp))
+  if (ckd_mul (&temp, format12->num_groups, sizeof *format12->groups))
     {
       xfree (format12);
       return NULL;
     }
 
-  if (INT_ADD_WRAPV (min_size, temp, &min_size))
+  if (ckd_add (&min_size, min_size, temp))
     {
       xfree (format12);
       return NULL;
@@ -828,9 +840,8 @@ sfnt_read_cmap_format_14 (int fd,
      14 cmap table.  */
 
   size = sizeof *format14;
-  if (INT_MULTIPLY_WRAPV (num_records, sizeof *format14->records,
-                         &temp)
-      || INT_ADD_WRAPV (size, temp, &size))
+  if (ckd_mul (&temp, num_records, sizeof *format14->records)
+      || ckd_add (&size, size, temp))
     return NULL;
 
   format14 = xmalloc (size);
@@ -888,7 +899,7 @@ sfnt_read_cmap_table_1 (int fd, uint32_t directory_offset,
   off_t offset;
   struct sfnt_cmap_encoding_subtable_data header;
 
-  if (INT_ADD_WRAPV (directory_offset, table_offset, &offset))
+  if (ckd_add (&offset, directory_offset, table_offset))
     return (struct sfnt_cmap_encoding_subtable_data *) -1;
 
   if (lseek (fd, offset, SEEK_SET) == (off_t) -1)
@@ -1924,8 +1935,11 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
      simple->instructions comes one word past number_of_contours,
      because end_pts_of_contours also contains the instruction
      length.  */
-  simple->instructions = (uint8_t *) (simple->end_pts_of_contours
-                                     + glyph->number_of_contours + 1);
+
+  simple->x_coordinates = (int16_t *) (simple->end_pts_of_contours
+                                      + glyph->number_of_contours + 1);
+  simple->y_coordinates = simple->x_coordinates + number_of_points;
+  simple->instructions = (uint8_t *) (simple->y_coordinates + 
number_of_points);
   simple->flags = simple->instructions + simple->instruction_length;
 
   /* Read instructions into the glyph.  */
@@ -2009,7 +2023,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
 
   /* Now that the flags have been decoded, start decoding the
      vectors.  */
-  simple->x_coordinates = (int16_t *) (simple->flags + number_of_points);
   vec_start = flags_start;
   i = 0;
   x = 0;
@@ -2067,7 +2080,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
      pointer to the flags for the current vector.  */
   flags_start = simple->flags;
   y = 0;
-  simple->y_coordinates = simple->x_coordinates + i;
   i = 0;
 
   while (i < number_of_points)
@@ -2408,6 +2420,8 @@ sfnt_read_glyph (sfnt_glyph glyph_code,
       glyph.ymin = 0;
       glyph.xmax = 0;
       glyph.ymax = 0;
+      glyph.advance_distortion = 0;
+      glyph.origin_distortion = 0;
       glyph.simple = xmalloc (sizeof *glyph.simple);
       glyph.compound = NULL;
       memset (glyph.simple, 0, sizeof *glyph.simple);
@@ -2585,6 +2599,16 @@ struct sfnt_compound_glyph_context
 
   /* Number of elements in and the size of that array.  */
   size_t num_end_points, end_points_size;
+
+  /* The X positions of two phantom points marking this glyph's origin
+     and advance position, only used while interpreting the glyph.  */
+  sfnt_f26dot6 phantom_point_1_x, phantom_point_2_x;
+
+  /* Y positions.  */
+  sfnt_f26dot6 phantom_point_1_y, phantom_point_2_y;
+
+  /* Unrounded X positions.  */
+  sfnt_f26dot6 phantom_point_1_s, phantom_point_2_s;
 };
 
 /* Extend the arrays inside the compound glyph decomposition context
@@ -2606,24 +2630,21 @@ sfnt_expand_compound_glyph_context (struct 
sfnt_compound_glyph_context *context,
   size_t size_bytes;
 
   /* Add each field while checking for overflow.  */
-  if (INT_ADD_WRAPV (number_of_contours, context->num_end_points,
-                    &context->num_end_points))
+  if (ckd_add (&context->num_end_points, number_of_contours,
+              context->num_end_points))
     return 1;
 
-  if (INT_ADD_WRAPV (number_of_points, context->num_points,
-                    &context->num_points))
+  if (ckd_add (&context->num_points, number_of_points, context->num_points))
     return 1;
 
   /* Reallocate each array to the new size if necessary.  */
   if (context->points_size < context->num_points)
     {
-      if (INT_MULTIPLY_WRAPV (context->num_points, 2,
-                             &context->points_size))
+      if (ckd_mul (&context->points_size, context->num_points, 2))
        context->points_size = context->num_points;
 
-      if (INT_MULTIPLY_WRAPV (context->points_size,
-                             sizeof *context->x_coordinates,
-                             &size_bytes))
+      if (ckd_mul (&size_bytes, context->points_size,
+                  sizeof *context->x_coordinates))
        return 1;
 
       context->x_coordinates = xrealloc (context->x_coordinates,
@@ -2647,13 +2668,11 @@ sfnt_expand_compound_glyph_context (struct 
sfnt_compound_glyph_context *context,
 
   if (context->end_points_size < context->num_end_points)
     {
-      if (INT_MULTIPLY_WRAPV (context->num_end_points, 2,
-                             &context->end_points_size))
+      if (ckd_mul (&context->end_points_size, context->num_end_points, 2))
        context->end_points_size = context->num_end_points;
 
-      if (INT_MULTIPLY_WRAPV (context->end_points_size,
-                             sizeof *context->contour_end_points,
-                             &size_bytes))
+      if (ckd_mul (&size_bytes, context->end_points_size,
+                  sizeof *context->contour_end_points))
        return 1;
 
       context->contour_end_points
@@ -2689,11 +2708,17 @@ sfnt_round_fixed (int32_t number)
    GET_METRICS, along with DCONTEXT, mean the same as in
    sfnt_decompose_glyph.
 
+   If it has been arranged that a component's metrics (or those of an
+   innermore component also with the flag set) replace the metrics of
+   GLYPH, set *METRICS_RETURN to those metrics.  Mind that such
+   metrics are not scaled in any manner.
+
    Value is 1 upon failure, else 0.  */
 
 static int
 sfnt_decompose_compound_glyph (struct sfnt_glyph *glyph,
                               struct sfnt_compound_glyph_context *context,
+                              struct sfnt_glyph_metrics *metrics_return,
                               sfnt_get_glyph_proc get_glyph,
                               sfnt_free_glyph_proc free_glyph,
                               sfnt_get_metrics_proc get_metrics,
@@ -2783,7 +2808,7 @@ sfnt_decompose_compound_glyph (struct sfnt_glyph *glyph,
       else
        {
          /* The offset is determined by matching a point location in
-            a preceeding component with a point location in the
+            a preceding component with a point location in the
             current component.  The index of the point in the
             previous component can be determined by adding
             component->argument1.a or component->argument1.c to
@@ -2929,16 +2954,61 @@ sfnt_decompose_compound_glyph (struct sfnt_glyph *glyph,
 
              /* Copy over the contours.  */
              for (i = 0; i < number_of_contours; ++i)
-               contour_base[i] = (contour_start
-                                  + subglyph->simple->end_pts_of_contours[i]);
+               contour_base[i]
+                 = (contour_start
+                    + subglyph->simple->end_pts_of_contours[i]);
+
+             /* If USE_MY_METRICS is present within this component,
+                save its metrics within *METRICS_RETURN.  */
+
+             if (component->flags & 01000 /* USE_MY_METRICS */)
+               {
+                 if ((*get_metrics) (component->glyph_index,
+                                     metrics_return, dcontext))
+                   {
+                     if (need_free)
+                       free_glyph (subglyph, dcontext);
+
+                     return 1;
+                   }
+
+                 /* Refer to the comment above sfnt_decompose_glyph
+                    for reasons and manner in which these offsets are
+                    applied.  */
+                 metrics_return->lbearing -= subglyph->origin_distortion;
+                 metrics_return->advance += subglyph->advance_distortion;
+               }
            }
        }
       else
        {
+         /* If USE_MY_METRICS, save this subglyph's metrics within
+            sub_metrics; they might be overwritten by metrics for
+            subglyphs of this compound subglyph in turn.  */
+
+         if (component->flags & 01000 /* USE_MY_METRICS */)
+           {
+             if ((*get_metrics) (component->glyph_index,
+                                 &sub_metrics, dcontext))
+               {
+                 if (need_free)
+                   free_glyph (subglyph, dcontext);
+
+                 return 1;
+               }
+
+             /* Refer to the comment above sfnt_decompose_glyph for
+                reasons and manner in which these offsets are
+                applied.  */
+             sub_metrics.lbearing -= subglyph->origin_distortion;
+             sub_metrics.advance += subglyph->advance_distortion;
+           }
+
          /* Compound subglyph.  Decompose the glyph recursively, and
             then apply the transform.  */
          rc = sfnt_decompose_compound_glyph (subglyph,
                                              context,
+                                             &sub_metrics,
                                              get_glyph,
                                              free_glyph,
                                              get_metrics,
@@ -2953,6 +3023,11 @@ sfnt_decompose_compound_glyph (struct sfnt_glyph *glyph,
              return 1;
            }
 
+         if (component->flags & 01000 /* USE_MY_METRICS */)
+           /* Save sub_metrics inside *metrics_return as stated
+              above.  */
+           *metrics_return = sub_metrics;
+
          /* When an anchor point is being used to translate the
             glyph, and the subglyph in question is actually a
             compound glyph, it is impossible to know which offset to
@@ -3075,7 +3150,8 @@ sfnt_decompose_glyph_1 (size_t here, size_t last,
   /* The contour is empty.  */
 
   if (here == last)
-    return 1;
+    /* An empty contour, if redundant, is not necessarily invalid.  */
+    return 0;
 
   /* Move the pen to the start of the contour.  Apparently some fonts
      have off the curve points as the start of a contour, so when that
@@ -3214,7 +3290,8 @@ sfnt_decompose_glyph_2 (size_t here, size_t last,
   /* The contour is empty.  */
 
   if (here == last)
-    return 1;
+    /* An empty contour, if redundant, is not necessarily invalid.  */
+    return 0;
 
   /* Move the pen to the start of the contour.  Apparently some fonts
      have off the curve points as the start of a contour, so when that
@@ -3339,6 +3416,19 @@ sfnt_decompose_glyph_2 (size_t here, size_t last,
    GET_METRICS to obtain glyph metrics prerequisite for establishing
    their coordinates.
 
+   When glyphs originate from a GX font with an active set of
+   transforms, the correct manner of applying such transforms is to
+   apply them within GET_GLYPH, while returning unaltered metrics from
+   GET_METRICS.
+
+   If there is a component glyph within GLYPH whose metrics have been
+   indicated as replacing those of its parent glyph, the variable
+   *METRICS_RETURN will be set to its metrics with GX-induced offsets
+   applied.
+
+   *METRICS_RETURN must initially hold metrics with GX offsets
+   applied, if any.
+
    All functions will be called with DCONTEXT as an argument.
 
    The winding rule used to fill the resulting lines is described in
@@ -3350,6 +3440,7 @@ sfnt_decompose_glyph_2 (size_t here, size_t last,
 
 static int
 sfnt_decompose_glyph (struct sfnt_glyph *glyph,
+                     struct sfnt_glyph_metrics *metrics_return,
                      sfnt_move_to_proc move_to,
                      sfnt_line_to_proc line_to,
                      sfnt_curve_to_proc curve_to,
@@ -3360,6 +3451,7 @@ sfnt_decompose_glyph (struct sfnt_glyph *glyph,
 {
   size_t here, last, n;
   struct sfnt_compound_glyph_context context;
+  struct sfnt_glyph_metrics compound_metrics;
 
   if (glyph->simple)
     {
@@ -3401,7 +3493,15 @@ sfnt_decompose_glyph (struct sfnt_glyph *glyph,
   /* Decompose the specified compound glyph.  */
   memset (&context, 0, sizeof context);
 
+  /* Rather than handing METRICS_RETURN over to
+     sfnt_decompose_compound_glyph, save metrics within a temporary
+     variable and postpone returning them until it is certain the
+     decomposition has succeeded.  */
+
+  compound_metrics = *metrics_return;
+
   if (sfnt_decompose_compound_glyph (glyph, &context,
+                                    &compound_metrics,
                                     get_glyph, free_glyph,
                                     get_metrics, 0,
                                     dcontext))
@@ -3414,6 +3514,8 @@ sfnt_decompose_glyph (struct sfnt_glyph *glyph,
       return 1;
     }
 
+  *metrics_return = compound_metrics;
+
   /* Now, generate the outlines.  */
 
   if (!context.num_end_points)
@@ -3487,12 +3589,18 @@ sfnt_build_append (int flags, sfnt_fixed x, sfnt_fixed 
y)
 {
   struct sfnt_glyph_outline *outline;
 
+  outline = build_outline_context.outline;
+
   if (x == build_outline_context.x
-      && y == build_outline_context.y)
+      && y == build_outline_context.y
+      /* If the outline is presently empty, the first move_to must be
+        recorded even if its X and Y are set to origin.  Without this
+        initial vertex, edges will be generated from the next vertex
+        onward, and thus be misaligned.  */
+      && outline->outline_used)
     /* Ignore redundant motion.  */
     return build_outline_context.outline;
 
-  outline = build_outline_context.outline;
   outline->outline_used++;
 
   /* See if the outline has to be extended.  Checking for overflow
@@ -3652,7 +3760,23 @@ sfnt_multiply_divide_2 (struct sfnt_large_integer *ab,
   return q;
 }
 
-#endif
+/* Add the specified unsigned 32-bit N to the large integer
+   INTEGER.  */
+
+static void
+sfnt_large_integer_add (struct sfnt_large_integer *integer,
+                       uint32_t n)
+{
+  struct sfnt_large_integer number;
+
+  number.low = integer->low + n;
+  number.high = integer->high + (number.low
+                                < integer->low);
+
+  *integer = number;
+}
+
+#endif /* !INT64_MAX */
 
 /* Calculate (A * B) / C with no rounding and return the result, using
    a 64 bit integer if necessary.  */
@@ -3665,32 +3789,37 @@ sfnt_multiply_divide (unsigned int a, unsigned int b, 
unsigned int c)
 
   sfnt_multiply_divide_1 (a, b, &temp);
   return sfnt_multiply_divide_2 (&temp, c);
-#else
+#else /* INT64_MAX */
   uint64_t temp;
 
   temp = (uint64_t) a * (uint64_t) b;
   return temp / c;
-#endif
+#endif /* !INT64_MAX */
 }
 
-#ifndef INT64_MAX
-
-/* Add the specified unsigned 32-bit N to the large integer
-   INTEGER.  */
+/* Calculate (A * B) / C with rounding and return the result, using a
+   64 bit integer if necessary.  */
 
-static void
-sfnt_large_integer_add (struct sfnt_large_integer *integer,
-                       uint32_t n)
+static unsigned int
+sfnt_multiply_divide_rounded (unsigned int a, unsigned int b,
+                             unsigned int c)
 {
-  struct sfnt_large_integer number;
+#ifndef INT64_MAX
+  struct sfnt_large_integer temp;
 
-  number.low = integer->low + n;
-  number.high = integer->high + (number.low
-                                < integer->low);
+  sfnt_multiply_divide_1 (a, b, &temp);
+  sfnt_large_integer_add (&temp, c / 2);
+  return sfnt_multiply_divide_2 (&temp, c);
+#else /* INT64_MAX */
+  uint64_t temp;
 
-  *integer = number;
+  temp = (uint64_t) a * (uint64_t) b + c / 2;
+  return temp / c;
+#endif /* !INT64_MAX */
 }
 
+#ifndef INT64_MAX
+
 /* Calculate (A * B) / C, rounding the result with a threshold of N.
    Use a 64 bit temporary.  */
 
@@ -3705,9 +3834,9 @@ sfnt_multiply_divide_round (unsigned int a, unsigned int 
b,
   return sfnt_multiply_divide_2 (&temp, c);
 }
 
-#endif /* INT64_MAX */
+#endif /* !INT64_MAX */
 
-/* The same as sfnt_multiply_divide, but handle signed values
+/* The same as sfnt_multiply_divide_rounded, but handle signed values
    instead.  */
 
 MAYBE_UNUSED static int
@@ -3726,8 +3855,8 @@ sfnt_multiply_divide_signed (int a, int b, int c)
   if (c < 0)
     sign = -sign;
 
-  return (sfnt_multiply_divide (abs (a), abs (b), abs (c))
-         * sign);
+  return (sfnt_multiply_divide_rounded (abs (a), abs (b),
+                                       abs (c)) * sign);
 }
 
 /* Multiply the two 16.16 fixed point numbers X and Y.  Return the
@@ -3743,7 +3872,7 @@ sfnt_mul_fixed (sfnt_fixed x, sfnt_fixed y)
 
   /* This can be done quickly with int64_t.  */
   return product / (int64_t) 65536;
-#else
+#else /* !INT64_MAX */
   int sign;
 
   sign = 1;
@@ -3756,7 +3885,7 @@ sfnt_mul_fixed (sfnt_fixed x, sfnt_fixed y)
 
   return sfnt_multiply_divide (abs (x), abs (y),
                               65536) * sign;
-#endif
+#endif /* INT64_MAX */
 }
 
 /* Multiply the two 16.16 fixed point numbers X and Y, with rounding
@@ -3773,7 +3902,7 @@ sfnt_mul_fixed_round (sfnt_fixed x, sfnt_fixed y)
 
   /* This can be done quickly with int64_t.  */
   return (product + round) / (int64_t) 65536;
-#else
+#else /* !INT64_MAX */
   int sign;
 
   sign = 1;
@@ -3786,7 +3915,7 @@ sfnt_mul_fixed_round (sfnt_fixed x, sfnt_fixed y)
 
   return sfnt_multiply_divide_round (abs (x), abs (y),
                                     32768, 65536) * sign;
-#endif
+#endif /* INT64_MAX */
 }
 
 /* Set the pen size to the specified point and return.  POINT will be
@@ -3886,11 +4015,11 @@ sfnt_curve_is_flat (struct sfnt_point control0,
   h.x = endpoint.x - control0.x;
   h.y = endpoint.y - control0.y;
 
-  /* 2.0 is a constant describing the area covered at which point the
-     curve is considered "flat".  */
+  /* 1.0 is a constant representing the area covered at which point
+     the curve is considered "flat".  */
   return (abs (sfnt_mul_fixed (g.x, h.y)
               - sfnt_mul_fixed (g.y, h.x))
-         <= 0400000);
+         <= 0200000);
 }
 
 /* Recursively split the splines in the bezier curve formed from
@@ -3965,7 +4094,14 @@ sfnt_curve_to_and_build (struct sfnt_point control,
    space.
 
    Use the unscaled glyph METRICS to determine the origin point of the
-   outline.
+   outline, or those of compound glyph components within *GLYPH
+   configured to replace their parents', which if existent are
+   returned in *METRICS.  METRICS should not be altered by GX-derived
+   offsets, as they will be applied to *METRICS if present, following
+   this formula:
+
+     LBEARING = LBEARING - GLYPH->origin_distortion
+     ADVANCE = ADVANCE + GLYPH->advance_distortion
 
    Call GET_GLYPH and FREE_GLYPH with the specified DCONTEXT to obtain
    glyphs for compound glyph subcomponents, and GET_METRICS with the
@@ -4008,8 +4144,15 @@ sfnt_build_glyph_outline (struct sfnt_glyph *glyph,
   /* Set the scale factor.  */
   build_outline_context.factor = scale;
 
+  /* Apply the glyph's advance and origin distortion to METRICS in
+     advance of constructing the glyph outline, which might replace
+     METRICS with the metrics of a compound subglyph.  */
+  metrics->lbearing -= glyph->origin_distortion;
+  metrics->advance += glyph->advance_distortion;
+
   /* Decompose the outline.  */
-  rc = sfnt_decompose_glyph (glyph, sfnt_move_to_and_build,
+  rc = sfnt_decompose_glyph (glyph, metrics,
+                            sfnt_move_to_and_build,
                             sfnt_line_to_and_build,
                             sfnt_curve_to_and_build,
                             get_glyph, free_glyph, get_metrics,
@@ -4029,7 +4172,7 @@ sfnt_build_glyph_outline (struct sfnt_glyph *glyph,
      is first used to calculate the origin point, and the origin
      distortion is applied to it to get the distorted origin.  */
 
-  origin = glyph->xmin - metrics->lbearing + glyph->origin_distortion;
+  origin = glyph->xmin - metrics->lbearing;
   outline->origin = sfnt_mul_fixed (origin, scale);
 
   return outline;
@@ -4205,7 +4348,6 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline 
*outline,
 
       /* Compute the step X.  This is how much X changes for each
         increase in Y.  */
-
       step_x = sfnt_div_fixed (dx, dy);
       edges[edge].next = NULL;
 
@@ -4295,7 +4437,6 @@ sfnt_poly_edges (struct sfnt_edge *edges, size_t size,
   /* Step down line by line.  Find active edges.  */
 
   y = edges[0].bottom;
-  active = 0;
   active = NULL;
   e = 0;
 
@@ -4593,217 +4734,1102 @@ sfnt_raster_glyph_outline (struct sfnt_glyph_outline 
*outline)
 
 
 
-/* Glyph metrics computation.  */
+#define sfnt_add(a, b)                         \
+  ((int) ((unsigned int) (a) + (unsigned int) (b)))
 
-/* Read an hmtx table from the font FD, using the table directory
-   specified as SUBTABLE, the maxp table MAXP, and the hhea table
-   HHEA.
+#define sfnt_sub(a, b)                         \
+  ((int) ((unsigned int) (a) - (unsigned int) (b)))
 
-   Return NULL upon failure, and the hmtx table otherwise.
-   HHEA->num_of_long_hor_metrics determines the number of horizontal
-   metrics present, and MAXP->num_glyphs -
-   HHEA->num_of_long_hor_metrics determines the number of left-side
-   bearings present.  */
+#define sfnt_mul(a, b)                         \
+  ((int) ((unsigned int) (a) * (unsigned int) (b)))
 
-TEST_STATIC struct sfnt_hmtx_table *
-sfnt_read_hmtx_table (int fd, struct sfnt_offset_subtable *subtable,
-                     struct sfnt_hhea_table *hhea,
-                     struct sfnt_maxp_table *maxp)
-{
-  struct sfnt_table_directory *directory;
-  struct sfnt_hmtx_table *hmtx;
-  size_t size;
-  ssize_t rc;
-  int i;
+
 
-  /* Find the table in the directory.  */
+/* Exact coverage scaler.
 
-  directory = sfnt_find_table (subtable, SFNT_TABLE_HMTX);
+   The foregoing routines calculate partial coverage for each pixel by
+   increasing each span in increments finer than a single pixel, then
+   merging active spans into the raster.
 
-  if (!directory)
-    return NULL;
+   Experience has proven this yields imperfect display results,
+   particularly when combined with glyph instruction code which aligns
+   points in a certain and as yet undetermined manner.
 
-  /* Figure out how many bytes are required.  */
-  size = ((hhea->num_of_long_hor_metrics
-          * sizeof (struct sfnt_long_hor_metric))
-         + (MAX (0, ((int) maxp->num_glyphs
-                     - hhea->num_of_long_hor_metrics))
-            * sizeof (int16_t)));
+   The scaler implemented in this page attains greater precision,
+   generating at length an array of scanlines, in which each is
+   represented by a list of steps.  Each step holds an X coordinate
+   and a coverage value, which contributes to the coverage of each
+   pixel within the scanline rightwards or equal to the pixel with its
+   X coordinate.
 
-  /* Check the length matches exactly.  */
-  if (directory->length != size)
-    return NULL;
+   Such a coverage value can be positive or negative; when the winding
+   direction of the span it derives from is positive, so is the
+   coverage value, that the pixels to its right (thus further into the
+   polygon it demarcates) might be painted in.  In the other case, the
+   value is negative, thus negating the effect of preceding steps and
+   marking the outer boundary of the section of the polygon's
+   intersection with the scanline.
 
-  /* Seek to the location given in the directory.  */
-  if (lseek (fd, directory->offset, SEEK_SET) == (off_t) -1)
-    return NULL;
+   The procedure for producing this array of scanlines is largely an
+   adaptation of that which sfnt_poly_edges implements; in particular
+   the process of sorting and filtering edges remains untouched.
 
-  /* Now allocate enough to hold all of that along with the table
-     directory structure.  */
+   Rather than advancing through the edges SFNT_POLY_STEP at a time,
+   the edges are iterated over scanline-by-scanline.  Every edge
+   overlapping with a particular scanline is considered piecemeal to
+   generate its array of steps.
 
-  hmtx = xmalloc (sizeof *hmtx + size);
+   An edge might overlap pixels within the scanline in one of four
+   fashions; each is illustrated with a graphic below:
 
-  /* Read into hmtx + 1.  */
-  rc = read (fd, hmtx + 1, size);
-  if (rc == -1 || rc < size)
-    {
-      xfree (hmtx);
-      return NULL;
-    }
+   +--------ee-----+------------------------------------------------+ (I)
+   |      ee.......|................................................|
+   |    ee.........|................................................|
+   |  ee...........|................................................|
+   |ee.............|................................................|
+  ee---------------+------------------------------------------------+
 
-  /* Set pointers to data.  */
-  hmtx->h_metrics = (struct sfnt_long_hor_metric *) (hmtx + 1);
-  hmtx->left_side_bearing
-    = (int16_t *) (hmtx->h_metrics
-                  + hhea->num_of_long_hor_metrics);
+   In this instance, the edge partially overlaps its first pixel, but
+   the remainder all receive complete coverage.
 
-  /* Swap what was read.  */
+   +---------------+---------eeeeee+--------------------------------+ (II)
+   |               |   eeeeee......|................................|
+   |                     eeeee............|................................|
+   |        eeeeee.|...............|................................|
+   |  eeeeee.......|...............|................................|
+   eee-------------+---------------+--------------------------------+
 
-  for (i = 0; i < hhea->num_of_long_hor_metrics; ++i)
-    {
-      sfnt_swap16 (&hmtx->h_metrics[i].advance_width);
-      sfnt_swap16 (&hmtx->h_metrics[i].left_side_bearing);
-    }
+   In this instance, the edge partially overlaps two or more pixels on
+   this scanline.  These pixels are referred to as a run.
 
-  for (; i < maxp->num_glyphs; ++i)
-    sfnt_swap16 (&hmtx->left_side_bearing[i - hhea->num_of_long_hor_metrics]);
+   +---------------+---------------+----------------+---------------+ (III)
+   |       eeeeeee.|...............|................|...............|
+   |            eeeeeeee..|...............|................|...............|
+   |   eeeeeeee....|...............|................|...............|
+   |  eeeeeee......|...............|................|...............|
+   +---------------+---------------+----------------+---------------+
 
-  /* All done.  */
-  return hmtx;
-}
+   This instance is much like the first instance, save that the
+   covered vertical area does not span the entire scanline.
 
-/* Obtain glyph metrics for the glyph indiced by GLYPH at the
-   specified PIXEL_SIZE.  Return 0 and the metrics in *METRICS if
-   metrics could be found, else 1.
+   +---------------+---------------+----------------+---------------+ (IV)
+   |               |               |                | eeeeeeeeeee...|
+   |                      |              eeeeeeeeeeeeeeeeeeeeeeeeeeeeeee...|
+   |          eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee|...............|
+   |eeeeeeeeeeeeeeeeeeeeeee........|................|...............|
+   +---------------+---------------+----------------+---------------+
 
-   If PIXEL_SIZE is -1, do not perform any scaling on the glyph
-   metrics; HEAD need not be specified in that case.
+   And this the second, again with the same distinction therefrom.
 
-   HMTX, HHEA, HEAD and MAXP should be the hmtx, hhea, head, and maxp
-   tables of the font respectively.  */
+   In each of these instances, a trapezoid is formed within every
+   pixel of the scanline, between:
 
-TEST_STATIC int
-sfnt_lookup_glyph_metrics (sfnt_glyph glyph, int pixel_size,
-                          struct sfnt_glyph_metrics *metrics,
-                          struct sfnt_hmtx_table *hmtx,
-                          struct sfnt_hhea_table *hhea,
-                          struct sfnt_head_table *head,
-                          struct sfnt_maxp_table *maxp)
-{
-  short lbearing;
-  unsigned short advance;
-  sfnt_fixed factor;
+     - The point of the span's entry into the first pixel, either that
+       point itself or, for subsequent pixels, its projection onto
+       those pixels.
 
-  if (glyph < hhea->num_of_long_hor_metrics)
-    {
-      /* There is a long entry in the hmtx table.  */
-      lbearing = hmtx->h_metrics[glyph].left_side_bearing;
-      advance = hmtx->h_metrics[glyph].advance_width;
-    }
-  else if (hhea->num_of_long_hor_metrics
-          && glyph < maxp->num_glyphs)
-    {
-      /* There is a short entry in the hmtx table.  */
-      lbearing
-       = hmtx->left_side_bearing[glyph
-                                 - hhea->num_of_long_hor_metrics];
-      advance
-       = hmtx->h_metrics[hhea->num_of_long_hor_metrics - 1].advance_width;
-    }
-  else
-    /* No entry corresponds to the glyph.  */
-    return 1;
+     - The point of the span's exit or its termination.
 
-  if (pixel_size == -1)
-    {
-      /* Return unscaled metrics in this case.  */
-      metrics->lbearing = lbearing;
-      metrics->advance = advance;
-      return 0;
-    }
+     - Both those points projected into the outer boundary of the
+       pertinent pixel.
 
-  /* Now scale lbearing and advance up to the pixel size.  */
-  factor = sfnt_div_fixed (pixel_size, head->units_per_em);
+   The proportion formed by the area of this trapezoid and that of the
+   pixel then constitutes the coverage value to be recorded.  */
 
-  /* Save them.  */
-  metrics->lbearing = sfnt_mul_fixed (lbearing * 65536, factor);
-  metrics->advance = sfnt_mul_fixed (advance * 65536, factor);
+/* Structure representing a step, as above.  */
 
-  /* All done.  */
-  return 0;
-}
+struct sfnt_step
+{
+  /* The next step in this list.  */
+  struct sfnt_step *next;
 
-/* Scale the specified glyph metrics by FACTOR.
-   Set METRICS->lbearing and METRICS->advance to their current
-   values times factor.  */
+  /* X coordinate of the step.  This value affects all pixels at and
+     beyond this X coordinate.  */
+  int x;
 
-MAYBE_UNUSED TEST_STATIC void
-sfnt_scale_metrics (struct sfnt_glyph_metrics *metrics,
-                   sfnt_fixed factor)
-{
-  metrics->lbearing
-    = sfnt_mul_fixed (metrics->lbearing * 65536, factor);
-  metrics->advance
-    = sfnt_mul_fixed (metrics->advance * 65536, factor);
-}
+  /* Coverage value between -1 and 1.  */
+  float coverage;
+};
 
-/* Calculate the factor used to convert em space to device space for a
-   font with the specified HEAD table and PPEM value.  */
+/* Structure representing an array of steps, one for each
+   scanline.  */
 
-MAYBE_UNUSED TEST_STATIC sfnt_fixed
-sfnt_get_scale (struct sfnt_head_table *head, int ppem)
+struct sfnt_step_raster
 {
-  /* Figure out how to convert from font unit-space to pixel space.
-     To turn one unit to its corresponding pixel size given a ppem of
-     1, the unit must be divided by head->units_per_em.  Then, it must
-     be multipled by the ppem.  So,
+  /* Number of scanlines within this raster.  */
+  size_t scanlines;
 
-       PIXEL = UNIT / UPEM * PPEM
+  /* Array of steps with one element for each scanline.  */
+  struct sfnt_step **steps;
 
-     which means:
+  /* Linked list of chunks of steps allocated for this raster.  */
+  struct sfnt_step_chunk *chunks;
+};
 
-       PIXEL = UNIT * PPEM / UPEM  */
+enum
+  {
+    SFNT_BLOCK_STEPS = 128,
+  };
 
-  return sfnt_div_fixed (ppem, head->units_per_em);
-}
+/* Structure representing a block of steps, which are allocated
+   SFNT_BLOCK_STEPS at a time.  */
 
-
+struct sfnt_step_chunk
+{
+  /* The next chunk in this list, or NULL.  */
+  struct sfnt_step_chunk *next;
 
-/* Font style parsing.  */
+  /* Number of steps used within this chunk thus far.  */
+  size_t nused;
 
-/* Read the name table from the given font FD, using the table
-   directory specified as SUBTABLE.  Perform validation on the offsets
-   in the name records.  Return NULL upon failure, else the name
-   table.  */
+  /* The steps themselves.  */
+  struct sfnt_step steps[SFNT_BLOCK_STEPS];
+};
 
-TEST_STATIC struct sfnt_name_table *
-sfnt_read_name_table (int fd, struct sfnt_offset_subtable *subtable)
-{
-  struct sfnt_table_directory *directory;
-  struct sfnt_name_table *name;
-  size_t required;
-  ssize_t rc;
-  int i;
+/* Structure representing an edge as consumed by the exact coverage
+   scaler.  This structure is much like struct sfnt_edge, albeit with
+   all fractionals replaced by floating point numbers and an extra
+   field holding a Y delta.  */
 
-  /* Find the table in the directory.  */
+struct sfnt_fedge
+{
+  /* Next edge in this chain.  */
+  struct sfnt_fedge *next;
 
-  directory = sfnt_find_table (subtable, SFNT_TABLE_NAME);
+  /* Winding direction.  1 if clockwise, -1 if counterclockwise.  */
+  int winding;
 
-  if (!directory)
-    return NULL;
+  /* X position, top and bottom of edges.  */
+  float x, top, bottom;
 
-  /* Seek to the location given in the directory.  */
-  if (lseek (fd, directory->offset, SEEK_SET) == (off_t) -1)
-    return NULL;
+  /* Amount to move X by upon each change of Y, and vice versa.  */
+  float step_x, step_y;
+};
 
-  /* Figure out the minimum that has to be read.  */
-  required = SFNT_ENDOF (struct sfnt_name_table,
-                        string_offset, uint16_t);
+typedef void (*sfnt_fedge_proc) (struct sfnt_fedge *, size_t,
+                                void *);
 
-  if (directory->length < required)
-    return NULL;
+/* Build a list of edges for each contour in OUTLINE, displacing each
+   edge by xmin and ymin.  Call EDGE_PROC with DCONTEXT and the edges
+   produced as arguments.  */
 
-  /* Allocate enough to hold the name table and variable length
+static void
+sfnt_build_outline_fedges (struct sfnt_glyph_outline *outline,
+                          sfnt_fedge_proc edge_proc, void *dcontext)
+{
+  struct sfnt_fedge *edges;
+  size_t i, edge, next_vertex;
+  sfnt_fixed dx, dy, step_x, step_y, ymin, xmin;
+  size_t top, bottom;
+
+  edges = alloca (outline->outline_used * sizeof *edges);
+  edge = 0;
+
+  /* ymin and xmin must be the same as the offset used to set offy and
+     offx in rasters.  */
+  ymin = sfnt_floor_fixed (outline->ymin);
+  xmin = sfnt_floor_fixed (outline->xmin);
+
+  for (i = 0; i < outline->outline_used; ++i)
+    {
+      /* Set NEXT_VERTEX to the next point (vertex) in this contour.
+
+        If i is past the end of the contour, then don't build edges
+        for this point.  */
+      next_vertex = i + 1;
+
+      if (next_vertex == outline->outline_used
+         || !(outline->outline[next_vertex].flags
+              & SFNT_GLYPH_OUTLINE_LINETO))
+       continue;
+
+      /* Skip past horizontal vertices.  */
+      if (outline->outline[next_vertex].y == outline->outline[i].y)
+       continue;
+
+      /* Figure out the winding direction.  */
+      if (outline->outline[next_vertex].y < outline->outline[i].y)
+       /* Vector will cross imaginary ray from its bottom from the
+          left of the ray.  Winding is thus 1.  */
+       edges[edge].winding = 1;
+      else
+       /* Moving clockwise.  Winding is thus -1.  */
+       edges[edge].winding = -1;
+
+      /* Figure out the top and bottom values of this edge.  If the
+        next edge is below, top is here and bot is the edge below.
+        If the next edge is above, then top is there and this is the
+        bottom.  */
+
+      if (outline->outline[next_vertex].y < outline->outline[i].y)
+       {
+         /* End of edge is below this one (keep in mind this is a
+            cartesian coordinate system, so smaller values are below
+            larger ones.) */
+         top = i;
+         bottom = next_vertex;
+       }
+      else
+       {
+         /* End of edge is above this one.  */
+         bottom = i;
+         top = next_vertex;
+       }
+
+      /* Record the edge.  Rasterization happens from bottom to
+        up, so record the X at the bottom.  */
+      dx = (outline->outline[top].x - outline->outline[bottom].x);
+      dy = abs (outline->outline[top].y
+               - outline->outline[bottom].y);
+
+      /* Compute the step X.  This is how much X changes for each
+        increase in Y.  */
+      step_x = sfnt_div_fixed (dx, dy);
+
+      /* And the step Y, which is the amount of movement to Y an
+        increase in X will incur.  */
+      step_y = dx ? sfnt_div_fixed (dy, dx) : 0;
+
+      /* Save information computed above into the edge.  */
+      edges[edge].top
+       = sfnt_fixed_float (outline->outline[top].y - ymin);
+      edges[edge].bottom
+       = sfnt_fixed_float (outline->outline[bottom].y - ymin);
+      edges[edge].x
+       = sfnt_fixed_float (outline->outline[bottom].x - xmin);
+      edges[edge].step_x = sfnt_fixed_float (step_x);
+      edges[edge].step_y = sfnt_fixed_float (step_y);
+      edges[edge].next = NULL;
+
+      /* Increment the edge index.  */
+      edge++;
+    }
+
+  if (edge)
+    edge_proc (edges, edge, dcontext);
+}
+
+typedef void (*sfnt_step_raster_proc) (struct sfnt_step_raster *, void *);
+
+/* Append a step with the supplied COVERAGE at X to the sorted list of
+   scanline steps within the container RASTER.  Y is the scanline to
+   append to.  */
+
+static void
+sfnt_insert_raster_step (struct sfnt_step_raster *raster,
+                        int x, float coverage, size_t scanline)
+{
+  struct sfnt_step_chunk *chunk;
+  struct sfnt_step *step, **p_next;
+
+  if (scanline >= raster->scanlines)
+    return;
+
+  if (x < 0)
+    x = 0;
+
+  /* Search within RASTER->steps[scanline] for a step at X.  */
+
+  p_next = &raster->steps[scanline];
+
+  while ((step = *p_next))
+    {
+      if (step->x > x)
+       break;
+
+      if (step->x == x)
+       goto found;
+
+      p_next = &step->next;
+    }
+
+  if (!raster->chunks
+      || raster->chunks->nused == SFNT_BLOCK_STEPS)
+    {
+      /* All chunks have been consumed, and consequently a new chunk
+        must be allocated.  */
+      chunk = xmalloc (sizeof *chunk);
+      chunk->next = raster->chunks;
+      chunk->nused = 0;
+      raster->chunks = chunk;
+    }
+  else
+    chunk = raster->chunks;
+
+  step          = &chunk->steps[chunk->nused++];
+  step->next    = *p_next;
+  *p_next       = step;
+  step->x       = x;
+  step->coverage = 0;
+
+ found:
+  step->coverage += coverage;
+}
+
+/* Draw EDGES, an unsorted array of polygon edges of size NEDGES.
+
+   Transform EDGES into an array of steps representing a raster with
+   HEIGHT scanlines, then call POLY_FUNC with DCONTEXT and the
+   resulting struct sfnt_step_raster to transfer it onto an actual
+   raster.
+
+   WIDTH must be the width of the raster.  Although there is no
+   guarantee that no steps generated extend past WIDTH, steps starting
+   after width might be omitted, and as such it must be accurate.  */
+
+static void
+sfnt_poly_edges_exact (struct sfnt_fedge *edges, size_t nedges,
+                      size_t height, size_t width,
+                      sfnt_step_raster_proc proc, void *dcontext)
+{
+  int y;
+  size_t size, e, edges_processed;
+  struct sfnt_fedge *active, **prev, *a, sentinel;
+  struct sfnt_step_raster raster;
+  struct sfnt_step_chunk *next, *last;
+
+  if (!height)
+    return;
+
+  /* Step down line by line.  Find active edges.  */
+
+  y = sfnt_floor_fixed (MAX (0, edges[0].bottom));
+  e = edges_processed = 0;
+  active = &sentinel;
+
+  /* Allocate the array of edges.  */
+
+  raster.scanlines = height;
+  raster.chunks    = NULL;
+
+  if (ckd_mul (&size, height, sizeof *raster.steps))
+    abort ();
+
+  raster.steps = xzalloc (size);
+
+  for (; y != height; y += 1)
+    {
+      /* Run over the whole array on each iteration of this loop;
+        experiments demonstrate this is faster for the majority of
+        glyphs.  */
+      for (e = 0; e < nedges; ++e)
+       {
+         /* Although edges is unsorted, edges which have already been
+            processed will see their next fields set, and can thus be
+            disregarded.  */
+         if (!edges[e].next
+             && (edges[e].bottom < y + 1)
+             && (edges[e].top > y))
+           {
+             /* As steps generated from each edge are sorted at the
+                time of their insertion, sorting the list of active
+                edges itself is redundant.  */
+             edges[e].next = active;
+             active = &edges[e];
+
+             /* Increment the counter recording the number of edges
+                processed, which is used to terminate this loop early
+                once all have been processed.  */
+             edges_processed++;
+           }
+       }
+
+      /* Iterate through each active edge, appending steps for it, and
+        removing it if it does not overlap with the next
+        scanline.  */
+
+      for (prev = &active; (a = *prev) != &sentinel;)
+       {
+         float x_top, x_bot, x_min, x_max;
+         float y_top, y_bot;
+         int x_pixel_min, x_pixel_max;
+
+#define APPEND_STEP(x, coverage)                               \
+         sfnt_insert_raster_step (&raster, x, coverage, y);
+
+         /* Calculate several values to establish which overlap
+            category this edge falls into.  */
+
+         y_top = y + 1; /* Topmost coordinate covered by this
+                           edge in this scanline.  */
+         y_bot = y;     /* Bottom-most coordinate covered by this
+                           edge in this scanline.  */
+
+         /* III or IV?  If the edge terminates before the next
+            scanline, make its terminus y_top.  */
+
+         if (y_top > a->top)
+           y_top = a->top;
+
+         /* Same goes for y_bottom.  */
+
+         if (a->bottom > y_bot)
+           y_bot = a->bottom;
+
+         /* y_top should never equal y_bottom, but check to be on the
+            safe side.  */
+         if (y_top == y_bot)
+           goto next;
+
+         /* x_top and x_bot are the X positions where the edge enters
+            and exits this scanline.  */
+
+         /*
+           (x_top)
+   +--------ee-----+------------------------------------------------+ (y_top)
+   |      ee.......|................................................|
+   |    ee.........|................................................|
+   |  ee...........|................................................|
+   |ee.............|................................................|
+  ee---------------+------------------------------------------------+ (y_bot)
+(x_bot)
+            (y_bot might be further below.)
+         */
+
+         x_top = (y_top - a->bottom) * a->step_x + a->x;
+         x_bot = (y_bot - a->bottom) * a->step_x + a->x;
+
+         x_min = MIN (x_top, x_bot);
+         x_max = MAX (x_top, x_bot);
+
+         /* Pixels containing x_bot and x_top respectively.  */
+         x_pixel_min = (int) (x_min);
+         x_pixel_max = (int) (x_max);
+
+#define TRAPEZOID_AREA(height, top_start, top_end, bot_start, bot_end) \
+         ((((float) (top_end) - (top_start))                           \
+           + ((float) (bot_end) - (bot_start)))                        \
+          / 2.0f * (float) (height))
+
+         /* I, III?  These two instances' criteria are that the edge
+            enters and exits within one pixel.  */
+
+         if (x_pixel_min == x_pixel_max)
+           {
+             float xmin, xmax, ytop, ybot, height;
+             float coverage, delta;
+
+             /* Partial coverage for the first pixel.  */
+
+             xmin = (x_min);
+             xmax = (x_max);
+             ytop = (y_top);
+             ybot = (y_bot);
+             height = ytop - ybot;
+
+             /* The trapezoid here is one of the following two:
+
+  ytop+------xmax--+-----------+---------------------------------------------+
+      |     /................................................................|
+      |    /.......|...........|.............................................|
+      |   /........|...........|.............................................|
+      |  /.........|...........|.............................................|
+      | / ...................................................................|
+  xmin+------------+-----------+---------------------------------------------+
+      ybot
+  ytop+------------+-----------+---------------------------------------------+
+      |\ xmin................................................................|
+      | \..........|...........|.............................................|
+      |  \.........|...........|.............................................|
+      |   \........|...........|.............................................|
+      |    \.......|...........|.............................................|
+      |     \................................................................|
+      +------xmax--+-----------+---------------------------------------------+
+
+                 In either situation, the first pixel's coverage is
+                 the space occupied by a trapezoid whose corners are
+                 xmin and x_pixel_min + 1 and xmax and x_pixel_min +
+                 1, and whose height is ytop - ybot.  The coverage for
+                 the remainder is the height alone.  */
+
+             coverage = (TRAPEZOID_AREA (height,
+                                         xmin, (int) xmin + 1,
+                                         xmax, (int) xmax + 1)
+                         * a->winding);
+             APPEND_STEP (x_pixel_min, coverage);
+
+             /* Then if the next pixel isn't beyond the raster,
+                append complete coverage for it.  */
+
+             if (x_pixel_min + 1 < width)
+               {
+                 delta = (y_top - y_bot) * a->winding;
+                 APPEND_STEP (x_pixel_max + 1, delta - coverage);
+               }
+           }
+         else
+           {
+             float dy, y_crossing, coverage;
+             float ytop, ybot, xtop, xbot, increment;
+             float x, last, here;
+
+             ytop = (y_top);
+             ybot = (y_bot);
+             xtop = (x_top);
+             xbot = (x_bot);
+
+#define TRIANGLE_AREA(width, height)                                   \
+             ((width) * (height) / 2.0f)
+
+             /* II, IV.  Coverage must be computed for each pixel
+                from x_pixel_min to x_pixel_max, with the latter
+                treated much as in I or III.  */
+
+             if (x_bot < x_top)
+               {
+                 /*
+
+
+  y_top                                                         x_top
+       
+-----------+-----------+-----------+------------+-------/------+-------------------------------+
+       |           |           |           |            |    
/--.......|...............................|
+       |x_pixel_min|           |           |            | 
/--..........|...............................|
+       |           |           |           |           
/+-y_crossing...|...............................|
+       |           |           |           |        
/--.|..............|...............................|
+       |           |           |           |      
/-....|..............|...............................|
+       |           |           |           |   
/--......|..x_pixel_max.|...............................|
+       |           |           |           
|/--.........|..............|...............................|
+       |           |           |         
/-+............|..............|...............................|
+       |           |           |      
/--..|............|..............|...............................|
+       |           |           |   
/--.....|............|..............|...............................|
+       |           |           
|/--........|............|..............|...............................|
+       |           |         
/-+...........|............|..............|...............................|
+       |           |      
/--..|...........|............|..............|...............................|
+       |           |   
/--.....|...........|............|..............|...............................|
+       |           | 
/-........|...........|............|..............|...............................|
+       |          
/+-y_crossing|...........|............|..............|...............................|
+       |       
/--.|...........|...........|............|..............|...............................|
+       |    
/--....|...........|...........|............|..............|...............................|
+       | 
/--.......|...........|...........|............|..............|...............................|
+       
+-----------+-----------+-----------+------------+--------------+-------------------------------+
+  y_bot x_bot
+
+
+The purpose of this code is to calculate the area occupied by dots of
+each pixel in between x_pixel_min and x_pixel_max + 1.
+
+The area occupied in the first pixel is a triangle comprising [x_bot,
+y_bot], [x_bot + 1, y_bot], and [x_bot + 1, y_crossing].
+
+The area occupied in the second pixel through x_pixel_max - 1 is that
+of a rectangle comprising [y_bot, pixel], [the previous rectangle's
+y_crossing, pixel], [the previous rectangle's y_crossing, pixel + 1],
+and [pixel + 1, y_bot] summed with the area the remaining triangle.
+
+The area occupied in the last pixel is a trapezoid proper.
+
+Thus the procedure is roughly as follows: dy is computed, which is the
+increase to the Y of the edge for each increase in scanline X.  */
+
+                 dy = a->step_y;
+
+                 /* As is y_crossing for the first pixel.  */
+                 y_crossing = ybot + dy * ((int) xbot + 1 - xbot);
+
+                 /* And the area of the first triangle.
+
+                    The width is (int) xbot + 1 - xbot, and the
+                    height is y_crossing - ybot.  */
+                 last = ((TRIANGLE_AREA (y_crossing - ybot,
+                                         (int) xbot + 1 - xbot))
+                         * a->winding);
+                 APPEND_STEP (x_pixel_min, last);
+
+                 /* Coverage value for subsequent rectangles.  The
+                    value set here is for the next pixel, which is
+                    filled from ybot to y_crossing.  */
+
+                 coverage = (y_crossing - ybot) * a->winding;
+                 increment = dy * a->winding;
+
+                 for (x = x_pixel_min + 1; x < x_pixel_max; x++)
+                   {
+                     here = coverage + increment / 2;
+                     APPEND_STEP (x, here - last);
+                     last = here;
+                     coverage += increment;
+                   }
+
+                 /* The y_crossing for the last pixel.  */
+                 y_crossing = ybot + dy * ((int) xtop - xbot);
+
+                 /* And calculate the area of the trapezoid in the
+                    last pixel.  */
+
+                 coverage += a->winding * TRAPEZOID_AREA (ytop - y_crossing,
+                                                          xtop,
+                                                          (int) xtop + 1,
+                                                          (int) xtop,
+                                                          (int) xtop + 1);
+                 here = coverage;
+                 APPEND_STEP (x_pixel_max, here - last);
+                 last = here;
+
+                 /* Fill the remainder of the scanline with
+                    height-derived coverage.  */
+
+                 if (x_pixel_max + 1 < width)
+                   APPEND_STEP (x_pixel_max + 1, ((y_top - y_bot)
+                                                  * a->winding - last));
+               }
+             else /* if (x_bot > x_top) */
+               {
+                 /*
+
+  y_top   x_top
+    
+----------------+----------------+-----------------+-----------------+-----------------------------+
+    |     
\--........|................|.................|.................|.............................|
+    |        
\--.....|................|.................|.................|.............................|
+    |           
\--..|................|.................|.................|.............................|
+    |              
\-+.y_crossing.....|.................|.................|.............................|
+    |                
|\--.............|.................|.................|.............................|
+    |                |   
\--..........|.................|.................|.............................|
+    |  x_pixel_min   |      
\---......|.................|.................|.............................|
+    |                |          
\--...|.................|.................|.............................|
+    |                |             
\--|y_crossing.......|.................|.............................|
+    |                |                
\--...............|.................|.............................|
+    |                |                |  
\--............|.................|.............................|
+    |                |                |     
\--.........|.................|.............................|
+    |                |                |        
\--......|.................|.............................|
+    
+----------------+----------------+-----------\-----+-----------------+-----------------------------+
+  y_bot                                        x_bot
+
+Whereas in this situation the trapezoid is inverted, and the code must
+be as well.  */
+
+                 /* The edge's Y decreases as the edge's X increases,
+                    yielding a negative a->step_x.  */
+                 dy = a->step_y;
+
+                 /* Calculate y_crossing for the first pixel.  */
+                 y_crossing = ytop + dy * ((int) xtop + 1 - xtop);
+
+                 /* And the area of the first triangle.  */
+                 last = ((TRIANGLE_AREA ((int) xtop + 1 - xtop,
+                                         ytop - y_crossing))
+                         * a->winding);
+                 APPEND_STEP (x_pixel_min, last);
+
+                 /* Coverage value for subsequent rectangles.  The
+                    value set here is for the next pixel, which is
+                    filled from ytop to y_crossing.  */
+                 coverage = (ytop - y_crossing) * a->winding;
+                 increment = -dy * a->winding;
+
+                 for (x = x_pixel_min + 1; x < x_pixel_max; x ++)
+                   {
+                     here = coverage + increment / 2;
+                     APPEND_STEP (x, here - last);
+                     last = here;
+                     coverage += increment;
+                   }
+
+                 /* The y_crossing for the last pixel.  */
+                 y_crossing = ytop + dy * ((int) xbot - xtop);
+
+                 /* And calculate the area of the trapezoid in the
+                    last pixel.  */
+
+                 coverage += a->winding * TRAPEZOID_AREA (y_crossing - ybot,
+                                                          (int) xbot,
+                                                          (int) xbot + 1,
+                                                          xbot,
+                                                          (int) xbot + 1);
+                 here = coverage;
+                 APPEND_STEP (x_pixel_max, here - last);
+                 last = here;
+
+                 /* Fill the remainder of the scanline with
+                    height-derived coverage.  */
+
+                 if (x_pixel_max + 1 < width)
+                   APPEND_STEP (x_pixel_max + 1, ((y_top - y_bot)
+                                                  * a->winding - last));
+               }
+
+#undef TRIANGLE_AREA
+           }
+
+#undef APPEND_STEP
+#undef TRAPEZOID_AREA
+
+         /* When an edge is created, its a->bottom (and by extension
+            a->y) is not aligned to a->x.  Since this iteration can
+            only affect the scan line Y, align a to the next
+            scanline, that the next iteration of this loop to
+            consider it might consider its entire intersection.  */
+         a->x += a->step_x * (y + 1 - a->bottom);
+         a->bottom = y + 1;
+       next:
+
+         if (a->top < y + 1)
+           *prev = a->next;
+         else
+           /* This edge doesn't intersect with the next scanline;
+              remove it from the list.  After the edge at hand is so
+              deleted from the list, its next field remains set,
+              excluding it from future consideration.  */
+           prev = &a->next;
+       }
+
+      /* Break if all is done.  */
+      if (active == &sentinel && edges_processed == nedges)
+       break;
+    }
+
+  (*proc) (&raster, dcontext);
+  xfree (raster.steps);
+
+  /* Free each block of steps allocated.  */
+  next = raster.chunks;
+  while (next)
+    {
+      last = next;
+      next = next->next;
+      xfree (last);
+    }
+}
+
+/* Apply winding rule to the coverage value VALUE.  Convert VALUE to a
+   number between 0 and 255.  If VALUE is negative, invert it.  If it
+   exceeds 255 afterwards, truncate it to 255.  */
+
+static int
+sfnt_compute_fill (float value)
+{
+  if (value < 0)
+    value = -value;
+
+  return MIN (value * 255, 255);
+}
+
+/* Set N pixels at DATA to the value VALUE.  If N is large, call
+   memset; otherwise set this by hand.  */
+
+static void
+sfnt_poly_set_steps (unsigned char *data, int value, int n)
+{
+  unsigned char *p;
+
+  p = data;
+  switch (n)
+    {
+    case 7:
+      *p++ = value;
+      FALLTHROUGH;
+    case 6:
+      *p++ = value;
+      FALLTHROUGH;
+    case 5:
+      *p++ = value;
+      FALLTHROUGH;
+    case 4:
+      *p++ = value;
+      FALLTHROUGH;
+    case 3:
+      *p++ = value;
+      FALLTHROUGH;
+    case 2:
+      *p++ = value;
+      FALLTHROUGH;
+    case 1:
+      *p++ = value;
+      FALLTHROUGH;
+    case 0:
+      break;
+    default:
+      memset (data, value, n);
+    }
+}
+
+/* Transfer steps generated by sfnt_poly_edges_exact from STEPS to the
+   provided raster RASTER.  */
+
+static void
+sfnt_poly_steps (struct sfnt_step_raster *steps,
+                struct sfnt_raster *raster)
+{
+  int y;
+  unsigned char *data;
+  int x, xend, fill;
+  float total;
+  struct sfnt_step *step;
+
+  y = 0; /* This y is an X-style coordinate in RASTER's space.
+
+           Its counterpart array of steps is STEPS->steps[
+           raster->height - y - 1].  */
+  data = raster->cells;
+
+  for (y = 0; y < raster->height; ++y, data += raster->stride)
+    {
+      fill = total = x = 0;
+
+      for (step = steps->steps[raster->height - y - 1];
+          step && x < raster->width; step = step->next)
+       {
+         xend = MIN (step->x, raster->width);
+
+         if (fill)
+           sfnt_poly_set_steps (data + x, fill, xend - x);
+
+         total += step->coverage;
+         fill = sfnt_compute_fill (total);
+         x = xend;
+       }
+
+      if (x < raster->width)
+        sfnt_poly_set_steps (data + x, fill, raster->width - x);
+    }
+}
+
+/* Poly each edge in EDGES onto the raster supplied in DCONTEXT.  */
+
+static void
+sfnt_raster_steps (struct sfnt_step_raster *steps, void *dcontext)
+{
+  sfnt_poly_steps (steps, dcontext);
+}
+
+/* Call sfnt_poly_edges_exact with suitable arguments for polying
+   EDGES onto DCONTEXT, a raster structure.  */
+
+static void
+sfnt_raster_edges_exact (struct sfnt_fedge *edges, size_t size,
+                        void *dcontext)
+{
+  struct sfnt_raster *raster;
+
+  raster = dcontext;
+  sfnt_poly_edges_exact (edges, size, raster->height,
+                        raster->width, sfnt_raster_steps,
+                        dcontext);
+}
+
+/* Generate an alpha mask for the glyph outline OUTLINE by means of
+   the exact coverage scaler.  Value is the alpha mask upon success,
+   NULL upon failure.  */
+
+TEST_STATIC struct sfnt_raster *
+sfnt_raster_glyph_outline_exact (struct sfnt_glyph_outline *outline)
+{
+  struct sfnt_raster raster, *data;
+
+  /* Get the raster parameters.  */
+  sfnt_prepare_raster (&raster, outline);
+
+  /* Allocate the raster data.  */
+  data = xmalloc (sizeof *data + raster.stride * raster.height);
+  *data = raster;
+  data->cells = (unsigned char *) (data + 1);
+  memset (data->cells, 0, raster.stride * raster.height);
+
+  /* Generate edges for the outline, polying each array of edges to
+     the raster.  */
+  sfnt_build_outline_fedges (outline, sfnt_raster_edges_exact, data);
+
+  /* All done.  */
+  return data;
+}
+
+
+
+/* Glyph metrics computation.  */
+
+/* Read an hmtx table from the font FD, using the table directory
+   specified as SUBTABLE, the maxp table MAXP, and the hhea table
+   HHEA.
+
+   Return NULL upon failure, and the hmtx table otherwise.
+   HHEA->num_of_long_hor_metrics determines the number of horizontal
+   metrics present, and MAXP->num_glyphs -
+   HHEA->num_of_long_hor_metrics determines the number of left-side
+   bearings present.  */
+
+TEST_STATIC struct sfnt_hmtx_table *
+sfnt_read_hmtx_table (int fd, struct sfnt_offset_subtable *subtable,
+                     struct sfnt_hhea_table *hhea,
+                     struct sfnt_maxp_table *maxp)
+{
+  struct sfnt_table_directory *directory;
+  struct sfnt_hmtx_table *hmtx;
+  size_t size;
+  ssize_t rc;
+  int i;
+
+  /* Find the table in the directory.  */
+
+  directory = sfnt_find_table (subtable, SFNT_TABLE_HMTX);
+
+  if (!directory)
+    return NULL;
+
+  /* Figure out how many bytes are required.  */
+  size = ((hhea->num_of_long_hor_metrics
+          * sizeof (struct sfnt_long_hor_metric))
+         + (MAX (0, ((int) maxp->num_glyphs
+                     - hhea->num_of_long_hor_metrics))
+            * sizeof (int16_t)));
+
+  /* Check the length matches exactly.  */
+  if (directory->length != size)
+    return NULL;
+
+  /* Seek to the location given in the directory.  */
+  if (lseek (fd, directory->offset, SEEK_SET) == (off_t) -1)
+    return NULL;
+
+  /* Now allocate enough to hold all of that along with the table
+     directory structure.  */
+
+  hmtx = xmalloc (sizeof *hmtx + size);
+
+  /* Read into hmtx + 1.  */
+  rc = read (fd, hmtx + 1, size);
+  if (rc == -1 || rc < size)
+    {
+      xfree (hmtx);
+      return NULL;
+    }
+
+  /* Set pointers to data.  */
+  hmtx->h_metrics = (struct sfnt_long_hor_metric *) (hmtx + 1);
+  hmtx->left_side_bearing
+    = (int16_t *) (hmtx->h_metrics
+                  + hhea->num_of_long_hor_metrics);
+
+  /* Swap what was read.  */
+
+  for (i = 0; i < hhea->num_of_long_hor_metrics; ++i)
+    {
+      sfnt_swap16 (&hmtx->h_metrics[i].advance_width);
+      sfnt_swap16 (&hmtx->h_metrics[i].left_side_bearing);
+    }
+
+  for (; i < maxp->num_glyphs; ++i)
+    sfnt_swap16 (&hmtx->left_side_bearing[i - hhea->num_of_long_hor_metrics]);
+
+  /* All done.  */
+  return hmtx;
+}
+
+/* Obtain unscaled glyph metrics for the glyph indexed by GLYPH.
+   Return 0 and the metrics in *METRICS if metrics could be found,
+   else 1.
+
+   HMTX, HHEA and MAXP should be the hmtx, hhea, head, and maxp tables
+   of the font respectively.  */
+
+TEST_STATIC int
+sfnt_lookup_glyph_metrics (sfnt_glyph glyph,
+                          struct sfnt_glyph_metrics *metrics,
+                          struct sfnt_hmtx_table *hmtx,
+                          struct sfnt_hhea_table *hhea,
+                          struct sfnt_maxp_table *maxp)
+{
+  short lbearing;
+  unsigned short advance;
+
+  if (glyph < hhea->num_of_long_hor_metrics)
+    {
+      /* There is a long entry in the hmtx table.  */
+      lbearing = hmtx->h_metrics[glyph].left_side_bearing;
+      advance = hmtx->h_metrics[glyph].advance_width;
+    }
+  else if (hhea->num_of_long_hor_metrics
+          && glyph < maxp->num_glyphs)
+    {
+      /* There is a short entry in the hmtx table.  */
+      lbearing
+       = hmtx->left_side_bearing[glyph
+                                 - hhea->num_of_long_hor_metrics];
+      advance
+       = hmtx->h_metrics[hhea->num_of_long_hor_metrics - 1].advance_width;
+    }
+  else
+    /* No entry corresponds to the glyph.  */
+    return 1;
+
+  /* Return unscaled metrics.  */
+  metrics->lbearing = lbearing;
+  metrics->advance = advance;
+  return 0;
+}
+
+/* Scale the specified glyph metrics by FACTOR.  Set METRICS->lbearing
+   and METRICS->advance to their current values times factor; take the
+   floor of the left bearing and round the advance width.  */
+
+MAYBE_UNUSED TEST_STATIC void
+sfnt_scale_metrics (struct sfnt_glyph_metrics *metrics,
+                   sfnt_fixed factor)
+{
+  sfnt_fixed lbearing, advance;
+
+  lbearing = sfnt_mul_fixed (metrics->lbearing * 65536, factor);
+  advance = sfnt_mul_fixed (metrics->advance * 65536, factor);
+
+  metrics->lbearing = sfnt_floor_fixed (lbearing);
+  metrics->advance = sfnt_round_fixed (advance);
+}
+
+/* Calculate the factor used to convert em space to device space for a
+   font with the specified HEAD table and PPEM value.  */
+
+MAYBE_UNUSED TEST_STATIC sfnt_fixed
+sfnt_get_scale (struct sfnt_head_table *head, int ppem)
+{
+  /* Figure out how to convert from font unit-space to pixel space.
+     To turn one unit to its corresponding pixel size given a ppem of
+     1, the unit must be divided by head->units_per_em.  Then, it must
+     be multiplied by the ppem.  So,
+
+       PIXEL = UNIT / UPEM * PPEM
+
+     which means:
+
+       PIXEL = UNIT * PPEM / UPEM  */
+
+  return sfnt_div_fixed (ppem, head->units_per_em);
+}
+
+
+
+/* Font style parsing.  */
+
+/* Read the name table from the given font FD, using the table
+   directory specified as SUBTABLE.  Perform validation on the offsets
+   in the name records.  Return NULL upon failure, else the name
+   table.  */
+
+TEST_STATIC struct sfnt_name_table *
+sfnt_read_name_table (int fd, struct sfnt_offset_subtable *subtable)
+{
+  struct sfnt_table_directory *directory;
+  struct sfnt_name_table *name;
+  size_t required;
+  ssize_t rc;
+  int i;
+
+  /* Find the table in the directory.  */
+
+  directory = sfnt_find_table (subtable, SFNT_TABLE_NAME);
+
+  if (!directory)
+    return NULL;
+
+  /* Seek to the location given in the directory.  */
+  if (lseek (fd, directory->offset, SEEK_SET) == (off_t) -1)
+    return NULL;
+
+  /* Figure out the minimum that has to be read.  */
+  required = SFNT_ENDOF (struct sfnt_name_table,
+                        string_offset, uint16_t);
+
+  if (directory->length < required)
+    return NULL;
+
+  /* Allocate enough to hold the name table and variable length
      data.  */
   name = xmalloc (sizeof *name + directory->length);
 
@@ -4896,7 +5922,7 @@ sfnt_read_name_table (int fd, struct sfnt_offset_subtable 
*subtable)
       return NULL;
     }
 
-  /* Read REQURIED bytes into the string data.  */
+  /* Read REQUIRED bytes into the string data.  */
   name->data = (unsigned char *) (name->name_records
                                  + name->count);
   rc = read (fd, name->data, required);
@@ -5007,11 +6033,10 @@ sfnt_read_meta_table (int fd, struct 
sfnt_offset_subtable *subtable)
      so an unswapped copy of the whole meta contents must be
      retained.  */
 
-  if (INT_MULTIPLY_WRAPV (sizeof *meta->data_maps, meta->num_data_maps,
-                         &map_size)
+  if (ckd_mul (&map_size, sizeof *meta->data_maps, meta->num_data_maps)
       /* Do so while checking for overflow from bad sfnt files.  */
-      || INT_ADD_WRAPV (map_size, sizeof *meta, &data_size)
-      || INT_ADD_WRAPV (data_size, directory->length, &data_size))
+      || ckd_add (&data_size, map_size, sizeof *meta)
+      || ckd_add (&data_size, data_size, directory->length))
     {
       xfree (meta);
       return NULL;
@@ -5061,9 +6086,8 @@ sfnt_read_meta_table (int fd, struct sfnt_offset_subtable 
*subtable)
       /* Verify the data offsets.  Overflow checking is particularly
         important here.  */
 
-      if (INT_ADD_WRAPV (meta->data_maps[i].data_offset,
-                        meta->data_maps[i].data_length,
-                        &offset))
+      if (ckd_add (&offset, meta->data_maps[i].data_offset,
+                  meta->data_maps[i].data_length))
        {
          xfree (meta);
          return NULL;
@@ -5149,9 +6173,7 @@ sfnt_read_ttc_header (int fd)
   /* Now, read the variable length data.  Make sure to check for
      overflow.  */
 
-  if (INT_MULTIPLY_WRAPV (ttc->num_fonts,
-                         sizeof *ttc->offset_table,
-                         &size))
+  if (ckd_mul (&size, ttc->num_fonts, sizeof *ttc->offset_table))
     {
       xfree (ttc);
       return NULL;
@@ -5182,7 +6204,7 @@ sfnt_read_ttc_header (int fd)
   size = (SFNT_ENDOF (struct sfnt_ttc_header, ul_dsig_offset,
                      uint32_t)
          - offsetof (struct sfnt_ttc_header, ul_dsig_tag));
-  rc = read (fd, &ttc->ul_dsig_offset, size);
+  rc = read (fd, &ttc->ul_dsig_tag, size);
   if (rc == -1 || rc < size)
     {
       xfree (ttc);
@@ -5270,7 +6292,7 @@ sfnt_read_cvt_table (int fd, struct sfnt_offset_subtable 
*subtable)
     return NULL;
 
   /* Figure out the minimum amount that has to be read.  */
-  if (INT_ADD_WRAPV (sizeof *cvt, directory->length, &required))
+  if (ckd_add (&required, directory->length, sizeof *cvt))
     return NULL;
 
   /* Allocate enough for that much data.  */
@@ -5321,7 +6343,7 @@ sfnt_read_fpgm_table (int fd, struct sfnt_offset_subtable 
*subtable)
     return NULL;
 
   /* Figure out the minimum amount that has to be read.  */
-  if (INT_ADD_WRAPV (sizeof *fpgm, directory->length, &required))
+  if (ckd_add (&required, directory->length, sizeof *fpgm))
     return NULL;
 
   /* Allocate enough for that much data.  */
@@ -5369,7 +6391,7 @@ sfnt_read_prep_table (int fd, struct sfnt_offset_subtable 
*subtable)
     return NULL;
 
   /* Figure out the minimum amount that has to be read.  */
-  if (INT_ADD_WRAPV (sizeof *prep, directory->length, &required))
+  if (ckd_add (&required, directory->length, sizeof *prep))
     return NULL;
 
   /* Allocate enough for that much data.  */
@@ -5457,19 +6479,21 @@ sfnt_mul_f26dot6 (sfnt_f26dot6 a, sfnt_f26dot6 b)
 #endif
 }
 
-/* Multiply the specified 2.14 number with another signed 32 bit
-   number.  Return the result as a signed 32 bit number.  */
+/* Multiply the specified two 26.6 fixed point numbers A and B, with
+   rounding.  Return the result, or an undefined value upon
+   overflow.  */
 
-static int32_t
-sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b)
+static sfnt_f26dot6
+sfnt_mul_f26dot6_round (sfnt_f26dot6 a, sfnt_f26dot6 b)
 {
 #ifdef INT64_MAX
   int64_t product;
 
   product = (int64_t) a * (int64_t) b;
 
-  return product / (int64_t) 16384;
-#else
+  /* This can be done quickly with int64_t.  */
+  return (product + 32) / (int64_t) 64;
+#else /* !INT64_MAX */
   int sign;
 
   sign = 1;
@@ -5480,60 +6504,48 @@ sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b)
   if (b < 0)
     sign = -sign;
 
-  return sfnt_multiply_divide (abs (a), abs (b),
-                              16384) * sign;
-#endif
+  return sfnt_multiply_divide_round (abs (a), abs (b),
+                                    32, 64) * sign;
+#endif /* INT64_MAX */
 }
 
-/* Multiply the specified 26.6 fixed point number X by the specified
-   16.16 fixed point number Y with symmetric rounding.
-
-   The 26.6 fixed point number must fit inside -32768 to 32767.ffff.
-   Value is otherwise undefined.  */
+/* Multiply the specified 2.14 number with another signed 32 bit
+   number.  Return the result as a signed 32 bit number.  */
 
-static sfnt_f26dot6
-sfnt_mul_f26dot6_fixed (sfnt_f26dot6 x, sfnt_fixed y)
+static int32_t
+sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b)
 {
 #ifdef INT64_MAX
-  uint64_t product;
-  int sign;
-
-  sign = 1;
-
-  if (x < 0)
-    {
-      x = -x;
-      sign = -sign;
-    }
-
-  if (y < 0)
-    {
-      y = -y;
-      sign = -sign;
-    }
+  int64_t product;
 
-  product = (uint64_t) y * (uint64_t) x;
+  product = (int64_t) a * (int64_t) b;
 
-  /* This can be done quickly with int64_t.  */
-  return ((int64_t) (product + 32676) / (int64_t) 65536) * sign;
+  return product / (int64_t) 16384;
 #else
-  struct sfnt_large_integer temp;
   int sign;
 
   sign = 1;
 
-  if (x < 0)
+  if (a < 0)
     sign = -sign;
 
-  if (y < 0)
+  if (b < 0)
     sign = -sign;
 
-  sfnt_multiply_divide_1 (abs (x), abs (y), &temp);
-  sfnt_large_integer_add (&temp, 32676);
-  return sfnt_multiply_divide_2 (&temp, 65536) * sign;
+  return sfnt_multiply_divide (abs (a), abs (b),
+                              16384) * sign;
 #endif
 }
 
+/* Multiply the specified 26.6 fixed point number X by the specified
+   16.16 fixed point number Y with rounding.  */
+
+static sfnt_f26dot6
+sfnt_mul_f26dot6_fixed (sfnt_f26dot6 x, sfnt_fixed y)
+{
+  return sfnt_mul_fixed_round (x, y);
+}
+
 /* Return the floor of the specified 26.6 fixed point value X.  */
 
 static sfnt_f26dot6
@@ -5631,59 +6643,51 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp,
   size = sizeof (*interpreter);
 
   /* Add program stack.  */
-  if (INT_ADD_WRAPV ((maxp->max_stack_elements
-                     * sizeof *interpreter->stack),
-                    size, &size))
+  if (ckd_add (&size, size, (maxp->max_stack_elements
+                            * sizeof *interpreter->stack)))
     return NULL;
 
   /* Add twilight zone.  */
 
-  if (INT_ADD_WRAPV ((maxp->max_twilight_points
-                     * sizeof *interpreter->twilight_x),
-                    size, &size))
+  if (ckd_add (&size, size, (maxp->max_twilight_points
+                            * sizeof *interpreter->twilight_x)))
     return NULL;
 
-  if (INT_ADD_WRAPV ((maxp->max_twilight_points
-                     * sizeof *interpreter->twilight_y),
-                    size, &size))
+  if (ckd_add (&size, size, (maxp->max_twilight_points
+                            * sizeof *interpreter->twilight_y)))
     return NULL;
 
-  if (INT_ADD_WRAPV ((maxp->max_twilight_points
-                     * sizeof *interpreter->twilight_y),
-                    size, &size))
+  if (ckd_add (&size, size, (maxp->max_twilight_points
+                            * sizeof *interpreter->twilight_y)))
     return NULL;
 
-  if (INT_ADD_WRAPV ((maxp->max_twilight_points
-                     * sizeof *interpreter->twilight_y),
-                    size, &size))
+  if (ckd_add (&size, size, (maxp->max_twilight_points
+                            * sizeof *interpreter->twilight_y)))
     return NULL;
 
   /* Add the storage area.  */
   storage_size = maxp->max_storage * sizeof *interpreter->storage;
-  if (INT_ADD_WRAPV (storage_size, size, &size))
+  if (ckd_add (&size, size, storage_size))
     return NULL;
 
   /* Add padding for the storage area.  */
   pad = alignof (struct sfnt_interpreter_definition);
   pad -= size & (pad - 1);
-  if (INT_ADD_WRAPV (pad, size, &size))
+  if (ckd_add (&size, size, pad))
     return NULL;
 
   /* Add function and instruction definitions.  */
-  if (INT_ADD_WRAPV ((((int) maxp->max_instruction_defs
-                      + maxp->max_function_defs)
-                     * sizeof *interpreter->function_defs),
-                    size, &size))
+  if (ckd_add (&size, size, (((int) maxp->max_instruction_defs
+                             + maxp->max_function_defs)
+                            * sizeof *interpreter->function_defs)))
     return NULL;
 
   /* Add control value table.  */
 
   if (cvt)
     {
-      if (INT_MULTIPLY_WRAPV (cvt->num_elements,
-                             sizeof *interpreter->cvt,
-                             &temp)
-         || INT_ADD_WRAPV (temp, size, &size))
+      if (ckd_mul (&temp, cvt->num_elements, sizeof *interpreter->cvt)
+         || ckd_add (&size, size, temp))
        return NULL;
     }
 
@@ -5744,7 +6748,7 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp,
   /* Now compute the scale.  Then, scale up the control value table
      values.  */
   interpreter->scale
-    = sfnt_div_fixed (pixel_size, head->units_per_em);
+    = sfnt_div_fixed (pixel_size * 64, head->units_per_em);
 
   /* Set the PPEM.  */
   interpreter->ppem = pixel_size;
@@ -5760,7 +6764,7 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp,
   /* Load the control value table.  */
   for (i = 0; i < interpreter->cvt_size; ++i)
     interpreter->cvt[i]
-      = sfnt_mul_f26dot6_fixed (cvt->values[i] * 64,
+      = sfnt_mul_f26dot6_fixed (cvt->values[i],
                                interpreter->scale);
 
   /* Fill in the default values for phase, period and threshold.  */
@@ -5826,7 +6830,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
   (interpreter->SP - interpreter->stack)
 
 #define TRAP(why)                              \
-  sfnt_interpret_trap (interpreter, (why))
+  sfnt_interpret_trap (interpreter, why)
 
 #define MOVE(a, b, n)                          \
   memmove (a, b, (n) * sizeof (uint32_t))
@@ -5854,15 +6858,6 @@ sfnt_interpret_trap (struct sfnt_interpreter 
*interpreter,
     TRAP ("instruction executed not valid"     \
          " outside control value program")     \
 
-#define sfnt_add(a, b)                         \
-  ((int) ((unsigned int) (a) + (unsigned int) (b)))
-
-#define sfnt_sub(a, b)                         \
-  ((int) ((unsigned int) (a) - (unsigned int) (b)))
-
-#define sfnt_mul(a, b)                         \
-  ((int) ((unsigned int) (a) * (unsigned int) (b)))
-
 
 
 /* Register, alu and logic instructions.  */
@@ -5897,7 +6892,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
    ? (TRAP ("stack underflow"), 0)             \
    : *(interpreter->SP - 1))
 
-#if !defined TEST || !0
+#if !defined TEST
 
 #define PUSH(value)                            \
   {                                            \
@@ -5915,7 +6910,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
     interpreter->SP++;                         \
   }
 
-#else /* TEST && 0 */
+#else /* TEST */
 
 #define PUSH(value)                            \
   {                                            \
@@ -5939,7 +6934,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
   {                                            \
     int16_t word;                              \
                                                \
-    word = (((int8_t) high) << 8 | low);       \
+    word = (((uint8_t) high) << 8 | low);      \
     PUSH_UNCHECKED (word);                     \
   }                                            \
 
@@ -6019,14 +7014,18 @@ sfnt_interpret_trap (struct sfnt_interpreter 
*interpreter,
 
 #define SLOOP()                                        \
   {                                            \
-    uint32_t loop;                             \
+    int32_t loop;                              \
                                                \
     loop = POP ();                             \
                                                \
-    if (!loop)                                 \
-      TRAP ("loop set to 0");                  \
+    if (loop < 0)                              \
+      TRAP ("loop set to invalid value");      \
                                                \
-    interpreter->state.loop = loop;            \
+    /* N.B. loop might be greater than 65535,  \
+       but no reasonable font should define    \
+       such values.  */                                \
+    interpreter->state.loop                    \
+      = MIN (65535, loop);                     \
   }
 
 #define SMD()                                  \
@@ -6084,8 +7083,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
     single_width = POP ();                     \
                                                \
     interpreter->state.single_width_value      \
-      = (interpreter->scale * single_width     \
-        / 1024);                               \
+      = sfnt_mul_fixed (single_width,          \
+                       interpreter->scale);    \
   }
 
 #define DUP()                                  \
@@ -6553,12 +7552,13 @@ sfnt_interpret_trap (struct sfnt_interpreter 
*interpreter,
 
 #define MUL()                                  \
   {                                            \
-    sfnt_f26dot6 n2, n1;                       \
+    sfnt_f26dot6 n2, n1, r;                    \
                                                \
     n2 = POP ();                               \
     n1 = POP ();                               \
                                                \
-    PUSH_UNCHECKED (sfnt_mul_f26dot6 (n2, n1));        \
+    r = sfnt_mul_f26dot6_round (n2, n1);       \
+    PUSH_UNCHECKED (r);                                \
   }
 
 #define ABS()                                  \
@@ -6613,8 +7613,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
       TRAP ("WCVTF out of bounds");            \
                                                \
     interpreter->cvt[location]                 \
-      = (interpreter->scale * value            \
-        / 1024);                               \
+      = sfnt_mul_fixed (value,                 \
+                       interpreter->scale);    \
   }
 
 #define JROT()                                 \
@@ -6670,9 +7670,12 @@ sfnt_interpret_trap (struct sfnt_interpreter 
*interpreter,
     interpreter->state.scan_control = value;   \
   }
 
-/* Selector bit 8 is undocumented, but present in the Macintosh
+/* Selector bit 3 is undocumented, but present in the Macintosh
    rasterizer.  02000 is returned if there is a variation axis in
-   use.  */
+   use.
+
+   Selector bit 5 is undocumented, but relied on by several fonts.
+   010000 is returned if a grayscale rasterizer is in use.  */
 
 #define GETINFO()                              \
   {                                            \
@@ -6689,6 +7692,9 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
        && interpreter->norm_coords)            \
       k |= 02000;                              \
                                                \
+    if (selector & 32)                         \
+      k |= 010000;                             \
+                                               \
     PUSH_UNCHECKED (k);                                \
   }
 
@@ -7148,8 +8154,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
     vector                                     \
       = interpreter->state.projection_vector;  \
                                                \
-    PUSH ((uint16_t) vector.x);                        \
-    PUSH ((uint16_t) vector.y);                        \
+    PUSH ((int32_t) vector.x);                 \
+    PUSH ((int32_t) vector.y);                 \
   }
 
 #define GFV()                                  \
@@ -7159,8 +8165,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
     vector                                     \
       = interpreter->state.freedom_vector;     \
                                                \
-    PUSH ((uint16_t) vector.x);                        \
-    PUSH ((uint16_t) vector.y);                        \
+    PUSH ((int32_t) vector.x);                 \
+    PUSH ((int32_t) vector.y);                 \
   }
 
 #define SFVTPV()                               \
@@ -7444,6 +8450,8 @@ static void
 sfnt_interpret_utp (struct sfnt_interpreter *interpreter,
                    uint32_t p)
 {
+  unsigned char mask;
+
   if (!interpreter->state.zp0)
     {
       if (p >= interpreter->twilight_zone_size)
@@ -7457,7 +8465,31 @@ sfnt_interpret_utp (struct sfnt_interpreter *interpreter,
       || p >= interpreter->glyph_zone->num_points)
     TRAP ("UTP[] p lies outside glyph zone");
 
-  interpreter->glyph_zone->flags[p] &= ~SFNT_POINT_TOUCHED_X;
+  /* The flags unset by UTP are subject to which axes in the freedom
+     vector are significant, as stated in the TrueType reference
+     manual by this needless mouthful:
+
+       A point may be touched in the x-direction, the y-direction, or
+       in both the x and y-directions.  The position of the freedom
+       vector determines whether the point is untouched in the
+       x-direction, the y-direction, or both.  If the vector is set to
+       the x-axis, the point will be untouched in the x-direction.  If
+       the vector is set to the y-axis, the point will be untouched in
+       the y-direction.  Otherwise the point will be untouched in both
+       directions.
+
+       A points that is marked as untouched will be moved by an IUP[]
+       instruction even if the point was previously touched.  */
+
+  mask = 0xff;
+
+  if (interpreter->state.freedom_vector.x)
+    mask &= ~SFNT_POINT_TOUCHED_X;
+
+  if (interpreter->state.freedom_vector.y)
+    mask &= ~SFNT_POINT_TOUCHED_Y;
+
+  interpreter->glyph_zone->flags[p] &= mask;
 }
 
 /* Save the specified unit VECTOR into INTERPRETER's graphics state as
@@ -7512,8 +8544,12 @@ sfnt_address_zp2 (struct sfnt_interpreter *interpreter,
       if (number >= interpreter->twilight_zone_size)
        TRAP ("address to ZP2 (twilight zone) out of bounds");
 
+      if (!x || !y)
+       goto next;
+
       *x = interpreter->twilight_x[number];
       *y = interpreter->twilight_y[number];
+    next:
 
       if (!x_org || !y_org)
        return;
@@ -7533,8 +8569,11 @@ sfnt_address_zp2 (struct sfnt_interpreter *interpreter,
   if (number >= interpreter->glyph_zone->num_points)
     TRAP ("address to ZP2 (glyph zone) out of bounds");
 
-  *x = interpreter->glyph_zone->x_current[number];
-  *y = interpreter->glyph_zone->y_current[number];
+  if (x && y)
+    {
+      *x = interpreter->glyph_zone->x_current[number];
+      *y = interpreter->glyph_zone->y_current[number];
+    }
 
   if (x_org && y_org)
     {
@@ -7560,8 +8599,12 @@ sfnt_address_zp1 (struct sfnt_interpreter *interpreter,
       if (number >= interpreter->twilight_zone_size)
        TRAP ("address to ZP1 (twilight zone) out of bounds");
 
+      if (!x || !y)
+       goto next;
+
       *x = interpreter->twilight_x[number];
       *y = interpreter->twilight_y[number];
+    next:
 
       if (!x_org || !y_org)
        return;
@@ -7581,8 +8624,11 @@ sfnt_address_zp1 (struct sfnt_interpreter *interpreter,
   if (number >= interpreter->glyph_zone->num_points)
     TRAP ("address to ZP1 (glyph zone) out of bounds");
 
-  *x = interpreter->glyph_zone->x_current[number];
-  *y = interpreter->glyph_zone->y_current[number];
+  if (x && y)
+    {
+      *x = interpreter->glyph_zone->x_current[number];
+      *y = interpreter->glyph_zone->y_current[number];
+    }
 
   if (x_org && y_org)
     {
@@ -7608,8 +8654,12 @@ sfnt_address_zp0 (struct sfnt_interpreter *interpreter,
       if (number >= interpreter->twilight_zone_size)
        TRAP ("address to ZP0 (twilight zone) out of bounds");
 
+      if (!x || !y)
+       goto next;
+
       *x = interpreter->twilight_x[number];
       *y = interpreter->twilight_y[number];
+    next:
 
       if (!x_org || !y_org)
        return;
@@ -7629,8 +8679,11 @@ sfnt_address_zp0 (struct sfnt_interpreter *interpreter,
   if (number >= interpreter->glyph_zone->num_points)
     TRAP ("address to ZP0 (glyph zone) out of bounds");
 
-  *x = interpreter->glyph_zone->x_current[number];
-  *y = interpreter->glyph_zone->y_current[number];
+  if (x && y)
+    {
+      *x = interpreter->glyph_zone->x_current[number];
+      *y = interpreter->glyph_zone->y_current[number];
+    }
 
   if (x_org && y_org)
     {
@@ -7917,7 +8970,7 @@ sfnt_dual_project_vector (struct sfnt_interpreter 
*interpreter,
 
 static void
 sfnt_interpret_fliprgoff (struct sfnt_interpreter *interpreter,
-                         uint32_t l, uint32_t h)
+                         uint32_t h, uint32_t l)
 {
   uint32_t i;
 
@@ -7927,7 +8980,7 @@ sfnt_interpret_fliprgoff (struct sfnt_interpreter 
*interpreter,
   if (!interpreter->state.zp0)
     return;
 
-  for (i = l; i < h; ++i)
+  for (i = l; i <= h; ++i)
     interpreter->glyph_zone->flags[i] &= ~01;
 }
 
@@ -7936,7 +8989,7 @@ sfnt_interpret_fliprgoff (struct sfnt_interpreter 
*interpreter,
 
 static void
 sfnt_interpret_fliprgon (struct sfnt_interpreter *interpreter,
-                        uint32_t l, uint32_t h)
+                        uint32_t h, uint32_t l)
 {
   uint32_t i;
 
@@ -7946,8 +8999,8 @@ sfnt_interpret_fliprgon (struct sfnt_interpreter 
*interpreter,
   if (!interpreter->state.zp0)
     return;
 
-  for (i = l; i < h; ++i)
-    interpreter->glyph_zone->flags[i] |= ~01;
+  for (i = l; i <= h; ++i)
+    interpreter->glyph_zone->flags[i] |= 01;
 }
 
 /* Interpret a FLIPPT instruction in INTERPRETER.  For loop times, pop
@@ -8591,6 +9644,8 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
   sfnt_f26dot6 new_distance;
   uint32_t p;
   sfnt_f26dot6 x, y, original_x, original_y;
+  struct sfnt_interpreter_zone *zone;
+  bool scale;
 
   /* First load both reference points.  */
   sfnt_address_zp0 (interpreter, interpreter->state.rp1,
@@ -8600,6 +9655,57 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
                    &rp2x, &rp2y, &rp2_original_x,
                    &rp2_original_y);
 
+  /* If RP1, RP2, and all arguments all fall within the glyph zone and
+     a simple glyph is loaded, replace their original coordinates as
+     loaded here with coordinates from the unscaled glyph outline.  */
+
+  zone = interpreter->glyph_zone;
+  scale = false;
+
+  if (zone && zone->simple
+      && interpreter->state.zp0
+      && interpreter->state.zp1
+      && interpreter->state.zp2)
+    {
+      p = interpreter->state.rp1;
+
+      /* If P is a phantom point... */
+      if (p >= zone->simple->number_of_points)
+       {
+         /* ...scale the phantom point to the size of the original
+            outline.  */
+         rp1_original_x = sfnt_div_fixed (rp1_original_x,
+                                          interpreter->scale);
+         rp1_original_y = sfnt_div_fixed (rp1_original_y,
+                                          interpreter->scale);
+       }
+      else
+       {
+         rp1_original_x = zone->simple->x_coordinates[p];
+         rp1_original_y = zone->simple->y_coordinates[p];
+       }
+
+      p = interpreter->state.rp2;
+
+      /* If P is a phantom point... */
+      if (p >= zone->simple->number_of_points)
+       {
+         /* ...scale the phantom point to the size of the original
+            outline.  */
+         rp2_original_x = sfnt_div_fixed (rp2_original_x,
+                                          interpreter->scale);
+         rp2_original_y = sfnt_div_fixed (rp2_original_y,
+                                          interpreter->scale);
+       }
+      else
+       {
+         rp2_original_x = zone->simple->x_coordinates[p];
+         rp2_original_y = zone->simple->y_coordinates[p];
+       }
+
+      scale = true;
+    }
+
   /* Get the original distance between of RP1 and RP2 measured
      relative to the dual projection vector.  */
   range = sfnt_dual_project_vector (interpreter,
@@ -8608,6 +9714,9 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
                                    sfnt_sub (rp2_original_y,
                                              rp1_original_y));
 
+  if (scale)
+    range = sfnt_mul_fixed_round (range, interpreter->scale);
+
   /* Get the new distance.  */
   new_range = sfnt_dual_project_vector (interpreter,
                                        sfnt_sub (rp2x, rp1x),
@@ -8621,6 +9730,25 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
       sfnt_address_zp2 (interpreter, p, &x, &y, &original_x,
                        &original_y);
 
+      if (scale)
+       {
+         /* If P is a phantom point... */
+         if (p >= zone->simple->number_of_points)
+           {
+             /* ...scale the phantom point to the size of the original
+                outline.  */
+             original_x = sfnt_div_fixed (original_x,
+                                          interpreter->scale);
+             original_y = sfnt_div_fixed (original_y,
+                                          interpreter->scale);
+           }
+         else
+           {
+             original_x = zone->simple->x_coordinates[p];
+             original_y = zone->simple->y_coordinates[p];
+           }
+       }
+
       /* Now compute the old distance from this point to rp1.  */
       org_distance
        = sfnt_dual_project_vector (interpreter,
@@ -8629,6 +9757,10 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
                                    sfnt_sub (original_y,
                                              rp1_original_y));
 
+      if (scale)
+       org_distance = sfnt_mul_fixed_round (org_distance,
+                                            interpreter->scale);
+
       /* And the current distance from this point to rp1, so
          how much to move can be determined.  */
       cur_distance
@@ -8798,7 +9930,7 @@ sfnt_deltac (int number, struct sfnt_interpreter 
*interpreter,
 
    Touch the point P (within the zone specified in zp0) in the
    directions specified in the freedom vector.  Then, if OPCODE is
-   0x7f, round the point and move it the rounded distance along the
+   0x2f, round the point and move it the rounded distance along the
    freedom vector.
 
    Finally, set the RP0 and RP1 registers to P.  */
@@ -8814,7 +9946,7 @@ sfnt_interpret_mdap (struct sfnt_interpreter *interpreter,
   /* Measure the current distance.  */
   here = sfnt_project_vector (interpreter, px, py);
 
-  if (opcode == 0x7f)
+  if (opcode == 0x2f)
     {
       /* Measure distance, round, then move to the distance.  */
       distance = sfnt_project_vector (interpreter, px, py);
@@ -8841,12 +9973,10 @@ sfnt_interpret_mdap (struct sfnt_interpreter 
*interpreter,
 
 static void
 sfnt_deltap (int number, struct sfnt_interpreter *interpreter,
-            unsigned char operand, unsigned int index)
+            unsigned char operand, unsigned int p)
 {
   int ppem, delta;
 
-  return;
-
   /* Extract the ppem from OPERAND.  The format is the same as in
      sfnt_deltac.  */
 
@@ -8950,8 +10080,8 @@ sfnt_deltap (int number, struct sfnt_interpreter 
*interpreter,
   delta *= 1l << (6 - interpreter->state.delta_shift);
 
   /* Move the point.  */
-  sfnt_check_zp0 (interpreter, index);
-  sfnt_move_zp0 (interpreter, index, 1, delta);
+  sfnt_check_zp0 (interpreter, p);
+  sfnt_move_zp0 (interpreter, p, 1, delta);
 }
 
 /* Needed by sfnt_interpret_call.  */
@@ -9535,6 +10665,7 @@ sfnt_dot_fix_14 (int32_t ax, int32_t ay, int bx, int by)
   return (int32_t) (((uint32_t) hi << 18) | (l >> 14));
 #else
   int64_t xx, yy;
+  int64_t temp;
 
   xx = (int64_t) ax * bx;
   yy = (int64_t) ay * by;
@@ -9543,7 +10674,12 @@ sfnt_dot_fix_14 (int32_t ax, int32_t ay, int bx, int by)
   yy = xx >> 63;
   xx += 0x2000 + yy;
 
-  return (int32_t) (xx / (2 << 14));
+  /* TrueType fonts rely on "division" here truncating towards
+     negative infinity, so compute the arithmetic right shift in place
+     of division.  */
+  temp = -(xx < 0);
+  temp = (temp ^ xx) >> 14 ^ temp;
+  return (int32_t) (temp);
 #endif
 }
 
@@ -9633,6 +10769,7 @@ sfnt_move (sfnt_f26dot6 *restrict x, sfnt_f26dot6 
*restrict y,
   sfnt_f26dot6 versor, k;
   sfnt_f2dot14 dot_product;
   size_t num;
+  unsigned char *flags_start;
 
   dot_product = interpreter->state.vector_dot_product;
 
@@ -9645,6 +10782,10 @@ sfnt_move (sfnt_f26dot6 *restrict x, sfnt_f26dot6 
*restrict y,
      other out, so the result is 26.6.  */
   versor = interpreter->state.freedom_vector.x;
 
+  /* Save flags that it may be restored for the second Y axis
+     loop.  */
+  flags_start = flags;
+
   if (versor)
     {
       /* Move along X axis, converting the distance to the freedom
@@ -9664,11 +10805,12 @@ sfnt_move (sfnt_f26dot6 *restrict x, sfnt_f26dot6 
*restrict y,
        }
     }
 
+  flags = flags_start;
   versor = interpreter->state.freedom_vector.y;
 
   if (versor)
     {
-      /* Move along X axis, converting the distance to the freedom
+      /* Move along Y axis, converting the distance to the freedom
         vector.  */
       num = n;
       k = sfnt_multiply_divide_signed (distance,
@@ -9686,6 +10828,15 @@ sfnt_move (sfnt_f26dot6 *restrict x, sfnt_f26dot6 
*restrict y,
     }
 }
 
+/* Compute the dot product of the two versors A and B with
+   rounding.  */
+
+static sfnt_f2dot14
+sfnt_short_frac_dot (sfnt_f2dot14 a, sfnt_f2dot14 b)
+{
+  return (sfnt_f2dot14) ((((long) a * b) + 8192) / 16384);
+}
+
 /* Validate the graphics state GS.
    Establish function pointers for rounding and projection.
    Establish dot product used to convert vector distances between
@@ -9762,11 +10913,18 @@ sfnt_validate_gs (struct sfnt_graphics_state *gs)
     gs->vector_dot_product = gs->projection_vector.y;
   else
     /* Actually calculate the dot product.  */
-    gs->vector_dot_product = ((((long) gs->projection_vector.x
-                               * gs->freedom_vector.x)
-                              + ((long) gs->projection_vector.y
-                                 * gs->freedom_vector.y))
-                             / 16384);
+    gs->vector_dot_product = (sfnt_short_frac_dot (gs->projection_vector.x,
+                                                  gs->freedom_vector.x)
+                             + sfnt_short_frac_dot (gs->projection_vector.y,
+                                                    gs->freedom_vector.y));
+
+  /* If the product is less than 1/16th of a vector, prevent overflow
+     by resetting it to 1.  */
+
+  if (gs->vector_dot_product > -0x400
+      && gs->vector_dot_product < 0x400)
+    gs->vector_dot_product = (gs->vector_dot_product < 0
+                             ? -0x4000 : 0x4000);
 
   /* Now figure out which function to use to move distances.  Handle
      the common case where both the freedom and projection vectors are
@@ -9989,6 +11147,11 @@ sfnt_interpret_shp (struct sfnt_interpreter 
*interpreter,
    ? interpreter->glyph_zone->x_points[p]      \
    : interpreter->glyph_zone->y_points[p])
 
+#define load_unscaled(p)                               \
+  (opcode == 0x31                                      \
+   ? interpreter->glyph_zone->simple->x_coordinates[p] \
+   : interpreter->glyph_zone->simple->y_coordinates[p])
+
 #define IUP_SINGLE_PAIR()                                              \
   /* Now make touch_start the first point before, i.e. the first       \
      touched point in this pair.  */                                   \
@@ -10038,23 +11201,40 @@ sfnt_interpret_shp (struct sfnt_interpreter 
*interpreter,
       if (position >= original_min_pos                                 \
          && position <= original_max_pos)                              \
        {                                                               \
+         /* Compute the ratio between the two touched point positions  \
+            and the original position of the point being touched with  \
+            positions from the unscaled outline, if at all             \
+            possible.  */                                              \
+                                                                       \
+         if (interpreter->glyph_zone->simple)                          \
+           {                                                           \
+             org_max_pos = load_unscaled (point_max);                  \
+             org_min_pos = load_unscaled (point_min);                  \
+             position = load_unscaled (i);                             \
+           }                                                           \
+         else                                                          \
+           {                                                           \
+             org_max_pos = original_max_pos;                           \
+             org_min_pos = original_min_pos;                           \
+           }                                                           \
+                                                                       \
          /* Handle the degenerate case where original_min_pos and      \
             original_max_pos have not changed by placing the point in  \
             the middle.  */                                            \
-         if (original_min_pos == original_max_pos)                     \
+         if (org_min_pos == org_max_pos)                               \
            ratio = 077777;                                             \
          else                                                          \
            /* ... preserve the ratio of i between min_pos and          \
               max_pos...  */                                           \
            ratio = sfnt_div_fixed ((sfnt_sub (position,                \
-                                              original_min_pos)        \
+                                              org_min_pos)             \
                                     * 1024),                           \
-                                   (sfnt_sub (original_max_pos,        \
-                                              original_min_pos)        \
+                                   (sfnt_sub (org_max_pos,             \
+                                              org_min_pos)             \
                                     * 1024));                          \
                                                                        \
          delta = sfnt_sub (max_pos, min_pos);                          \
-         delta = sfnt_mul_fixed (ratio, delta);                        \
+         delta = sfnt_mul_fixed_round (ratio, delta);                  \
          store_point (i, sfnt_add (min_pos, delta));                   \
        }                                                               \
       else                                                             \
@@ -10089,8 +11269,8 @@ sfnt_interpret_iup_1 (struct sfnt_interpreter 
*interpreter,
   size_t first_point;
   size_t point_min, point_max, i;
   sfnt_f26dot6 position, min_pos, max_pos, delta, ratio;
-  sfnt_f26dot6 original_max_pos;
-  sfnt_f26dot6 original_min_pos;
+  sfnt_f26dot6 original_max_pos, org_max_pos;
+  sfnt_f26dot6 original_min_pos, org_min_pos;
 
   /* Find the first touched point.  If none is found, simply
      return.  */
@@ -10176,6 +11356,7 @@ sfnt_interpret_iup_1 (struct sfnt_interpreter 
*interpreter,
 #undef load_point
 #undef store_point
 #undef load_original
+#undef load_unscaled
 
 /* Interpret an IUP (``interpolate untouched points'') instruction.
    INTERPRETER is the interpreter, and OPCODE is the instruction
@@ -10361,6 +11542,64 @@ sfnt_interpret_mirp (struct sfnt_interpreter 
*interpreter,
     interpreter->state.rp0 = p;
 }
 
+/* Return the projection of the two points P1 and P2's original values
+   along the dual projection vector, with P1 inside ZP0 and P2 inside
+   ZP1.  If this zone is the glyph zone and the outline positions of
+   those points are directly accessible, project their original
+   positions and scale the result with rounding, so as to prevent
+   rounding-introduced inaccuracies.
+
+   The scenario where such inaccuracies are significant is generally
+   where an Italic glyph is being instructed at small PPEM sizes,
+   during which a point moved by MDAP[rN] is within 1/64th of a
+   pixel's distance from a point on the grid, yet the measurements
+   taken between such a point and the reference point against which
+   the distance to move is computed is such that the position of the
+   point after applying their rounded values differs by one grid
+   coordinate from the font designer's intentions, either exaggerating
+   or neutralizing the slant of the stem to which it belongs.
+
+   This behavior applies only to MDRP (which see), although a similar
+   strategy is also applied while interpreting IP instructions.  */
+
+static sfnt_f26dot6
+sfnt_project_zp1_zp0_org (struct sfnt_interpreter *interpreter,
+                         uint32_t p1, uint32_t p2)
+{
+  sfnt_fword x1, y1, x2, y2, projection;
+  struct sfnt_simple_glyph *simple;
+  sfnt_f26dot6 org_x1, org_y1, org_x2, org_y2;
+
+  /* Addressing the twilight zone, perhaps only partially.  */
+  if (!interpreter->state.zp0
+      || !interpreter->state.zp1
+      /* Not interpreting a glyph.  */
+      || !interpreter->glyph_zone
+      /* Not interpreting a simple glyph.  */
+      || !interpreter->glyph_zone->simple
+      /* P1 or P2 are phantom points.  */
+      || p1 >= interpreter->glyph_zone->simple->number_of_points
+      || p2 >= interpreter->glyph_zone->simple->number_of_points)
+    goto project_normally;
+
+  simple = interpreter->glyph_zone->simple;
+  x1 = simple->x_coordinates[p1];
+  y1 = simple->y_coordinates[p1];
+  x2 = simple->x_coordinates[p2];
+  y2 = simple->y_coordinates[p2];
+
+  /* Compute the projection.  */
+  projection = DUAL_PROJECT (x1 - x2, y1 - y2);
+
+  /* Return the projection, scaled with rounding.  */
+  return sfnt_mul_fixed_round (projection, interpreter->scale);
+
+ project_normally:
+  sfnt_address_zp1 (interpreter, p1, NULL, NULL, &org_x1, &org_y1);
+  sfnt_address_zp0 (interpreter, p2, NULL, NULL, &org_x2, &org_y2);
+  return DUAL_PROJECT (org_x1 - org_x2, org_y1 - org_y2);
+}
+
 /* Interpret an MDRP instruction with the specified OPCODE in
    INTERPRETER.  Pop a point in ZP1, and move the point until its
    distance from RP0 in ZP0 is the same as in the original outline.
@@ -10375,33 +11614,33 @@ sfnt_interpret_mdrp (struct sfnt_interpreter 
*interpreter,
                     uint32_t opcode)
 {
   uint32_t p;
-  sfnt_f26dot6 distance, delta;
-  sfnt_f26dot6 current_projection, original_projection;
-  sfnt_f26dot6 x, y, org_x, org_y;
-  sfnt_f26dot6 rx, ry, org_rx, org_ry;
+  sfnt_f26dot6 distance, applied;
+  sfnt_f26dot6 current_projection;
+  sfnt_f26dot6 x, y, rx, ry;
 
   /* Point number.  */
   p = POP ();
 
   /* Load the points.  */
-  sfnt_address_zp1 (interpreter, p, &x, &y, &org_x, &org_y);
+  sfnt_address_zp1 (interpreter, p, &x, &y, NULL, NULL);
   sfnt_address_zp0 (interpreter, interpreter->state.rp0,
-                   &rx, &ry, &org_rx, &org_ry);
+                   &rx, &ry, NULL, NULL);
+
+  /* Calculate the distance between P and rp0 prior to hinting.  */
+  distance = sfnt_project_zp1_zp0_org (interpreter, p,
+                                      interpreter->state.rp0);
 
-  distance = DUAL_PROJECT (org_x - org_rx,
-                          org_y - org_ry);
-  original_projection = distance;
+  /* Calculate the distance between P and rp0 as of now in the hinting
+     process.  */
   current_projection = PROJECT (x - rx, y - ry);
 
   /* Test against the single width value.  */
 
-  delta = sfnt_sub (distance,
-                   interpreter->state.single_width_value);
-
-  if (delta < 0)
-    delta = -delta;
-
-  if (delta < interpreter->state.sw_cut_in)
+  if (interpreter->state.sw_cut_in > 0
+      && distance < (interpreter->state.single_width_value
+                    + interpreter->state.sw_cut_in)
+      && distance > (interpreter->state.single_width_value
+                    - interpreter->state.sw_cut_in))
     {
       /* Use the single width instead, as the CVT entry is too
         small.  */
@@ -10412,38 +11651,34 @@ sfnt_interpret_mdrp (struct sfnt_interpreter 
*interpreter,
        distance = -interpreter->state.single_width_value;
     }
 
-  /* Flag B means look at the cvt cut in and round the
-     distance.  */
+  /* Flag B implies that the distance should be rounded.  The CVT cut
+     in is not taken into account by MDRP, contrary to earlier
+     presumptions.  */
 
   if (opcode & 4)
-    {
-      delta = sfnt_sub (distance, original_projection);
-
-      if (delta < 0)
-       delta = -delta;
-
-      if (delta > interpreter->state.cvt_cut_in)
-       distance = original_projection;
-
-      /* Now, round the distance.  */
-      distance = sfnt_round_symmetric (interpreter, distance);
-    }
+    applied = sfnt_round_symmetric (interpreter, distance);
+  else
+    applied = distance;
 
   /* Flag C means look at the minimum distance.  */
 
   if (opcode & 8)
     {
-      if (original_projection >= 0
-         && distance < interpreter->state.minimum_distance)
-       distance = interpreter->state.minimum_distance;
-      else if (original_projection < 0
-              && distance > -interpreter->state.minimum_distance)
-       distance = -interpreter->state.minimum_distance;
+      /* Test the sign of the initial distance, but compare the
+        distance that will be applied in reality against the minimum
+        distance.  */
+
+      if (distance >= 0
+         && applied < interpreter->state.minimum_distance)
+       applied = interpreter->state.minimum_distance;
+      else if (distance < 0
+              && applied > -interpreter->state.minimum_distance)
+       applied = -interpreter->state.minimum_distance;
     }
 
   /* Finally, move the point.  */
   sfnt_move_zp1 (interpreter, p, 1,
-                sfnt_sub (distance, current_projection));
+                sfnt_sub (applied, current_projection));
 
   /* Set RP1 to RP0 and RP2 to the point.  If flag 3 is set, also make
      it RP0.  */
@@ -11111,11 +12346,43 @@ sfnt_interpret_control_value_program (struct 
sfnt_interpreter *interpreter,
   sfnt_interpret_run (interpreter,
                      SFNT_RUN_CONTEXT_CONTROL_VALUE_PROGRAM);
 
-  /* If instruct_control & 4, then changes to the graphics state made
+  /* If instruct_control & 2, then changes to the graphics state made
      in this program should be reverted.  */
 
-  if (interpreter->state.instruct_control & 4)
+  if (interpreter->state.instruct_control & 2)
     sfnt_init_graphics_state (&interpreter->state);
+  else
+    {
+      /* And even if not, reset the following graphics state
+        variables, to which both the Apple and MS scalers don't
+        permit modifications from the preprogram.
+
+         Not only is such reversion undocumented, it is also
+         inefficient, for modern fonts at large only move points on
+         the Y axis.  As such, these fonts must issue a redundant
+         SVTCA[Y] instruction within each glyph program, in place of
+         initializing the projection and freedom vectors once and for
+         all in prep.  Unfortunately many fonts which do instruct on
+         the X axis now rely on this ill-conceived behavior, so Emacs
+         must, reluctantly, follow suit.  */
+
+      interpreter->state.dual_projection_vector.x = 040000; /* 1.0 */
+      interpreter->state.dual_projection_vector.y = 0;
+      interpreter->state.freedom_vector.x = 040000; /* 1.0 */
+      interpreter->state.freedom_vector.y = 0;
+      interpreter->state.projection_vector.x = 040000; /* 1.0 */
+      interpreter->state.projection_vector.y = 0;
+      interpreter->state.rp0 = 0;
+      interpreter->state.rp1 = 0;
+      interpreter->state.rp2 = 0;
+      interpreter->state.zp0 = 1;
+      interpreter->state.zp1 = 1;
+      interpreter->state.zp2 = 1;
+      interpreter->state.loop = 1;
+
+      /* Validate the graphics state.  */
+      sfnt_validate_gs (&interpreter->state);
+    }
 
   /* Save the graphics state upon success.  */
   memcpy (state, &interpreter->state, sizeof *state);
@@ -11208,15 +12475,18 @@ sfnt_decompose_instructed_outline (struct 
sfnt_instructed_outline *outline,
 
 /* Decompose and build an outline for the specified instructed outline
    INSTRUCTED.  Return the outline data with a refcount of 0 upon
-   success, or NULL upon failure.
+   success, and the advance width of the instructed glyph in
+   *ADVANCE_WIDTH, or NULL upon failure.
 
    This function is not reentrant.  */
 
 TEST_STATIC struct sfnt_glyph_outline *
-sfnt_build_instructed_outline (struct sfnt_instructed_outline *instructed)
+sfnt_build_instructed_outline (struct sfnt_instructed_outline *instructed,
+                              sfnt_fixed *advance_width)
 {
   struct sfnt_glyph_outline *outline;
   int rc;
+  sfnt_f26dot6 x1, x2;
 
   memset (&build_outline_context, 0, sizeof build_outline_context);
 
@@ -11253,10 +12523,23 @@ sfnt_build_instructed_outline (struct 
sfnt_instructed_outline *instructed)
      instructed.  */
 
   if (instructed->num_points > 1)
-    outline->origin
-      = instructed->x_points[instructed->num_points - 2];
+    {
+      x1 = instructed->x_points[instructed->num_points - 2];
+      x2 = instructed->x_points[instructed->num_points - 1];
+
+      /* Convert the origin point to a 16.16 fixed point number.  */
+      outline->origin = x1 * 1024;
+
+      /* Do the same for the advance width.  */
+      *advance_width = (x2 - x1) * 1024;
+    }
   else
-    outline->origin = 0;
+    {
+      /* Phantom points are absent from this outline, which is
+        impossible.  */
+      *advance_width = 0;
+      outline->origin = 0;
+    }
 
   if (rc)
     {
@@ -11274,14 +12557,18 @@ sfnt_build_instructed_outline (struct 
sfnt_instructed_outline *instructed)
    scale SCALE.
 
    Place the X and Y coordinates of the first phantom point in *X1 and
-   *Y1, and those of the second phantom point in *X2 and *Y2.  */
+   *Y1, and those of the second phantom point in *X2 and *Y2.
+
+   Place the unrounded X coordinates of both phantom points in *S1 and
+   *S2 respectively.  */
 
 static void
 sfnt_compute_phantom_points (struct sfnt_glyph *glyph,
                             struct sfnt_glyph_metrics *metrics,
                             sfnt_fixed scale,
                             sfnt_f26dot6 *x1, sfnt_f26dot6 *y1,
-                            sfnt_f26dot6 *x2, sfnt_f26dot6 *y2)
+                            sfnt_f26dot6 *x2, sfnt_f26dot6 *y2,
+                            sfnt_f26dot6 *s1, sfnt_f26dot6 *s2)
 {
   sfnt_fword f1, f2;
 
@@ -11301,8 +12588,14 @@ sfnt_compute_phantom_points (struct sfnt_glyph *glyph,
   f2 += glyph->advance_distortion;
 
   /* Next, scale both up.  */
-  *x1 = sfnt_mul_f26dot6_fixed (f1 * 64, scale);
-  *x2 = sfnt_mul_f26dot6_fixed (f2 * 64, scale);
+  *s1 = sfnt_mul_f26dot6_fixed (f1, scale);
+  *s2 = sfnt_mul_f26dot6_fixed (f2, scale);
+
+  /* While not expressly provided in the manual, the phantom points
+     (at times termed the advance and origin points) represent pixel
+     coordinates within the raster, and are therefore rounded.  */
+  *x1 = sfnt_round_f26dot6 (*s1);
+  *x2 = sfnt_round_f26dot6 (*s2);
 
   /* Clear y1 and y2.  */
   *y1 = 0;
@@ -11325,9 +12618,7 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
   size_t zone_size, temp, outline_size, i;
   struct sfnt_interpreter_zone *zone;
   struct sfnt_interpreter_zone *volatile preserved_zone;
-  sfnt_f26dot6 phantom_point_1_x;
   sfnt_f26dot6 phantom_point_1_y;
-  sfnt_f26dot6 phantom_point_2_x;
   sfnt_f26dot6 phantom_point_2_y;
   sfnt_f26dot6 tem;
   volatile bool zone_was_allocated;
@@ -11338,19 +12629,16 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
 
   /* Calculate the size of the zone structure.  */
 
-  if (INT_MULTIPLY_WRAPV (glyph->simple->number_of_points + 2,
-                         sizeof *zone->x_points * 4,
-                         &temp)
-      || INT_ADD_WRAPV (temp, zone_size, &zone_size)
-      || INT_MULTIPLY_WRAPV (glyph->number_of_contours,
-                            sizeof *zone->contour_end_points,
-                            &temp)
-      || INT_ADD_WRAPV (temp, zone_size, &zone_size)
-      || INT_MULTIPLY_WRAPV (glyph->simple->number_of_points + 2,
-                            sizeof *zone->flags,
-                            &temp)
-      || INT_ADD_WRAPV (temp, zone_size, &zone_size)
-      || INT_ADD_WRAPV (sizeof *zone, zone_size, &zone_size))
+  if (ckd_mul (&temp, glyph->simple->number_of_points + 2,
+              sizeof *zone->x_points * 4)
+      || ckd_add (&zone_size, zone_size, temp)
+      || ckd_mul (&temp, glyph->number_of_contours,
+                 sizeof *zone->contour_end_points)
+      || ckd_add (&zone_size, zone_size, temp)
+      || ckd_mul (&temp, glyph->simple->number_of_points + 2,
+                 sizeof *zone->flags)
+      || ckd_add (&zone_size, zone_size, temp)
+      || ckd_add (&zone_size, zone_size, sizeof *zone))
     return "Glyph exceeded maximum permissible size";
 
   /* Don't use malloc if possible.  */
@@ -11374,6 +12662,7 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
   zone->y_current = zone->y_points + zone->num_points;
   zone->flags = (unsigned char *) (zone->y_current
                                   + zone->num_points);
+  zone->simple = glyph->simple;
 
   /* Load x_points and x_current.  */
   for (i = 0; i < glyph->simple->number_of_points; ++i)
@@ -11382,23 +12671,25 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
       tem = glyph->simple->x_coordinates[i];
 
       /* Scale that fword.  */
-      tem = sfnt_mul_f26dot6_fixed (tem * 64, interpreter->scale);
+      tem = sfnt_mul_f26dot6_fixed (tem, interpreter->scale);
 
       /* Set x_points and x_current.  */
       zone->x_points[i] = tem;
       zone->x_current[i] = tem;
     }
 
-  /* Compute phantom points.  */
+  /* Compute and load phantom points.  */
   sfnt_compute_phantom_points (glyph, metrics, interpreter->scale,
-                              &phantom_point_1_x, &phantom_point_1_y,
-                              &phantom_point_2_x, &phantom_point_2_y);
-
-  /* Load phantom points.  */
-  zone->x_points[i] = phantom_point_1_x;
-  zone->x_points[i + 1] = phantom_point_2_x;
-  zone->x_current[i] = phantom_point_1_x;
-  zone->x_current[i + 1] = phantom_point_2_x;
+                              &zone->x_current[i], &phantom_point_1_y,
+                              &zone->x_current[i + 1], &phantom_point_2_y,
+                              /* Phantom points are rounded to the
+                                 pixel grid once they are inserted
+                                 into the glyph zone, but the
+                                 original coordinates must remain
+                                 untouched, as fonts rely on this to
+                                 interpolate points by this
+                                 scale.  */
+                              &zone->x_points[i], &zone->x_points[i + 1]);
 
   /* Load y_points and y_current, along with flags.  */
   for (i = 0; i < glyph->simple->number_of_points; ++i)
@@ -11408,7 +12699,7 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
 
       /* Scale that fword.  Make sure not to round Y, as this could
         lead to Y spilling over to the next line.  */
-      tem = sfnt_mul_fixed (tem * 64, interpreter->scale);
+      tem = sfnt_mul_f26dot6_fixed (tem, interpreter->scale);
 
       /* Set y_points and y_current.  */
       zone->y_points[i] = tem;
@@ -11425,8 +12716,8 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
   /* Load phantom points.  */
   zone->y_points[i] = phantom_point_1_y;
   zone->y_points[i + 1] = phantom_point_2_y;
-  zone->y_current[i] = phantom_point_1_x;
-  zone->y_current[i + 1] = phantom_point_2_x;
+  zone->y_current[i] = phantom_point_1_y;
+  zone->y_current[i + 1] = phantom_point_2_y;
 
   /* Load phantom point flags.  */
   zone->flags[i] = SFNT_POINT_PHANTOM;
@@ -11583,7 +12874,8 @@ sfnt_transform_f26dot6 (struct 
sfnt_compound_glyph_component *component,
 /* Internal helper for sfnt_interpret_compound_glyph_3.
 
    Instruct the compound glyph GLYPH using INTERPRETER after all of
-   its components have been instructed.
+   its components have been instructed.  Save the resulting points
+   within CONTEXT, and set its phantom point fields to match as well.
 
    Use the unscaled METRICS to compute the phantom points of this
    glyph.
@@ -11593,6 +12885,11 @@ sfnt_transform_f26dot6 (struct 
sfnt_compound_glyph_component *component,
    In addition, CONTEXT also contains two additional ``phantom
    points'' supplying the left and right side bearings of GLYPH.
 
+   S1 and S2 are the unrounded values of the last two phantom points,
+   which supply the original values saved into the glyph zone.  In
+   practical terms, they are set as the last two values of the glyph
+   zone's original position array.
+
    Value is NULL upon success, or a description of the error upon
    failure.  */
 
@@ -11601,22 +12898,22 @@ sfnt_interpret_compound_glyph_2 (struct sfnt_glyph 
*glyph,
                                 struct sfnt_interpreter *interpreter,
                                 struct sfnt_compound_glyph_context *context,
                                 size_t base_index, size_t base_contour,
-                                struct sfnt_glyph_metrics *metrics)
+                                struct sfnt_glyph_metrics *metrics,
+                                sfnt_f26dot6 s1, sfnt_f26dot6 s2)
 {
   size_t num_points, num_contours, i;
   size_t zone_size, temp;
   struct sfnt_interpreter_zone *zone;
   struct sfnt_interpreter_zone *volatile preserved_zone;
   volatile bool zone_was_allocated;
-  int rc;
   sfnt_f26dot6 *x_base, *y_base;
-  size_t *contour_base;
-  unsigned char *flags_base;
 
-  /* Figure out how many points and contours there are to
-     instruct.  */
+  /* Figure out how many points and contours there are to instruct.  A
+     minimum of two points must be present, namely: the origin and
+     advance phantom points.  */
   num_points = context->num_points - base_index;
   num_contours = context->num_end_points - base_contour;
+  assert (num_points >= 2);
 
   /* Nothing to instruct! */
   if (!num_points && !num_contours)
@@ -11628,19 +12925,13 @@ sfnt_interpret_compound_glyph_2 (struct sfnt_glyph 
*glyph,
   zone_size = 0;
   zone_was_allocated = false;
 
-  if (INT_MULTIPLY_WRAPV (num_points + 2,
-                         sizeof *zone->x_points * 4,
-                         &temp)
-      || INT_ADD_WRAPV (temp, zone_size, &zone_size)
-      || INT_MULTIPLY_WRAPV (num_contours,
-                            sizeof *zone->contour_end_points,
-                            &temp)
-      || INT_ADD_WRAPV (temp, zone_size, &zone_size)
-      || INT_MULTIPLY_WRAPV (num_points + 2,
-                            sizeof *zone->flags,
-                            &temp)
-      || INT_ADD_WRAPV (temp, zone_size, &zone_size)
-      || INT_ADD_WRAPV (sizeof *zone, zone_size, &zone_size))
+  if (ckd_mul (&temp, num_points + 2, sizeof *zone->x_points * 4)
+      || ckd_add (&zone_size, zone_size, temp)
+      || ckd_mul (&temp, num_contours, sizeof *zone->contour_end_points)
+      || ckd_add (&zone_size, zone_size, temp)
+      || ckd_mul (&temp, num_points + 2, sizeof *zone->flags)
+      || ckd_add (&zone_size, zone_size, temp)
+      || ckd_add (&zone_size, zone_size, sizeof *zone))
     return "Glyph exceeded maximum permissible size";
 
   /* Don't use malloc if possible.  */
@@ -11664,6 +12955,7 @@ sfnt_interpret_compound_glyph_2 (struct sfnt_glyph 
*glyph,
   zone->y_current = zone->y_points + zone->num_points;
   zone->flags = (unsigned char *) (zone->y_current
                                   + zone->num_points);
+  zone->simple = NULL;
 
   /* Copy and renumber all contour end points to start from
      base_index.  */
@@ -11691,6 +12983,11 @@ sfnt_interpret_compound_glyph_2 (struct sfnt_glyph 
*glyph,
                        & ~SFNT_POINT_TOUCHED_BOTH);
     }
 
+  /* Copy S1 and S2 into the glyph zone.  */
+  assert (num_points >= 2);
+  zone->x_points[num_points - 1] = s2;
+  zone->x_points[num_points - 2] = s1;
+
   /* Load the compound glyph program.  */
   interpreter->IP = 0;
   interpreter->SP = interpreter->stack;
@@ -11725,27 +13022,20 @@ sfnt_interpret_compound_glyph_2 (struct sfnt_glyph 
*glyph,
       context->y_coordinates[base_index + i] = zone->y_current[i];
     }
 
-  /* Grow various arrays to fit the phantom points.  */
-  rc = sfnt_expand_compound_glyph_context (context, 0, 2,
-                                          &x_base, &y_base,
-                                          &flags_base,
-                                          &contour_base);
-
-  if (rc)
-    {
-      if (zone_was_allocated)
-       xfree (zone);
-
-      return "Failed to expand arrays for phantom points";
-    }
-
-  /* Copy over the phantom points.  */
+  /* Return the phantom points after instructing completes to the
+     context's coordinate arrays.  */
+  x_base    = &context->x_coordinates[i - 2];
+  y_base    = &context->y_coordinates[i - 2];
   x_base[0] = zone->x_current[num_points - 2];
   x_base[1] = zone->x_current[num_points - 1];
   y_base[0] = zone->y_current[num_points - 2];
   y_base[1] = zone->y_current[num_points - 1];
-  flags_base[0] = zone->flags[num_points - 2];
-  flags_base[1] = zone->flags[num_points - 1];
+  context->phantom_point_1_x = x_base[0];
+  context->phantom_point_1_y = y_base[0];
+  context->phantom_point_1_s = x_base[0];
+  context->phantom_point_2_x = x_base[1];
+  context->phantom_point_2_y = y_base[1];
+  context->phantom_point_2_s = x_base[1];
 
   /* Free the zone if needed.  */
   if (zone_was_allocated)
@@ -11792,10 +13082,8 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph 
*glyph,
   bool defer_offsets;
   struct sfnt_instructed_outline *value;
   struct sfnt_glyph_metrics sub_metrics;
-  sfnt_f26dot6 phantom_point_1_x;
-  sfnt_f26dot6 phantom_point_1_y;
-  sfnt_f26dot6 phantom_point_2_x;
-  sfnt_f26dot6 phantom_point_2_y;
+  sfnt_f26dot6 pp1x, pp1y, pp1s;
+  sfnt_f26dot6 pp2x, pp2y, pp2s;
 
   error = NULL;
 
@@ -11818,6 +13106,17 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph 
*glyph,
   /* Pacify -Wmaybe-uninitialized.  */
   point = point2 = 0;
 
+  /* Compute phantom points for this glyph here.  They will be
+     subsequently overridden if a component glyph's metrics must be
+     used instead.  */
+  sfnt_compute_phantom_points (glyph, metrics, interpreter->scale,
+                              &context->phantom_point_1_x,
+                              &context->phantom_point_1_y,
+                              &context->phantom_point_2_x,
+                              &context->phantom_point_2_y,
+                              &context->phantom_point_1_s,
+                              &context->phantom_point_2_s);
+
   for (j = 0; j < glyph->compound->num_components; ++j)
     {
       /* Look up the associated subglyph.  */
@@ -11848,14 +13147,14 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph 
*glyph,
          if (!(component->flags & 01)) /* ARG_1_AND_2_ARE_WORDS */
            {
              /* X and Y are signed bytes.  */
-             x = component->argument1.b * 64;
-             y = component->argument2.b * 64;
+             x = component->argument1.b;
+             y = component->argument2.b;
            }
          else
            {
              /* X and Y are signed words.  */
-             x = component->argument1.d * 64;
-             y = component->argument2.d * 64;
+             x = component->argument1.d;
+             y = component->argument2.d;
            }
 
          /* Now convert X and Y into device coordinates.  */
@@ -11877,7 +13176,7 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph 
*glyph,
       else
        {
          /* The offset is determined by matching a point location in
-            a preceeding component with a point location in the
+            a preceding component with a point location in the
             current component.  The index of the point in the
             previous component is established by adding
             component->argument1.a or component->argument1.c to
@@ -11937,8 +13236,8 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph 
*glyph,
         decomposition.  */
 
       if (sfnt_lookup_glyph_metrics (component->glyph_index,
-                                    -1, &sub_metrics,
-                                    hmtx, hhea, NULL, maxp))
+                                    &sub_metrics, hmtx, hhea,
+                                    maxp))
        {
          if (need_free)
            free_glyph (subglyph, dcontext);
@@ -12042,6 +13341,27 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph 
*glyph,
                  y = (ytemp - value->y_points[point2]);
                }
 
+             /* If USE_MY_METRICS is present in this component, save
+                the instructed phantom points inside CONTEXT.
+
+                N.B. such points replace even the unrounded points
+                within the context, as this distinction is lost in
+                phantom points sourced from instructed glyphs.  */
+
+             if (component->flags & 01000) /* USE_MY_METRICS */
+               {
+                 context->phantom_point_1_x
+                   = context->phantom_point_1_s
+                   = value->x_points[last_point];
+                 context->phantom_point_1_y
+                   = value->y_points[last_point];
+                 context->phantom_point_2_x
+                   = context->phantom_point_2_s
+                   = value->x_points[last_point + 1];
+                 context->phantom_point_2_y
+                   = value->y_points[last_point + 1];
+               }
+
              xfree (value);
 
              /* Apply the transform to the points, excluding phantom
@@ -12053,7 +13373,17 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph 
*glyph,
       else
        {
          /* Compound subglyph.  Decompose and instruct the glyph
-            recursively, and then apply the transform.  */
+            recursively, and then apply the transform.
+
+            If USE_MY_METRICS is not set, save the phantom points
+            presently in CONTEXT, then restore them afterwards.  */
+
+         pp1x = context->phantom_point_1_x;
+         pp1y = context->phantom_point_1_y;
+         pp1s = context->phantom_point_1_s;
+         pp2x = context->phantom_point_2_x;
+         pp2y = context->phantom_point_2_y;
+         pp2s = context->phantom_point_2_s;
 
          error = sfnt_interpret_compound_glyph_1 (subglyph, interpreter,
                                                   state,
@@ -12071,6 +13401,16 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph 
*glyph,
              return error;
            }
 
+         if (!(component->flags & 01000)) /* USE_MY_METRICS */
+           {
+             context->phantom_point_1_x = pp1x;
+             context->phantom_point_1_y = pp1y;
+             context->phantom_point_1_s = pp1s;
+             context->phantom_point_2_x = pp2x;
+             context->phantom_point_2_y = pp2y;
+             context->phantom_point_2_s = pp2s;
+           }
+
          /* Anchor points for glyphs with instructions must be
             computed after grid fitting completes.
 
@@ -12130,13 +13470,8 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph 
*glyph,
     }
 
   /* Run the program for the entire compound glyph, if any.  CONTEXT
-     should not contain phantom points by this point, so append its
-     own.  */
-
-  /* Compute phantom points.  */
-  sfnt_compute_phantom_points (glyph, metrics, interpreter->scale,
-                              &phantom_point_1_x, &phantom_point_1_y,
-                              &phantom_point_2_x, &phantom_point_2_y);
+     should not contain phantom points by this point, so append the
+     points for this glyph as a whole.  */
 
   /* Grow various arrays to include those points.  */
   rc = sfnt_expand_compound_glyph_context (context,
@@ -12150,10 +13485,10 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph 
*glyph,
                                           &flags_base, &contour_base);
 
   /* Store the phantom points within the compound glyph.  */
-  x_base[0] = phantom_point_1_x;
-  x_base[1] = phantom_point_2_x;
-  y_base[0] = phantom_point_1_y;
-  y_base[1] = phantom_point_2_y;
+  x_base[0] = context->phantom_point_1_x;
+  x_base[1] = context->phantom_point_2_x;
+  y_base[0] = context->phantom_point_1_y;
+  y_base[1] = context->phantom_point_2_y;
   flags_base[0] = SFNT_POINT_PHANTOM;
   flags_base[1] = SFNT_POINT_PHANTOM;
 
@@ -12163,7 +13498,9 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph 
*glyph,
       error = sfnt_interpret_compound_glyph_2 (glyph, interpreter,
                                               context, base_index,
                                               base_contour,
-                                              metrics);
+                                              metrics,
+                                              context->phantom_point_1_s,
+                                              context->phantom_point_2_s);
     }
 
   return error;
@@ -12237,16 +13574,12 @@ sfnt_interpret_compound_glyph (struct sfnt_glyph 
*glyph,
   /* Copy the compound glyph data into an instructed outline.  */
   outline_size = sizeof (*outline);
 
-  if (INT_MULTIPLY_WRAPV (context.num_end_points,
-                         sizeof *outline->contour_end_points,
-                         &temp)
-      || INT_ADD_WRAPV (outline_size, temp, &outline_size)
-      || INT_MULTIPLY_WRAPV (context.num_points,
-                            sizeof *outline->x_points * 2,
-                            &temp)
-      || INT_ADD_WRAPV (outline_size, temp, &outline_size)
-      || INT_ADD_WRAPV (context.num_points, outline_size,
-                       &outline_size))
+  if (ckd_mul (&temp, context.num_end_points,
+              sizeof *outline->contour_end_points)
+      || ckd_add (&outline_size, outline_size, temp)
+      || ckd_mul (&temp, context.num_points, sizeof *outline->x_points * 2)
+      || ckd_add (&outline_size, outline_size, temp)
+      || ckd_add (&outline_size, outline_size, context.num_points))
     {
       xfree (context.x_coordinates);
       xfree (context.y_coordinates);
@@ -12369,9 +13702,8 @@ sfnt_read_default_uvs_table (int fd, off_t offset)
   /* Now, allocate enough to hold the UVS table.  */
 
   size = sizeof *uvs;
-  if (INT_MULTIPLY_WRAPV (sizeof *uvs->ranges, num_ranges,
-                         &temp)
-      || INT_ADD_WRAPV (temp, size, &size))
+  if (ckd_mul (&temp, num_ranges, sizeof *uvs->ranges)
+      || ckd_add (&size, size, temp))
     return NULL;
 
   uvs = xmalloc (size);
@@ -12440,9 +13772,8 @@ sfnt_read_nondefault_uvs_table (int fd, off_t offset)
   /* Now, allocate enough to hold the UVS table.  */
 
   size = sizeof *uvs;
-  if (INT_MULTIPLY_WRAPV (sizeof *uvs->mappings, num_mappings,
-                         &temp)
-      || INT_ADD_WRAPV (temp, size, &size))
+  if (ckd_mul (&temp, num_mappings, sizeof *uvs->mappings)
+      || ckd_add (&size, size, temp))
     return NULL;
 
   uvs = xmalloc (size);
@@ -12522,9 +13853,9 @@ sfnt_create_uvs_context (struct sfnt_cmap_format_14 
*cmap, int fd)
   off_t offset;
   struct sfnt_uvs_context *context;
 
-  if (INT_MULTIPLY_WRAPV (cmap->num_var_selector_records,
-                         sizeof *table_offsets, &size)
-      || INT_MULTIPLY_WRAPV (size, 2, &size))
+  if (ckd_mul (&size, cmap->num_var_selector_records,
+              sizeof *table_offsets)
+      || ckd_mul (&size, size, 2))
     return NULL;
 
   context = NULL;
@@ -12544,9 +13875,8 @@ sfnt_create_uvs_context (struct sfnt_cmap_format_14 
*cmap, int fd)
 
       if (cmap->records[i].default_uvs_offset)
        {
-         if (INT_ADD_WRAPV (cmap->offset,
-                            cmap->records[i].default_uvs_offset,
-                            &table_offsets[j].offset))
+         if (ckd_add (&table_offsets[j].offset, cmap->offset,
+                      cmap->records[i].default_uvs_offset))
            goto bail;
 
          table_offsets[j++].is_nondefault_table = false;
@@ -12554,9 +13884,8 @@ sfnt_create_uvs_context (struct sfnt_cmap_format_14 
*cmap, int fd)
 
       if (cmap->records[i].nondefault_uvs_offset)
        {
-         if (INT_ADD_WRAPV (cmap->offset,
-                            cmap->records[i].nondefault_uvs_offset,
-                            &table_offsets[j].offset))
+         if (ckd_add (&table_offsets[j].offset, cmap->offset,
+                      cmap->records[i].nondefault_uvs_offset))
            goto bail;
 
          table_offsets[j++].is_nondefault_table = true;
@@ -12994,14 +14323,12 @@ sfnt_read_fvar_table (int fd, struct 
sfnt_offset_subtable *subtable)
      name identifier, or 3 * sizeof (uint16_t) + axisCount * sizeof
      (sfnt_fixed), meaning there is.  */
 
-  if (INT_MULTIPLY_WRAPV (fvar->axis_count, sizeof (sfnt_fixed),
-                         &temp)
-      || INT_ADD_WRAPV (2 * sizeof (uint16_t), temp, &non_ps_size))
+  if (ckd_mul (&temp, fvar->axis_count, sizeof (sfnt_fixed))
+      || ckd_add (&non_ps_size, temp, 2 * sizeof (uint16_t)))
     goto bail;
 
-  if (INT_MULTIPLY_WRAPV (fvar->axis_count, sizeof (sfnt_fixed),
-                         &temp)
-      || INT_ADD_WRAPV (3 * sizeof (uint16_t), temp, &ps_size))
+  if (ckd_mul (&temp, fvar->axis_count, sizeof (sfnt_fixed))
+      || ckd_add (&ps_size, temp, 3 * sizeof (uint16_t)))
     goto bail;
 
   if (fvar->instance_size != non_ps_size
@@ -13011,8 +14338,7 @@ sfnt_read_fvar_table (int fd, struct 
sfnt_offset_subtable *subtable)
   /* Now compute the offset of the axis data from the start of the
      font file.  */
 
-  if (INT_ADD_WRAPV (fvar->offset_to_data, directory->offset,
-                    &offset))
+  if (ckd_add (&offset, fvar->offset_to_data, directory->offset))
     goto bail;
 
   /* Seek there.  */
@@ -13029,28 +14355,23 @@ sfnt_read_fvar_table (int fd, struct 
sfnt_offset_subtable *subtable)
      sfnt_instance) + sizeof (sfnt_fixed) * fvar->instance_count *
      fvar->axis_count.  */
 
-  if (INT_MULTIPLY_WRAPV (fvar->axis_count, sizeof *fvar->axis,
-                         &temp)
-      || INT_ADD_WRAPV (min_bytes, temp, &min_bytes))
+  if (ckd_mul (&temp, fvar->axis_count, sizeof *fvar->axis)
+      || ckd_add (&min_bytes, min_bytes, temp))
     goto bail;
 
-  pad = alignof (struct sfnt_variation_axis);
+  pad = alignof (struct sfnt_instance);
   pad -= min_bytes & (pad - 1);
 
-  if (INT_ADD_WRAPV (min_bytes, pad, &min_bytes))
+  if (ckd_add (&min_bytes, min_bytes, pad))
     goto bail;
 
-  if (INT_MULTIPLY_WRAPV (fvar->instance_count,
-                         sizeof *fvar->instance,
-                         &temp)
-      || INT_ADD_WRAPV (min_bytes, temp, &min_bytes))
+  if (ckd_mul (&temp, fvar->instance_count, sizeof *fvar->instance)
+      || ckd_add (&min_bytes, min_bytes, temp))
     goto bail;
 
-  if (INT_MULTIPLY_WRAPV (fvar->instance_count,
-                         sizeof *fvar->instance->coords,
-                         &temp)
-      || INT_MULTIPLY_WRAPV (temp, fvar->axis_count, &temp)
-      || INT_ADD_WRAPV (min_bytes, temp, &min_bytes))
+  if (ckd_mul (&temp, fvar->instance_count, sizeof *fvar->instance->coords)
+      || ckd_mul (&temp, temp, fvar->axis_count)
+      || ckd_add (&min_bytes, min_bytes, temp))
     goto bail;
 
   /* Reallocate fvar.  */
@@ -13232,9 +14553,9 @@ sfnt_read_gvar_table (int fd, struct 
sfnt_offset_subtable *subtable)
     goto bail;
 
   /* Figure out how big gvar needs to be.  */
-  if (INT_ADD_WRAPV (sizeof *gvar, coordinate_size, &min_bytes)
-      || INT_ADD_WRAPV (min_bytes, off_size, &min_bytes)
-      || INT_ADD_WRAPV (min_bytes, data_size, &min_bytes))
+  if (ckd_add (&min_bytes, coordinate_size, sizeof *gvar)
+      || ckd_add (&min_bytes, min_bytes, off_size)
+      || ckd_add (&min_bytes, min_bytes, data_size))
     goto bail;
 
   /* Now allocate enough for all of this extra data.  */
@@ -13270,8 +14591,7 @@ sfnt_read_gvar_table (int fd, struct 
sfnt_offset_subtable *subtable)
 
   if (gvar->shared_coord_count)
     {
-      if (INT_ADD_WRAPV (gvar->offset_to_coord, directory->offset,
-                        &offset))
+      if (ckd_add (&offset, gvar->offset_to_coord, directory->offset))
        goto bail;
 
       if (lseek (fd, offset, SEEK_SET) != offset)
@@ -13295,8 +14615,7 @@ sfnt_read_gvar_table (int fd, struct 
sfnt_offset_subtable *subtable)
 
   if (gvar->data_size)
     {
-      if (INT_ADD_WRAPV (gvar->offset_to_data, directory->offset,
-                        &offset))
+      if (ckd_add (&offset, gvar->offset_to_data, directory->offset))
        goto bail;
 
       if (lseek (fd, offset, SEEK_SET) != offset)
@@ -13392,10 +14711,10 @@ sfnt_read_avar_table (int fd, struct 
sfnt_offset_subtable *subtable)
 
       /* Now add one struct sfnt_short_frac_segment for each axis and
          each of its correspondences.  */
-      if (INT_ADD_WRAPV (sizeof (struct sfnt_short_frac_segment),
-                        min_size, &min_size)
-         || INT_ADD_WRAPV (sizeof (struct sfnt_short_frac_correspondence)
-                           * buffer[k], min_size, &min_size))
+      if (ckd_add (&min_size, min_size, sizeof (struct 
sfnt_short_frac_segment))
+         || ckd_add (&min_size, min_size,
+                     (sizeof (struct sfnt_short_frac_correspondence)
+                      * buffer[k])))
        goto bail1;
 
       /* Verify that words from here to buffer[1 + buffer[k] * 2], the
@@ -13744,8 +15063,7 @@ sfnt_read_cvar_table (int fd, struct 
sfnt_offset_subtable *subtable,
            goto bail2;
 
          tuple += sizeof *coords * fvar->axis_count;
-         if (INT_ADD_WRAPV (size, sizeof *coords * fvar->axis_count,
-                            &size))
+         if (ckd_add (&size, size, sizeof *coords * fvar->axis_count))
            goto bail2;
        }
       else
@@ -13757,20 +15075,20 @@ sfnt_read_cvar_table (int fd, struct 
sfnt_offset_subtable *subtable,
       if (index & 0x4000)
        {
          tuple += fvar->axis_count * 4;
-         if (INT_ADD_WRAPV (size, fvar->axis_count * 4, &size))
+         if (ckd_add (&size, size, fvar->axis_count * 4))
            goto bail2;
        }
 
       /* Add one point and one delta for each CVT element.  */
-      if (INT_ADD_WRAPV (size, cvt->num_elements * 4, &size))
+      if (ckd_add (&size, size, cvt->num_elements * 4))
        goto bail2;
 
       /* Now add the size of the tuple.  */
-      if (INT_ADD_WRAPV (size, sizeof *cvar->variation, &size))
+      if (ckd_add (&size, size, sizeof *cvar->variation))
        goto bail2;
     }
 
-  if (INT_ADD_WRAPV (sizeof *cvar, size, &size))
+  if (ckd_add (&size, size, sizeof *cvar))
     goto bail2;
 
   /* Reallocate cvar.  */
@@ -14173,322 +15491,235 @@ sfnt_compute_tuple_scale (struct sfnt_blend *blend, 
bool intermediate_p,
   return scale;
 }
 
-/* Infer point positions for points that have been partially moved
-   within the contour in GLYPH denoted by START and END.  */
+/* Move each point in the simple glyph GLYPH between PAIR_START and
+   PAIR_END to agree with the positions of those two anchor points as
+   compared with their initial positions recorded within the arrays X
+   and Y.
+
+   The range formed between PAIR_START and PAIR_END may encompass the
+   upper extreme of the contour between START and END.  */
 
 static void
-sfnt_infer_deltas_1 (struct sfnt_glyph *glyph, size_t start,
-                    size_t end, bool *touched, sfnt_fword *x,
-                    sfnt_fword *y)
+sfnt_infer_deltas_2 (struct sfnt_glyph *glyph, size_t pair_start,
+                    size_t pair_end, size_t start, size_t end,
+                    sfnt_fword *x, sfnt_fword *y)
 {
-  size_t i, pair_start, pair_end, pair_first, j;
-  sfnt_fword min_pos, max_pos, position;
+  size_t j;
+  sfnt_fword min_pos, max_pos, position, d1, d2;
   sfnt_fixed ratio, delta;
 
-  pair_start = pair_first = -1;
-
-  /* Look for pairs of touched points.  */
+  j = pair_start + 1;
 
-  for (i = start; i <= end; ++i)
+  while (j != pair_end)
     {
-      if (!touched[i])
-       continue;
+      /* Reset j to the contour's start position if it is about to
+        overrun this contour.  */
 
-      if (pair_start == -1)
+      if (j > end)
        {
-         pair_first = i;
-         goto next;
+         /* The start of the contour might also be the end of this
+            reference point.  */
+         if (start == pair_end)
+           return;
+
+         j = start;
        }
 
-      pair_end = i;
+      /* Consider the X axis.  Set min_pos and max_pos to the
+        smallest and greatest values along that axis.  */
+      min_pos = MIN (x[pair_start], x[pair_end]);
+      max_pos = MAX (x[pair_start], x[pair_end]);
 
-      /* pair_start to pair_end are now a pair of points, where points
-        in between should be interpolated.  */
+      /* Now see if the current point lies between min and
+        max...
 
-      for (j = pair_start + 1; j < pair_end; ++j)
+         GX interpolation differs from IUP in one important detail:
+         points are shifted to follow the movement of their reference
+         points if their positions are identical to those of any of
+         their reference points, whereas IUP considers such points to
+         fall within their reference points.  */
+      if (x[j] > min_pos && x[j] < max_pos)
+       {
+         /* Interpolate between min_pos and max_pos.  */
+         ratio = sfnt_div_fixed ((sfnt_sub (x[j], min_pos)
+                                  * 65536),
+                                 (sfnt_sub (max_pos, min_pos)
+                                  * 65536));
+
+         /* Load the current positions of pair_start and pair_end
+            along this axis.  */
+         min_pos = MIN (glyph->simple->x_coordinates[pair_start],
+                        glyph->simple->x_coordinates[pair_end]);
+         max_pos = MAX (glyph->simple->x_coordinates[pair_start],
+                        glyph->simple->x_coordinates[pair_end]);
+
+         /* Lerp in between.  */
+         delta = sfnt_sub (max_pos, min_pos);
+         delta = sfnt_mul_fixed (ratio, delta);
+         glyph->simple->x_coordinates[j] = min_pos + delta;
+       }
+      else
        {
-         /* Consider the X axis.  Set min_pos and max_pos to the
-            smallest and greatest values along that axis.  */
-         min_pos = MIN (x[pair_start], x[pair_end]);
-         max_pos = MAX (x[pair_start], x[pair_end]);
-
-         /* Now see if the current point lies between min and
-            max... */
-         if (x[j] >= min_pos && x[j] <= max_pos)
+         /* ... otherwise, move point j by the delta of the
+            nearest touched point.  */
+
+         /* If min_pos and max_pos are the same, apply
+            pair_start's delta if it is identical to that of
+            pair_end, or apply nothing at all otherwise.  */
+
+         if (min_pos == max_pos)
            {
-             /* If min_pos and max_pos are the same, apply
-                pair_start's delta if it is identical to that of
-                pair_end, or apply nothing at all otherwise.  */
+             d1 = (glyph->simple->x_coordinates[pair_start]
+                   - x[pair_start]);
+             d2 = (glyph->simple->x_coordinates[pair_end]
+                   - x[pair_end]);
 
-             if (min_pos == max_pos)
-               {
-                 if ((glyph->simple->x_coordinates[pair_start]
-                      - x[pair_start])
-                     == (glyph->simple->x_coordinates[pair_end]
-                         - x[pair_end]))
-                   glyph->simple->x_coordinates[j]
-                     += (glyph->simple->x_coordinates[pair_start]
-                         - x[pair_start]);
+             if (d1 == d2)
+               glyph->simple->x_coordinates[j] += d1;
 
-                 continue;
-               }
+             goto consider_y;
+           }
 
-             /* Interpolate between min_pos and max_pos.  */
-             ratio = sfnt_div_fixed ((sfnt_sub (x[j], min_pos)
-                                      * 65536),
-                                     (sfnt_sub (max_pos, min_pos)
-                                      * 65536));
-
-             /* Load the current positions of pair_start and pair_end
-                along this axis.  */
-             min_pos = MIN (glyph->simple->x_coordinates[pair_start],
-                            glyph->simple->x_coordinates[pair_end]);
-             max_pos = MAX (glyph->simple->x_coordinates[pair_start],
-                            glyph->simple->x_coordinates[pair_end]);
-
-             /* Lerp in between.  */
-             delta = sfnt_sub (max_pos, min_pos);
-             delta = sfnt_mul_fixed (ratio, delta);
-             glyph->simple->x_coordinates[j] = min_pos + delta;
+         if (x[j] >= max_pos)
+           {
+             position = MAX (glyph->simple->x_coordinates[pair_start],
+                             glyph->simple->x_coordinates[pair_end]);
+             delta = position - max_pos;
            }
          else
            {
-             /* ... otheriwse, move point j by the delta of the
-                nearest touched point.  */
+             position = MIN (glyph->simple->x_coordinates[pair_start],
+                             glyph->simple->x_coordinates[pair_end]);
+             delta = position - min_pos;
+           }
 
-             if (x[j] >= max_pos)
-               {
-                 position = MAX (glyph->simple->x_coordinates[pair_start],
-                                 glyph->simple->x_coordinates[pair_end]);
-                 delta = position - max_pos;
-               }
-             else
-               {
-                 position = MIN (glyph->simple->x_coordinates[pair_start],
-                                 glyph->simple->x_coordinates[pair_end]);
-                 delta = position - min_pos;
-               }
+         glyph->simple->x_coordinates[j] = x[j] + delta;
+       }
 
-             glyph->simple->x_coordinates[j] = x[j] + delta;
-           }
+    consider_y:
+
+      /* Now, consider the Y axis.  */
+      min_pos = MIN (y[pair_start], y[pair_end]);
+      max_pos = MAX (y[pair_start], y[pair_end]);
+
+      /* Now see if the current point lies between min and
+        max...
+
+         GX interpolation differs from IUP in one important detail:
+         points are shifted to follow the movement of their reference
+         points if their positions are identical to those of any of
+         their reference points, whereas IUP considers such points to
+         fall within their reference points.  */
+      if (y[j] > min_pos && y[j] < max_pos)
+       {
+         /* Interpolate between min_pos and max_pos.  */
+         ratio = sfnt_div_fixed ((sfnt_sub (y[j], min_pos)
+                                  * 65536),
+                                 (sfnt_sub (max_pos, min_pos)
+                                  * 65536));
+
+         /* Load the current positions of pair_start and pair_end
+            along this axis.  */
+         min_pos = MIN (glyph->simple->y_coordinates[pair_start],
+                        glyph->simple->y_coordinates[pair_end]);
+         max_pos = MAX (glyph->simple->y_coordinates[pair_start],
+                        glyph->simple->y_coordinates[pair_end]);
+
+         /* Lerp in between.  */
+         delta = sfnt_sub (max_pos, min_pos);
+         delta = sfnt_mul_fixed (ratio, delta);
+         glyph->simple->y_coordinates[j] = min_pos + delta;
+       }
+      else
+       {
+         /* ... otherwise, move point j by the delta of the
+            nearest touched point.  */
 
-         /* Now, consider the Y axis.  */
-         min_pos = MIN (y[pair_start], y[pair_end]);
-         max_pos = MAX (y[pair_start], y[pair_end]);
+         /* If min_pos and max_pos are the same, apply
+            pair_start's delta if it is identical to that of
+            pair_end, or apply nothing at all otherwise.  */
 
-         /* Now see if the current point lies between min and
-            max... */
-         if (y[j] >= min_pos && y[j] <= max_pos)
+         if (min_pos == max_pos)
            {
-             /* If min_pos and max_pos are the same, apply
-                pair_start's delta if it is identical to that of
-                pair_end, or apply nothing at all otherwise.  */
+             d1 = (glyph->simple->y_coordinates[pair_start]
+                   - y[pair_start]);
+             d2 = (glyph->simple->y_coordinates[pair_end]
+                   - y[pair_end]);
 
-             if (min_pos == max_pos)
-               {
-                 if ((glyph->simple->y_coordinates[pair_start]
-                      - y[pair_start])
-                     == (glyph->simple->y_coordinates[pair_end]
-                         - y[pair_end]))
-                   glyph->simple->y_coordinates[j]
-                     += (glyph->simple->y_coordinates[pair_start]
-                         - y[pair_start]);
+             if (d1 == d2)
+               glyph->simple->y_coordinates[j] += d1;
 
-                 continue;
-               }
+             goto next;
+           }
 
-             /* Interpolate between min_pos and max_pos.  */
-             ratio = sfnt_div_fixed ((sfnt_sub (y[j], min_pos)
-                                      * 65536),
-                                     (sfnt_sub (max_pos, min_pos)
-                                      * 65536));
-
-             /* Load the current positions of pair_start and pair_end
-                along this axis.  */
-             min_pos = MIN (glyph->simple->y_coordinates[pair_start],
-                            glyph->simple->y_coordinates[pair_end]);
-             max_pos = MAX (glyph->simple->y_coordinates[pair_start],
-                            glyph->simple->y_coordinates[pair_end]);
-
-             /* Lerp in between.  */
-             delta = sfnt_sub (max_pos, min_pos);
-             delta = sfnt_mul_fixed (ratio, delta);
-             glyph->simple->y_coordinates[j] = min_pos + delta;
+         if (y[j] >= max_pos)
+           {
+             position = MAX (glyph->simple->y_coordinates[pair_start],
+                             glyph->simple->y_coordinates[pair_end]);
+             delta = position - max_pos;
            }
          else
            {
-             /* ... otheriwse, move point j by the delta of the
-                nearest touched point.  */
-
-             if (y[j] >= max_pos)
-               {
-                 position = MAX (glyph->simple->y_coordinates[pair_start],
-                                 glyph->simple->y_coordinates[pair_end]);
-                 delta = position - max_pos;
-               }
-             else
-               {
-                 position = MIN (glyph->simple->y_coordinates[pair_start],
-                                 glyph->simple->y_coordinates[pair_end]);
-                 delta = position - min_pos;
-               }
-
-             glyph->simple->y_coordinates[j] = y[j] + delta;
+             position = MIN (glyph->simple->y_coordinates[pair_start],
+                             glyph->simple->y_coordinates[pair_end]);
+             delta = position - min_pos;
            }
+
+         glyph->simple->y_coordinates[j] = y[j] + delta;
        }
 
     next:
-      pair_start = i;
+      j++;
     }
+}
 
-  /* If pair_start is set, then lerp points between it and
-     pair_first.  */
-
-  if (pair_start != (size_t) -1)
-    {
-      j = pair_start + 1;
-
-      if (j > end)
-       j = start;
-
-      pair_end = pair_first;
-
-      while (j != pair_first)
-       {
-         /* Consider the X axis.  Set min_pos and max_pos to the
-            smallest and greatest values along that axis.  */
-         min_pos = MIN (x[pair_start], x[pair_end]);
-         max_pos = MAX (x[pair_start], x[pair_end]);
-
-         /* Now see if the current point lies between min and
-            max... */
-         if (x[j] >= min_pos && x[j] <= max_pos)
-           {
-             /* If min_pos and max_pos are the same, apply
-                pair_start's delta if it is identical to that of
-                pair_end, or apply nothing at all otherwise.  */
+/* Infer point positions for points that have been partially moved
+   within the contour in GLYPH denoted by START and END.  */
 
-             if (min_pos == max_pos)
-               {
-                 if ((glyph->simple->x_coordinates[pair_start]
-                      - x[pair_start])
-                     == (glyph->simple->x_coordinates[pair_end]
-                         - x[pair_end]))
-                   glyph->simple->x_coordinates[j]
-                     += (glyph->simple->x_coordinates[pair_start]
-                         - x[pair_start]);
-
-                 goto next_1;
-               }
+static void
+sfnt_infer_deltas_1 (struct sfnt_glyph *glyph, size_t start,
+                    size_t end, bool *touched, sfnt_fword *x,
+                    sfnt_fword *y)
+{
+  size_t i, pair_start, pair_end, pair_first;
 
-             /* Interpolate between min_pos and max_pos.  */
-             ratio = sfnt_div_fixed ((sfnt_sub (x[j], min_pos)
-                                      * 65536),
-                                     (sfnt_sub (max_pos, min_pos)
-                                      * 65536));
-
-             /* Load the current positions of pair_start and pair_end
-                along this axis.  */
-             min_pos = MIN (glyph->simple->x_coordinates[pair_start],
-                            glyph->simple->x_coordinates[pair_end]);
-             max_pos = MAX (glyph->simple->x_coordinates[pair_start],
-                            glyph->simple->x_coordinates[pair_end]);
-
-             /* Lerp in between.  */
-             delta = sfnt_sub (max_pos, min_pos);
-             delta = sfnt_mul_fixed (ratio, delta);
-             glyph->simple->x_coordinates[j] = min_pos + delta;
-           }
-         else
-           {
-             /* ... otheriwse, move point j by the delta of the
-                nearest touched point.  */
+  pair_start = pair_first = -1;
 
-             if (x[j] >= max_pos)
-               {
-                 position = MAX (glyph->simple->x_coordinates[pair_start],
-                                 glyph->simple->x_coordinates[pair_end]);
-                 delta = position - max_pos;
-               }
-             else
-               {
-                 position = MIN (glyph->simple->x_coordinates[pair_start],
-                                 glyph->simple->x_coordinates[pair_end]);
-                 delta = position - min_pos;
-               }
+  /* Look for pairs of touched points.  */
 
-             glyph->simple->x_coordinates[j] = x[j] + delta;
-           }
+  for (i = start; i <= end; ++i)
+    {
+      if (!touched[i])
+       continue;
 
-         /* Now, consider the Y axis.  */
-         min_pos = MIN (y[pair_start], y[pair_end]);
-         max_pos = MAX (y[pair_start], y[pair_end]);
+      if (pair_start == -1)
+       {
+         pair_first = i;
+         goto next;
+       }
 
-         /* Now see if the current point lies between min and
-            max... */
-         if (y[j] >= min_pos && y[j] <= max_pos)
-           {
-             /* If min_pos and max_pos are the same, apply
-                pair_start's delta if it is identical to that of
-                pair_end, or apply nothing at all otherwise.  */
+      pair_end = i;
 
-             if (min_pos == max_pos)
-               {
-                 if ((glyph->simple->y_coordinates[pair_start]
-                      - y[pair_start])
-                     == (glyph->simple->y_coordinates[pair_end]
-                         - y[pair_end]))
-                   glyph->simple->y_coordinates[j]
-                     += (glyph->simple->y_coordinates[pair_start]
-                         - y[pair_start]);
-
-                 goto next_1;
-               }
+      /* pair_start to pair_end are now a pair of points whose
+        intermediates should be interpolated.  */
+      sfnt_infer_deltas_2 (glyph, pair_start, pair_end,
+                          start, end, x, y);
 
-             /* Interpolate between min_pos and max_pos.  */
-             ratio = sfnt_div_fixed ((sfnt_sub (y[j], min_pos)
-                                      * 65536),
-                                     (sfnt_sub (max_pos, min_pos)
-                                      * 65536));
-
-             /* Load the current positions of pair_start and pair_end
-                along this axis.  */
-             min_pos = MIN (glyph->simple->y_coordinates[pair_start],
-                            glyph->simple->y_coordinates[pair_end]);
-             max_pos = MAX (glyph->simple->y_coordinates[pair_start],
-                            glyph->simple->y_coordinates[pair_end]);
-
-             /* Lerp in between.  */
-             delta = sfnt_sub (max_pos, min_pos);
-             delta = sfnt_mul_fixed (ratio, delta);
-             glyph->simple->y_coordinates[j] = min_pos + delta;
-           }
-         else
-           {
-             /* ... otheriwse, move point j by the delta of the
-                nearest touched point.  */
+    next:
+      pair_start = i;
+    }
 
-             if (y[j] >= max_pos)
-               {
-                 position = MAX (glyph->simple->y_coordinates[pair_start],
-                                 glyph->simple->y_coordinates[pair_end]);
-                 delta = position - max_pos;
-               }
-             else
-               {
-                 position = MIN (glyph->simple->y_coordinates[pair_start],
-                                 glyph->simple->y_coordinates[pair_end]);
-                 delta = position - min_pos;
-               }
+  /* If pair_start is set, then lerp points between it and
+     pair_first.  */
 
-             glyph->simple->y_coordinates[j] = y[j] + delta;
-           }
+  if (pair_start != (size_t) -1)
+    {
+      pair_end = pair_first;
 
-       next_1:
-         j++;
-         if (j > end)
-           j = start;
-       }
+      /* pair_start to pair_end are now a pair of points whose
+        intermediates should be interpolated.  */
+      sfnt_infer_deltas_2 (glyph, pair_start, pair_end,
+                          start, end, x, y);
     }
 }
 
@@ -14554,7 +15785,7 @@ sfnt_infer_deltas (struct sfnt_glyph *glyph, bool 
*touched,
    of one or two coordinates for each axis.  Each such list is
    referred to as a ``tuple''.
 
-   The deltas, one for each point, are multipled by the normalized
+   The deltas, one for each point, are multiplied by the normalized
    value of each axis and applied to those points for each tuple that
    is found to be applicable.
 
@@ -14845,14 +16076,20 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, 
sfnt_glyph id,
                                     * glyph->simple->number_of_points);
 
              original_y = original_x + glyph->simple->number_of_points;
-             memcpy (original_x, glyph->simple->x_coordinates,
-                     (sizeof *original_x
-                      * glyph->simple->number_of_points));
-             memcpy (original_y, glyph->simple->y_coordinates,
-                     (sizeof *original_y
-                      * glyph->simple->number_of_points));
            }
 
+         /* The array of original coordinates should reflect the
+            state of the glyph immediately before deltas from this
+            tuple are applied, in contrast to the state before any
+            deltas are applied.  */
+
+         memcpy (original_x, glyph->simple->x_coordinates,
+                 (sizeof *original_x
+                  * glyph->simple->number_of_points));
+         memcpy (original_y, glyph->simple->y_coordinates,
+                 (sizeof *original_y
+                  * glyph->simple->number_of_points));
+
          memset (touched, 0, (sizeof *touched
                               * glyph->simple->number_of_points));
 
@@ -15356,7 +16593,7 @@ sfnt_vary_interpreter (struct sfnt_interpreter 
*interpreter,
 
          /* Multiply the delta by the interpreter scale factor and
             then the tuple scale factor.  */
-         delta = sfnt_mul_f26dot6_fixed (variation->deltas[j] * 64,
+         delta = sfnt_mul_f26dot6_fixed (variation->deltas[j],
                                          interpreter->scale);
          delta = sfnt_mul_fixed_round (delta, scale);
 
@@ -15622,9 +16859,9 @@ sfnt_test_get_metrics (sfnt_glyph glyph, struct 
sfnt_glyph_metrics *metrics,
   struct sfnt_test_dcontext *tables;
 
   tables = dcontext;
-  return sfnt_lookup_glyph_metrics (glyph, -1, metrics,
+  return sfnt_lookup_glyph_metrics (glyph, metrics,
                                    tables->hmtx, tables->hhea,
-                                   NULL, tables->maxp);
+                                   tables->maxp);
 }
 
 static void
@@ -15934,7 +17171,7 @@ sfnt_x_raster (struct sfnt_raster **rasters,
          ascent = sfnt_mul_fixed (hhea->ascent * 65536,
                                   scale) / 65536;
 
-         origin = 0;
+         origin = 5;
 
          for (i = 0; i < nrasters; ++i)
            {
@@ -16373,13 +17610,13 @@ sfnt_check_ssw (struct sfnt_interpreter *interpreter,
     }
 
   if (interpreter->state.single_width_value
-      != sfnt_mul_f26dot6_fixed (-64, interpreter->scale))
+      != sfnt_mul_f26dot6_fixed (-1, interpreter->scale))
     {
       fprintf (stderr, "failed, got %d at scale %d,"
               " expected %d\n",
               interpreter->state.single_width_value,
               interpreter->scale,
-              sfnt_mul_f26dot6_fixed (-64, interpreter->scale));
+              sfnt_mul_f26dot6_fixed (-1, interpreter->scale));
       return;
     }
 
@@ -17383,13 +18620,13 @@ static struct sfnt_interpreter_test all_tests[] =
       "SLOOP",
       /* PUSHB[0] 2
         SLOOP[]
-        PUSHB[0] 0
+        PUSHW[0] 255 255 (-1)
         SLOOP[] */
       (unsigned char []) { 0xb0, 2,
                           0x17,
-                          0xb0, 0,
+                          0xb8, 255, 255,
                           0x17, },
-      6,
+      7,
       NULL,
       sfnt_check_sloop,
     },
@@ -19182,7 +20419,8 @@ sfnt_identify_instruction (struct sfnt_interpreter 
*interpreter)
       return buffer;
     }
 
-  if (exec_fpgm->instructions
+  if (exec_fpgm
+      && exec_fpgm->instructions
       && where >= exec_fpgm->instructions
       && where < (exec_fpgm->instructions
                  + exec_fpgm->num_instructions))
@@ -19196,6 +20434,11 @@ sfnt_identify_instruction (struct sfnt_interpreter 
*interpreter)
   return buffer;
 }
 
+/* Function called to rasterize a glyph outline.  */
+#define TYPE struct sfnt_glyph_outline *
+static struct sfnt_raster *(*test_raster_glyph_outline) (TYPE);
+#undef TYPE
+
 static void
 sfnt_verbose (struct sfnt_interpreter *interpreter)
 {
@@ -19205,6 +20448,7 @@ sfnt_verbose (struct sfnt_interpreter *interpreter)
   unsigned char opcode;
   const char *name;
   static unsigned int instructions;
+  sfnt_fixed advance;
 
   /* Build a temporary outline containing the values of the
      interpreter's glyph zone.  */
@@ -19218,7 +20462,7 @@ sfnt_verbose (struct sfnt_interpreter *interpreter)
       temp.y_points = interpreter->glyph_zone->y_current;
       temp.flags = interpreter->glyph_zone->flags;
 
-      outline = sfnt_build_instructed_outline (&temp);
+      outline = sfnt_build_instructed_outline (&temp, &advance);
 
       if (!outline)
        return;
@@ -19229,7 +20473,7 @@ sfnt_verbose (struct sfnt_interpreter *interpreter)
              sfnt_coerce_fixed (outline->xmax),
              sfnt_coerce_fixed (outline->ymax));
 
-      raster = sfnt_raster_glyph_outline (outline);
+      raster = (*test_raster_glyph_outline) (outline);
 
       if (raster)
        sfnt_test_raster (raster, NULL, 0);
@@ -19433,6 +20677,7 @@ main (int argc, char **argv)
   struct sfnt_instance *instance;
   struct sfnt_blend blend;
   struct sfnt_metrics_distortion distortion;
+  sfnt_fixed advance;
 
   if (argc < 2)
     return 1;
@@ -19446,12 +20691,24 @@ main (int argc, char **argv)
       if (!interpreter)
        abort ();
 
+      if (getenv ("SFNT_VERBOSE"))
+       {
+         interpreter->run_hook = sfnt_verbose;
+         interpreter->push_hook = sfnt_push_hook;
+         interpreter->pop_hook = sfnt_pop_hook;
+       }
+
       for (i = 0; i < ARRAYELTS (all_tests); ++i)
        sfnt_run_interpreter_test (&all_tests[i], interpreter);
 
       exit (0);
     }
 
+  if (getenv ("SFNT_EXACT_SCALING"))
+    test_raster_glyph_outline = sfnt_raster_glyph_outline_exact;
+  else
+    test_raster_glyph_outline = sfnt_raster_glyph_outline;
+
   fd = open (argv[1], O_RDONLY);
 
   if (fd < 0)
@@ -19543,8 +20800,8 @@ main (int argc, char **argv)
       return 1;
     }
 
-#define FANCY_PPEM 18
-#define EASY_PPEM  18
+#define FANCY_PPEM 12
+#define EASY_PPEM  12
 
   interpreter = NULL;
   head = sfnt_read_head_table (fd, font);
@@ -19771,11 +21028,11 @@ main (int argc, char **argv)
          if (instance && gvar)
            sfnt_vary_simple_glyph (&blend, code, glyph,
                                    &distortion);
+         else
+           memset (&distortion, 0, sizeof distortion);
 
-         if (sfnt_lookup_glyph_metrics (code, -1,
-                                        &metrics,
-                                        hmtx, hhea,
-                                        head, maxp))
+         if (sfnt_lookup_glyph_metrics (code, &metrics,
+                                        hmtx, hhea, maxp))
            exit (4);
 
          interpreter->state = state;
@@ -19788,14 +21045,17 @@ main (int argc, char **argv)
              exit (5);
            }
 
-         outline = sfnt_build_instructed_outline (value);
+         outline = sfnt_build_instructed_outline (value, &advance);
+         advances[i] = (advance / 65536);
+
+         fprintf (stderr, "advance: %d\n", advances[i]);
 
          if (!outline)
            exit (6);
 
          xfree (value);
 
-         raster = sfnt_raster_glyph_outline (outline);
+         raster = (*test_raster_glyph_outline) (outline);
 
          if (!raster)
            exit (7);
@@ -19803,8 +21063,6 @@ main (int argc, char **argv)
          xfree (outline);
 
          rasters[i] = raster;
-         advances[i] = (sfnt_mul_fixed (metrics.advance, scale)
-                        + sfnt_mul_fixed (distortion.advance, scale));
        }
 
       sfnt_x_raster (rasters, advances, length, hhea, scale);
@@ -19934,6 +21192,16 @@ main (int argc, char **argv)
       interpreter = sfnt_make_interpreter (maxp, cvt, head,
                                           fvar, FANCY_PPEM,
                                           FANCY_PPEM);
+
+      if (getenv ("SFNT_DEBUG"))
+       interpreter->run_hook = sfnt_run_hook;
+      else if (getenv ("SFNT_VERBOSE"))
+       {
+         interpreter->run_hook = sfnt_verbose;
+         interpreter->push_hook = sfnt_push_hook;
+         interpreter->pop_hook = sfnt_pop_hook;
+       }
+
       state = interpreter->state;
 
       if (instance && gvar)
@@ -20033,7 +21301,15 @@ main (int argc, char **argv)
                    printf ("variation failed!\n");
                }
 
-             if (sfnt_decompose_glyph (glyph, sfnt_test_move_to,
+             if (sfnt_lookup_glyph_metrics (code, &metrics,
+                                            hmtx, hhea, maxp))
+               {
+                 printf ("metrics lookup failure");
+                 memset (&metrics, 0, sizeof metrics);
+               }
+
+             if (sfnt_decompose_glyph (glyph, &metrics,
+                                       sfnt_test_move_to,
                                        sfnt_test_line_to,
                                        sfnt_test_curve_to,
                                        sfnt_test_get_glyph,
@@ -20042,10 +21318,8 @@ main (int argc, char **argv)
                                        &dcontext))
                printf ("decomposition failure\n");
 
-             if (sfnt_lookup_glyph_metrics (code, -1,
-                                            &metrics,
-                                            hmtx, hhea,
-                                            head, maxp))
+             if (sfnt_lookup_glyph_metrics (code, &metrics,
+                                            hmtx, hhea, maxp))
                {
                  printf ("metrics lookup failure");
                  memset (&metrics, 0, sizeof metrics);
@@ -20069,7 +21343,7 @@ main (int argc, char **argv)
                  fprintf (stderr, "outline origin, rbearing: %"
                           PRIi32" %"PRIi32"\n",
                           outline->origin,
-                          outline->ymax - outline->origin);
+                          outline->xmax - outline->origin);
                  sfnt_test_max = outline->ymax - outline->ymin;
 
                  for (i = 0; i < outline->outline_used; i++)
@@ -20100,10 +21374,10 @@ main (int argc, char **argv)
 
                  clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start);
 
-                 for (i = 0; i < 120; ++i)
+                 for (i = 0; i < 12800; ++i)
                    {
                      xfree (raster);
-                     raster = sfnt_raster_glyph_outline (outline);
+                     raster = (*test_raster_glyph_outline) (outline);
                    }
 
                  clock_gettime (CLOCK_THREAD_CPUTIME_ID, &end);
@@ -20125,29 +21399,24 @@ main (int argc, char **argv)
 
              if (hmtx && head)
                {
-                 if (!sfnt_lookup_glyph_metrics (code, EASY_PPEM,
-                                                 &metrics,
-                                                 hmtx, hhea,
-                                                 head, maxp))
-                   printf ("lbearing, advance: %g, %g\n",
-                           sfnt_coerce_fixed (metrics.lbearing),
-                           sfnt_coerce_fixed (metrics.advance));
+                 sfnt_scale_metrics (&metrics, scale);
+                 printf ("scaled lbearing, advance: %g, %g\n",
+                         sfnt_coerce_fixed (metrics.lbearing),
+                         sfnt_coerce_fixed (metrics.advance));
 
-                 if (interpreter)
+                 if (!sfnt_lookup_glyph_metrics (code, &metrics, hmtx,
+                                                 hhea, maxp))
                    {
-                     if (getenv ("SFNT_DEBUG"))
-                       interpreter->run_hook = sfnt_run_hook;
-                     else if (getenv ("SFNT_VERBOSE"))
-                       {
-                         interpreter->run_hook = sfnt_verbose;
-                         interpreter->push_hook = sfnt_push_hook;
-                         interpreter->pop_hook = sfnt_pop_hook;
-                       }
+                     sfnt_scale_metrics (&metrics, scale);
+                     printf ("lbearing, advance: %g, %g\n",
+                             sfnt_coerce_fixed (metrics.lbearing),
+                             sfnt_coerce_fixed (metrics.advance));
+                   }
 
-                     if (!sfnt_lookup_glyph_metrics (code, -1,
-                                                     &metrics,
-                                                     hmtx, hhea,
-                                                     head, maxp))
+                 if (interpreter)
+                   {
+                     if (!sfnt_lookup_glyph_metrics (code, &metrics,
+                                                     hmtx, hhea, maxp))
                        {
                          printf ("interpreting glyph\n");
                          interpreter->state = state;
@@ -20183,12 +21452,24 @@ main (int argc, char **argv)
                              printf ("rasterizing instructed outline\n");
                              if (outline)
                                xfree (outline);
-                             outline = sfnt_build_instructed_outline (value);
+                             outline
+                               = sfnt_build_instructed_outline (value,
+                                                                &advance);
                              xfree (value);
 
+#define LB outline->xmin - outline->origin
+#define RB outline->xmax - outline->origin
+                             printf ("instructed advance, lb, rb: %g %g %g\n",
+                                     sfnt_coerce_fixed (advance),
+                                     sfnt_coerce_fixed (LB),
+                                     sfnt_coerce_fixed (RB));
+#undef LB
+#undef RB
+
                              if (outline)
                                {
-                                 raster = sfnt_raster_glyph_outline (outline);
+                                 raster
+                                   = (*test_raster_glyph_outline) (outline);
 
                                  if (raster)
                                    {
@@ -20214,7 +21495,8 @@ main (int argc, char **argv)
              printf ("time spent building edges: %lld sec %ld nsec\n",
                      (long long) sub1.tv_sec, sub1.tv_nsec);
              printf ("time spent rasterizing: %lld sec %ld nsec\n",
-                     (long long) sub2.tv_sec / 120, sub2.tv_nsec / 120);
+                     (long long) sub2.tv_sec / 12800,
+                     sub2.tv_nsec / 12800);
 
              xfree (outline);
            }
diff --git a/src/sfnt.h b/src/sfnt.h
index f6ab6a6eebd..444b1dfe427 100644
--- a/src/sfnt.h
+++ b/src/sfnt.h
@@ -1,6 +1,6 @@
 /* sfnt format font support for GNU Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -123,6 +123,7 @@ typedef int16_t sfnt_fword;
 typedef uint16_t sfnt_ufword;
 
 #define sfnt_coerce_fixed(fixed) ((sfnt_fixed) (fixed) / 65535.0)
+#define sfnt_fixed_float(fixed)  ((sfnt_fixed) (fixed) / 65535.0f)
 
 typedef unsigned int sfnt_glyph;
 typedef unsigned int sfnt_char;
@@ -247,7 +248,7 @@ enum sfnt_macintosh_platform_specific_id
     SFNT_MACINTOSH_GREEK              = 6,
     SFNT_MACINTOSH_RUSSIAN            = 7,
     SFNT_MACINTOSH_RSYMBOL            = 8,
-    SFNT_MACINTOSH_DEVANGARI          = 9,
+    SFNT_MACINTOSH_DEVANAGARI         = 9,
     SFNT_MACINTOSH_GURMUKHI           = 10,
     SFNT_MACINTOSH_GUJARATI           = 11,
     SFNT_MACINTOSH_ORIYA              = 12,
@@ -778,7 +779,7 @@ struct sfnt_edge
   /* X position, top and bottom of edges.  */
   sfnt_fixed x, top, bottom;
 
-  /* Amount to move X by upon each change of Y.  */
+  /* Amount to move X by upon each change of Y, and vice versa.  */
   sfnt_fixed step_x;
 };
 
@@ -1283,7 +1284,7 @@ struct sfnt_gvar_table
   unsigned char *glyph_variation_data;
 };
 
-/* Structure repesenting a set of axis coordinates and their
+/* Structure representing a set of axis coordinates and their
    normalized equivalents.
 
    To use this structure, call
@@ -1454,6 +1455,7 @@ struct sfnt_post_table
 
 
 #define SFNT_CEIL_FIXED(fixed) (((fixed) + 0177777) & 037777600000)
+#define SFNT_ROUND_FIXED(fixed) (((fixed) + 0100000) & 037777600000)
 #define SFNT_FLOOR_FIXED(fixed) ((fixed) & 037777600000)
 
 
@@ -1511,6 +1513,7 @@ extern void sfnt_prepare_raster (struct sfnt_raster *,
 
 #define PROTOTYPE struct sfnt_glyph_outline *
 extern struct sfnt_raster *sfnt_raster_glyph_outline (PROTOTYPE);
+extern struct sfnt_raster *sfnt_raster_glyph_outline_exact (PROTOTYPE);
 #undef PROTOTYPE
 
 #define PROTOTYPE                      \
@@ -1521,11 +1524,10 @@ extern struct sfnt_raster *sfnt_raster_glyph_outline 
(PROTOTYPE);
 extern struct sfnt_hmtx_table *sfnt_read_hmtx_table (PROTOTYPE);
 #undef PROTOTYPE
 
-extern int sfnt_lookup_glyph_metrics (sfnt_glyph, int,
+extern int sfnt_lookup_glyph_metrics (sfnt_glyph,
                                      struct sfnt_glyph_metrics *,
                                      struct sfnt_hmtx_table *,
                                      struct sfnt_hhea_table *,
-                                     struct sfnt_head_table *,
                                      struct sfnt_maxp_table *);
 
 extern void sfnt_scale_metrics (struct sfnt_glyph_metrics *,
@@ -1757,6 +1759,10 @@ struct sfnt_interpreter_zone
 
   /* Pointer to the flags associated with this data.  */
   unsigned char *flags;
+
+  /* If this structure was produced from a simple glyph, pointer to
+     the simple glyph itself.  NULL otherwise.  */
+  struct sfnt_simple_glyph *simple;
 };
 
 enum
@@ -2100,7 +2106,7 @@ extern const char *sfnt_interpret_control_value_program 
(PROTOTYPE);
 
 #undef PROTOTYPE
 
-#define PROTOTYPE struct sfnt_instructed_outline *
+#define PROTOTYPE struct sfnt_instructed_outline *, sfnt_fixed *
 
 extern struct sfnt_glyph_outline *sfnt_build_instructed_outline (PROTOTYPE);
 
diff --git a/src/sfntfont-android.c b/src/sfntfont-android.c
index e49615210eb..94aedd0cd66 100644
--- a/src/sfntfont-android.c
+++ b/src/sfntfont-android.c
@@ -1,6 +1,6 @@
 /* sfnt format font driver for Android.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -78,7 +78,7 @@ static size_t max_scanline_buffer_size;
     {                                                          \
       size_t _size;                                            \
                                                                \
-      if (INT_MULTIPLY_WRAPV (height, stride, &_size))         \
+      if (ckd_mul (&_size, height, stride))                    \
        memory_full (SIZE_MAX);                                 \
                                                                \
       if (_size < MAX_ALLOCA)                                  \
@@ -112,7 +112,7 @@ static size_t max_scanline_buffer_size;
       size_t _size;                                            \
       void *_temp;                                             \
                                                                \
-      if (INT_MULTIPLY_WRAPV (height, stride, &_size))         \
+      if (ckd_mul (&_size, height, stride))                    \
        memory_full (SIZE_MAX);                                 \
                                                                \
       if (_size > scanline_buffer.buffer_size)                 \
diff --git a/src/sfntfont.c b/src/sfntfont.c
index 68e850779fc..860fc446184 100644
--- a/src/sfntfont.c
+++ b/src/sfntfont.c
@@ -1,6 +1,6 @@
 /* sfnt format font driver for GNU Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -1348,7 +1348,7 @@ sfntfont_charset_for_cmap (struct 
sfnt_cmap_encoding_subtable subtable)
    subtable in *SUBTABLE upon success, NULL otherwise.
 
    If FORMAT14 is non-NULL, return any associated format 14 variation
-   selection context in *FORMAT14 should the selected charcter map be
+   selection context in *FORMAT14 should the selected character map be
    a Unicode character map.  */
 
 static struct sfnt_cmap_encoding_subtable_data *
@@ -1371,7 +1371,7 @@ sfntfont_select_cmap (struct sfnt_cmap_table *cmap,
          if (!format14)
            return data[i];
 
-         /* Search for a correspoinding format 14 character map.
+         /* Search for a corresponding format 14 character map.
             This is used in conjunction with the selected character
             map to map variation sequences.  */
 
@@ -1400,7 +1400,7 @@ sfntfont_select_cmap (struct sfnt_cmap_table *cmap,
          if (!format14)
            return data[i];
 
-         /* Search for a correspoinding format 14 character map.
+         /* Search for a corresponding format 14 character map.
             This is used in conjunction with the selected character
             map to map variation sequences.  */
 
@@ -1939,13 +1939,51 @@ sfntfont_desc_to_entity (struct sfnt_font_desc *desc, 
int instance)
   return entity;
 }
 
+/* Return whether fewer fields inside the font entity A are set than
+   there are set inside the font entity B.  */
+
+static Lisp_Object
+sfntfont_compare_font_entities (Lisp_Object a, Lisp_Object b)
+{
+  ptrdiff_t count_a, count_b, i;
+
+  count_a = 0;
+  count_b = 0;
+
+  for (i = 0; i < FONT_ENTITY_MAX; ++i)
+    {
+      if (!NILP (AREF (a, i)))
+       count_a++;
+    }
+
+  for (i = 0; i < FONT_ENTITY_MAX; ++i)
+    {
+      if (!NILP (AREF (b, i)))
+       count_b++;
+    }
+
+  return count_a < count_b ? Qt : Qnil;
+}
+
+/* Function that compares two font entities to return whether fewer
+   fields are set within the first than in the second.  */
+
+static union Aligned_Lisp_Subr Scompare_font_entities =
+  {
+    {
+      { PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS), },
+      { .a2 = sfntfont_compare_font_entities, },
+      2, 2, "sfntfont_compare_font_entities", {0}, lisp_h_Qnil,
+    },
+  };
+
 /* Return a list of font-entities matching the specified
    FONT_SPEC.  */
 
 Lisp_Object
 sfntfont_list (struct frame *f, Lisp_Object font_spec)
 {
-  Lisp_Object matching, tem;
+  Lisp_Object matching, tem, compare_font_entities;
   struct sfnt_font_desc *desc;
   int i, rc, instances[100];
 
@@ -1982,9 +2020,16 @@ sfntfont_list (struct frame *f, Lisp_Object font_spec)
                              matching);
        }
     }
-
   unblock_input ();
 
+  /* Sort matching by the number of fields set inside each element, so
+     that values of FONT_SPECs that leave a number of fields
+     unspecified will yield a list with the closest matches (that is
+     to say, those whose fields are precisely as specified by the
+     caller) ordered first.  */
+
+  XSETSUBR (compare_font_entities, &Scompare_font_entities.s);
+  matching = Fsort (matching, compare_font_entities);
   return matching;
 }
 
@@ -2115,9 +2160,8 @@ sfntfont_get_metrics (sfnt_glyph glyph, struct 
sfnt_glyph_metrics *metrics,
   struct sfntfont_get_glyph_outline_dcontext *tables;
 
   tables = dcontext;
-  return sfnt_lookup_glyph_metrics (glyph, -1, metrics,
-                                   tables->hmtx, tables->hhea,
-                                   NULL, tables->maxp);
+  return sfnt_lookup_glyph_metrics (glyph, metrics, tables->hmtx,
+                                   tables->hhea, tables->maxp);
 }
 
 /* Dereference the outline OUTLINE.  Free it once refcount reaches
@@ -2182,6 +2226,7 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
   const char *error;
   struct sfnt_glyph_metrics temp;
   struct sfnt_metrics_distortion distortion;
+  sfnt_fixed advance;
 
   start = cache->next;
   distortion.advance = 0;
@@ -2252,13 +2297,9 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
 
   /* Now load the glyph's unscaled metrics into TEMP.  */
 
-  if (sfnt_lookup_glyph_metrics (glyph_code, -1, &temp, hmtx, hhea,
-                                head, maxp))
+  if (sfnt_lookup_glyph_metrics (glyph_code, &temp, hmtx, hhea, maxp))
     goto fail;
 
-  /* Add the advance width distortion.  */
-  temp.advance += distortion.advance;
-
   if (interpreter)
     {
       if (glyph->simple)
@@ -2284,34 +2325,50 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
 
       if (!error)
        {
-         outline = sfnt_build_instructed_outline (value);
+         /* Now record the advance with that measured from the
+            phantom points within the instructed glyph outline, and
+            subsequently replace it once metrics are scaled.  */
+
+         outline = sfnt_build_instructed_outline (value,
+                                                  &advance);
          xfree (value);
+
+         if (outline)
+           {
+             /* Save the new advance width.  This advance width is
+                rounded again, as the instruction code executed might
+                have moved both phantom points such that they no
+                longer measure a fractional distance.  */
+             temp.advance = SFNT_ROUND_FIXED (advance);
+
+             /* Finally, adjust the left side bearing of the glyph
+                metrics by the origin point of the outline, should a
+                transformation have been applied by either
+                instruction code or glyph variation.  The left side
+                bearing is the distance from the origin point to the
+                left most point on the X axis.  */
+             temp.lbearing
+               = SFNT_FLOOR_FIXED (outline->xmin - outline->origin);
+           }
        }
     }
 
   if (!outline)
     {
-      if (!interpreter)
-       outline = sfnt_build_glyph_outline (glyph, scale,
-                                           &temp,
-                                           sfntfont_get_glyph,
-                                           sfntfont_free_glyph,
-                                           sfntfont_get_metrics,
-                                           &dcontext);
-      else
-       outline = sfnt_build_glyph_outline (glyph, scale,
-                                           &temp,
-                                           sfntfont_get_glyph,
-                                           sfntfont_free_glyph,
-                                           sfntfont_get_metrics,
-                                           &dcontext);
+      /* Build the outline.  This will apply GX offsets within *GLYPH
+        to TEMP.  */
+      outline = sfnt_build_glyph_outline (glyph, scale,
+                                         &temp,
+                                         sfntfont_get_glyph,
+                                         sfntfont_free_glyph,
+                                         sfntfont_get_metrics,
+                                         &dcontext);
+
+      /* At this point, the glyph metrics are unscaled.  Scale them
+        up.  If INTERPRETER is set, use the scale placed within.  */
+      sfnt_scale_metrics (&temp, scale);
     }
 
-  /* At this point, the glyph metrics are unscaled.  Scale them up.
-     If INTERPRETER is set, use the scale placed within.  */
-
-  sfnt_scale_metrics (&temp, scale);
-
  fail:
 
   xfree (glyph);
@@ -2319,13 +2376,6 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
   if (!outline)
     return NULL;
 
-  if (index != -1)
-    /* Finally, adjust the left side bearing of the glyph metrics by
-       the origin point of the outline, should a distortion have been
-       applied.  The left side bearing is the distance from the origin
-       point to the left most point on the X axis.  */
-    temp.lbearing = outline->xmin - outline->origin;
-
   start = xmalloc (sizeof *start);
   start->glyph = glyph_code;
   start->outline = outline;
@@ -2444,7 +2494,11 @@ sfntfont_get_glyph_raster (sfnt_glyph glyph_code,
     }
 
   /* Not already cached.  Raster the outline.  */
-  raster = sfnt_raster_glyph_outline (outline);
+
+  if (!sfnt_raster_glyphs_exactly)
+    raster = sfnt_raster_glyph_outline (outline);
+  else
+    raster = sfnt_raster_glyph_outline_exact (outline);
 
   if (!raster)
     return NULL;
@@ -2631,16 +2685,23 @@ sfntfont_lookup_glyph (struct sfnt_font_info 
*font_info, int c)
   return glyph;
 }
 
+static int sfntfont_measure_pcm (struct sfnt_font_info *, sfnt_glyph,
+                                struct font_metrics *);
+
 /* Probe and set FONT_INFO->font.average_width,
    FONT_INFO->font.space_width, and FONT_INFO->font.min_width
-   according to the tables contained therein.  */
+   according to the tables contained therein.
+
+   As this function generates outlines for all glyphs, outlines for
+   all ASCII characters will be entered into the outline cache as
+   well.  */
 
 static void
 sfntfont_probe_widths (struct sfnt_font_info *font_info)
 {
   int i, num_characters, total_width;
   sfnt_glyph glyph;
-  struct sfnt_glyph_metrics metrics;
+  struct font_metrics pcm;
 
   num_characters = 0;
   total_width = 0;
@@ -2659,29 +2720,27 @@ sfntfont_probe_widths (struct sfnt_font_info *font_info)
       if (!glyph)
        continue;
 
-      /* Now look up the metrics of this glyph.  */
-      if (sfnt_lookup_glyph_metrics (glyph, font_info->font.pixel_size,
-                                    &metrics, font_info->hmtx,
-                                    font_info->hhea, font_info->head,
-                                    font_info->maxp))
+      /* Now look up the metrics of this glyph.  Data from the metrics
+        table doesn't fit the bill, since variations and instruction
+        code is not applied to it.  */
+      if (sfntfont_measure_pcm (font_info, glyph, &pcm))
        continue;
 
       /* Increase the number of characters.  */
       num_characters++;
 
       /* Add the advance to total_width.  */
-      total_width += SFNT_CEIL_FIXED (metrics.advance) / 65536;
+      total_width += pcm.width;
 
       /* Update min_width if it hasn't been set yet or is wider.  */
       if (font_info->font.min_width == 1
-         || font_info->font.min_width > metrics.advance / 65536)
-       font_info->font.min_width = metrics.advance / 65536;
+         || font_info->font.min_width > pcm.width)
+       font_info->font.min_width = pcm.width;
 
       /* If i is the space character, set the space width.  Make sure
         to round this up.  */
       if (i == 32)
-       font_info->font.space_width
-         = SFNT_CEIL_FIXED (metrics.advance) / 65536;
+       font_info->font.space_width = pcm.width;
     }
 
   /* Now, if characters were found, set average_width.  */
@@ -3269,9 +3328,6 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
 
   ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
 
-  /* Find out the minimum, maximum and average widths.  */
-  sfntfont_probe_widths (font_info);
-
   /* Clear various offsets.  */
   font_info->font.baseline_offset = 0;
   font_info->font.relative_compose = 0;
@@ -3361,6 +3417,10 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
     }
 
  cancel_blend:
+
+  /* Find out the minimum, maximum and average widths.  */
+  sfntfont_probe_widths (font_info);
+
   /* Calculate the xfld name.  */
   font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil, Qt);
 
@@ -3474,12 +3534,12 @@ sfntfont_measure_pcm (struct sfnt_font_info *font, 
sfnt_glyph glyph,
   if (!outline)
     return 1;
 
-  /* Round the left side bearing downwards.  */
-  pcm->lbearing = SFNT_FLOOR_FIXED (metrics.lbearing) / 65536;
+  /* The left side bearing has already been floored.  */
+  pcm->lbearing = metrics.lbearing / 65536;
   pcm->rbearing = SFNT_CEIL_FIXED (outline->xmax) / 65536;
 
-  /* Round the advance, ascent and descent upwards.  */
-  pcm->width = SFNT_CEIL_FIXED (metrics.advance) / 65536;
+  /* The advance is already rounded; ceil the ascent and descent.  */
+  pcm->width = metrics.advance / 65536;
   pcm->ascent = SFNT_CEIL_FIXED (outline->ymax) / 65536;
   pcm->descent = SFNT_CEIL_FIXED (-outline->ymin) / 65536;
 
@@ -3683,7 +3743,7 @@ sfntfont_draw (struct glyph_string *s, int from, int to,
       if (s->padding_p)
        current_x += 1;
       else
-       current_x += SFNT_CEIL_FIXED (metrics.advance) / 65536;
+       current_x += metrics.advance / 65536;
     }
 
   /* Call the window system function to put the glyphs to the
@@ -4116,6 +4176,13 @@ eliminating artifacts and chance effects consequent upon 
the direct
 upscaling of glyph outline data.  Instruction code is occasionally
 incompatible with Emacs and must be disregarded.  */);
   Vsfnt_uninstructable_family_regexp = Qnil;
+
+  DEFVAR_BOOL ("sfnt-raster-glyphs-exactly", sfnt_raster_glyphs_exactly,
+    doc: /* How font glyph outlines should be converted to graphics.
+If non-nil, glyphs will be displayed in a more precise manner, at the
+cost of performance on devices where floating-point math operations
+are slow.  */);
+  sfnt_raster_glyphs_exactly = true;
 }
 
 void
diff --git a/src/sfntfont.h b/src/sfntfont.h
index 28267cdb1d6..0e57ee35028 100644
--- a/src/sfntfont.h
+++ b/src/sfntfont.h
@@ -1,6 +1,6 @@
 /* sfnt format font driver for GNU Emacs.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/sheap.c b/src/sheap.c
index 9ea0d91ef75..bab70c4e343 100644
--- a/src/sheap.c
+++ b/src/sheap.c
@@ -1,7 +1,7 @@
 /* simulate `sbrk' with an array in .bss, for `unexec' support for Cygwin;
    complete rewrite of xemacs Cygwin `unexec' code
 
-   Copyright (C) 2004-2023 Free Software Foundation, Inc.
+   Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/sheap.h b/src/sheap.h
index b62adf4318f..92f7ba5e857 100644
--- a/src/sheap.h
+++ b/src/sheap.h
@@ -1,6 +1,6 @@
 /* Static heap allocation for GNU Emacs.
 
-Copyright 2016-2023 Free Software Foundation, Inc.
+Copyright 2016-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/sort.c b/src/sort.c
index 706c057dab0..2f98bfa648c 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -1,6 +1,6 @@
 /* Timsort for sequences.
 
-Copyright (C) 2022-2023 Free Software Foundation, Inc.
+Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -946,8 +946,7 @@ tim_sort (Lisp_Object predicate, Lisp_Object *seq, const 
ptrdiff_t length)
     /* If the run is short, extend it to min(minrun, nremaining).  */
     if (n < minrun)
       {
-       const ptrdiff_t force = nremaining <= minrun ?
-         nremaining : minrun;
+       const ptrdiff_t force = min (nremaining, minrun);
        binarysort (&ms, lo, lo + force, lo + n);
        n = force;
       }
diff --git a/src/sound.c b/src/sound.c
index 9c023725da0..004015fc936 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -1,6 +1,6 @@
 /* sound.c -- sound support.
 
-Copyright (C) 1998-1999, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1998-1999, 2001-2024 Free Software Foundation, Inc.
 
 Author: Gerd Moellmann <gerd@gnu.org>
 
diff --git a/src/sqlite.c b/src/sqlite.c
index 7135cc672bc..7a018b28aa4 100644
--- a/src/sqlite.c
+++ b/src/sqlite.c
@@ -1,6 +1,6 @@
 /* Support for accessing SQLite databases.
 
-Copyright (C) 2021-2023 Free Software Foundation, Inc.
+Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/syntax.c b/src/syntax.c
index 0cac923bba7..a4ad61328e6 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -1,5 +1,5 @@
 /* GNU Emacs routines to deal with syntax tables; also word and list parsing.
-   Copyright (C) 1985, 1987, 1993-1995, 1997-1999, 2001-2023 Free
+   Copyright (C) 1985, 1987, 1993-1995, 1997-1999, 2001-2024 Free
    Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -468,7 +468,7 @@ parse_sexp_propertize (ptrdiff_t charpos)
       && syntax_propertize__done < zv)
     {
       modiff_count modiffs = CHARS_MODIFF;
-      safe_call1 (Qinternal__syntax_propertize,
+      safe_calln (Qinternal__syntax_propertize,
                  make_fixnum (min (zv, 1 + charpos)));
       if (modiffs != CHARS_MODIFF)
        error ("internal--syntax-propertize modified the buffer!");
diff --git a/src/syntax.h b/src/syntax.h
index 01982be25a0..34e53775a97 100644
--- a/src/syntax.h
+++ b/src/syntax.h
@@ -1,6 +1,6 @@
 /* Declarations having to do with GNU Emacs syntax tables.
 
-Copyright (C) 1985, 1993-1994, 1997-1998, 2001-2023 Free Software
+Copyright (C) 1985, 1993-1994, 1997-1998, 2001-2024 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/sysdep.c b/src/sysdep.c
index f49fed7da1e..3a6829dd27a 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -1,5 +1,5 @@
 /* Interfaces to system-dependent kernel and library entries.
-   Copyright (C) 1985-1988, 1993-1995, 1999-2023 Free Software
+   Copyright (C) 1985-1988, 1993-1995, 1999-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -36,7 +36,6 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include <utimens.h>
 
 #include "lisp.h"
-#include "sheap.h"
 #include "sysselect.h"
 #include "blockinput.h"
 
diff --git a/src/sysselect.h b/src/sysselect.h
index 6cde52911f4..ccb10c1d124 100644
--- a/src/sysselect.h
+++ b/src/sysselect.h
@@ -1,5 +1,5 @@
 /* sysselect.h - System-dependent definitions for the select function.
-   Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/syssignal.h b/src/syssignal.h
index 6aa3572b903..e5144588c75 100644
--- a/src/syssignal.h
+++ b/src/syssignal.h
@@ -1,6 +1,6 @@
 /* syssignal.h - System-dependent definitions for signals.
 
-Copyright (C) 1993, 1999, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993, 1999, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/sysstdio.h b/src/sysstdio.h
index 8e9e5bec86c..3a3d23ee0a8 100644
--- a/src/sysstdio.h
+++ b/src/sysstdio.h
@@ -1,6 +1,6 @@
 /* Standard I/O for Emacs.
 
-Copyright 2013-2023 Free Software Foundation, Inc.
+Copyright 2013-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/systhread.c b/src/systhread.c
index caa4dfd4443..ef40cb0a223 100644
--- a/src/systhread.c
+++ b/src/systhread.c
@@ -1,5 +1,5 @@
 /* System thread definitions
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/systhread.h b/src/systhread.h
index b8f078df071..c36a1ca6142 100644
--- a/src/systhread.h
+++ b/src/systhread.h
@@ -1,5 +1,5 @@
 /* System thread definitions
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/systime.h b/src/systime.h
index 936f1a50a96..fc93ea03233 100644
--- a/src/systime.h
+++ b/src/systime.h
@@ -1,5 +1,5 @@
 /* systime.h - System-dependent definitions for time manipulations.
-   Copyright (C) 1993-1994, 2002-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993-1994, 2002-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/systty.h b/src/systty.h
index 918b4178905..7038cce27ef 100644
--- a/src/systty.h
+++ b/src/systty.h
@@ -1,5 +1,5 @@
 /* systty.h - System-dependent definitions for terminals.
-   Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/syswait.h b/src/syswait.h
index 80e2d8d39d0..f4790b725a9 100644
--- a/src/syswait.h
+++ b/src/syswait.h
@@ -1,5 +1,5 @@
 /* Define wait system call interface for Emacs.
-   Copyright (C) 1993-1995, 2000-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993-1995, 2000-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/term.c b/src/term.c
index 25184101b78..3fa244be824 100644
--- a/src/term.c
+++ b/src/term.c
@@ -1,5 +1,5 @@
 /* Terminal control module for terminals described by TERMCAP
-   Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2023 Free Software
+   Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -86,12 +86,12 @@ static AVOID vfatal (const char *, va_list) 
ATTRIBUTE_FORMAT_PRINTF (1, 0);
 #ifndef HAVE_ANDROID
 
 #define OUTPUT(tty, a)                                          \
-  emacs_tputs ((tty), a,                                        \
+  emacs_tputs (tty, a,                                        \
                FRAME_TOTAL_LINES (XFRAME (selected_frame)) - curY (tty),       
\
                cmputc)
 
-#define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
-#define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
+#define OUTPUT1(tty, a) emacs_tputs (tty, a, 1, cmputc)
+#define OUTPUTL(tty, a, lines) emacs_tputs (tty, a, lines, cmputc)
 
 #define OUTPUT_IF(tty, a)                                               \
   do {                                                                  \
@@ -99,7 +99,8 @@ static AVOID vfatal (const char *, va_list) 
ATTRIBUTE_FORMAT_PRINTF (1, 0);
       OUTPUT (tty, a);                                                 \
   } while (0)
 
-#define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } 
while (0)
+#define OUTPUT1_IF(tty, a) \
+  do { if (a) emacs_tputs (tty, a, 1, cmputc); } while (0)
 
 #endif
 
@@ -1117,7 +1118,7 @@ per_line_cost (const char *str)
 
 int *char_ins_del_vector;
 
-#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
+#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS (f)])
 
 static void
 calculate_ins_del_char_costs (struct frame *f)
@@ -1630,8 +1631,19 @@ produce_glyphs (struct it *it)
     it->pixel_width = it->nglyphs = 0;
   else if (it->char_to_display == '\t')
     {
+      /* wrap-prefix strings are prepended to continuation lines, so
+        the width of tab characters inside should be computed from
+        the start of this screen line rather than as a product of the
+        total width of the physical line being wrapped.  */
       int absolute_x = (it->current_x
-                       + it->continuation_lines_width);
+                       + (it->string_from_prefix_prop_p
+                          /* Subtract the width of the
+                             prefix from it->current_x if
+                             it exists.  */
+                          ? 0 : (it->continuation_lines_width
+                                 ? (it->continuation_lines_width
+                                    - it->wrap_prefix_width)
+                                 : 0)));
       int x0 = absolute_x;
       /* Adjust for line numbers.  */
       if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
@@ -1703,7 +1715,13 @@ produce_glyphs (struct it *it)
   /* Advance current_x by the pixel width as a convenience for
      the caller.  */
   if (it->area == TEXT_AREA)
-    it->current_x += it->pixel_width;
+    {
+      it->current_x += it->pixel_width;
+
+      if (it->continuation_lines_width
+         && it->string_from_prefix_prop_p)
+       it->wrap_prefix_width = it->current_x;
+    }
   it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
   it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
 #endif
@@ -2235,7 +2253,7 @@ set_tty_color_mode (struct tty_display_info *tty, struct 
frame *f)
       tty->previous_color_mode = mode;
       tty_setup_colors (tty , mode);
       /*  This recomputes all the faces given the new color definitions.  */
-      safe_call (1, intern ("tty-set-up-initial-frame-faces"));
+      safe_calln (intern ("tty-set-up-initial-frame-faces"));
     }
 }
 
diff --git a/src/termcap.c b/src/termcap.c
index 1e989b6e2de..a8c1cef2456 100644
--- a/src/termcap.c
+++ b/src/termcap.c
@@ -1,5 +1,5 @@
 /* Work-alike for termcap, plus extra features.
-   Copyright (C) 1985-1986, 1993-1995, 2000-2008, 2011, 2013-2023 Free
+   Copyright (C) 1985-1986, 1993-1995, 2000-2008, 2011, 2013-2024 Free
    Software Foundation, Inc.
 
 This program is free software; you can redistribute it and/or modify
diff --git a/src/termchar.h b/src/termchar.h
index 5c47679a994..2d845107e11 100644
--- a/src/termchar.h
+++ b/src/termchar.h
@@ -1,5 +1,5 @@
 /* Flags and parameters describing terminal's characteristics.
-   Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/termhooks.h b/src/termhooks.h
index 6bf507aae33..8defebb20bd 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -1,6 +1,6 @@
 /* Parameters and display hooks for terminal devices.
 
-Copyright (C) 1985-1986, 1993-1994, 2001-2023 Free Software Foundation,
+Copyright (C) 1985-1986, 1993-1994, 2001-2024 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/terminal.c b/src/terminal.c
index 07c37883f0e..23a5582d4d9 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -1,5 +1,5 @@
 /* Functions related to terminal devices.
-   Copyright (C) 2005-2023 Free Software Foundation, Inc.
+   Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -389,7 +389,7 @@ but if the second argument FORCE is non-nil, you may do so. 
*/)
                      Qdelete_terminal_functions, terminal),
               pending_funcalls);
   else
-    safe_call2 (Qrun_hook_with_args, Qdelete_terminal_functions, terminal);
+    safe_calln (Qrun_hook_with_args, Qdelete_terminal_functions, terminal);
 
   if (t->delete_terminal_hook)
     (*t->delete_terminal_hook) (t);
diff --git a/src/terminfo.c b/src/terminfo.c
index 66820920d47..4feac32bedc 100644
--- a/src/terminfo.c
+++ b/src/terminfo.c
@@ -1,5 +1,5 @@
 /* Interface from Emacs to terminfo.
-   Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/termopts.h b/src/termopts.h
index 346c46bdaaa..f5df2464c23 100644
--- a/src/termopts.h
+++ b/src/termopts.h
@@ -1,5 +1,5 @@
 /* Flags and parameters describing user options for handling the terminal.
-   Copyright (C) 1985-1986, 1990, 2001-2023 Free Software Foundation,
+   Copyright (C) 1985-1986, 1990, 2001-2024 Free Software Foundation,
    Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/textconv.c b/src/textconv.c
index bd72562317f..0d35ec19c55 100644
--- a/src/textconv.c
+++ b/src/textconv.c
@@ -1,6 +1,6 @@
 /* String conversion support for graphics terminals.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -23,7 +23,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
    They may then request that the text editor remove or substitute
    that text for something else, for example when providing the
    ability to ``undo'' or ``edit'' previously composed text.  This is
-   most commonly seen in input methods for CJK laguages for X Windows,
+   most commonly seen in input methods for CJK languages for X Windows,
    and is extensively used throughout Android by input methods for all
    kinds of scripts.
 
@@ -649,8 +649,7 @@ really_commit_text (struct frame *f, EMACS_INT position,
             start of the text that was inserted.  */
          wanted = start;
 
-         if (INT_ADD_WRAPV (wanted, position, &wanted)
-             || wanted < BEGV)
+         if (ckd_add (&wanted, wanted, position) || wanted < BEGV)
            wanted = BEGV;
 
          if (wanted > ZV)
@@ -664,8 +663,7 @@ really_commit_text (struct frame *f, EMACS_INT position,
             TEXT.  */
          wanted = PT;
 
-         if (INT_ADD_WRAPV (wanted, position - 1, &wanted)
-             || wanted > ZV)
+         if (ckd_add (&wanted, wanted, position - 1) || wanted > ZV)
            wanted = ZV;
 
          if (wanted < BEGV)
@@ -712,8 +710,7 @@ really_commit_text (struct frame *f, EMACS_INT position,
 
       if (position <= 0)
        {
-         if (INT_ADD_WRAPV (wanted, position, &wanted)
-             || wanted < BEGV)
+         if (ckd_add (&wanted, wanted, position) || wanted < BEGV)
            wanted = BEGV;
 
          if (wanted > ZV)
@@ -725,8 +722,7 @@ really_commit_text (struct frame *f, EMACS_INT position,
        {
          wanted = PT;
 
-         if (INT_ADD_WRAPV (wanted, position - 1, &wanted)
-             || wanted > ZV)
+         if (ckd_add (&wanted, wanted, position - 1) || wanted > ZV)
            wanted = ZV;
 
          if (wanted < BEGV)
@@ -870,8 +866,7 @@ really_set_composing_text (struct frame *f, ptrdiff_t 
position,
     {
       wanted = start;
 
-      if (INT_SUBTRACT_WRAPV (wanted, position, &wanted)
-         || wanted < BEGV)
+      if (ckd_sub (&wanted, wanted, position) || wanted < BEGV)
        wanted = BEGV;
 
       if (wanted > ZV)
@@ -885,8 +880,7 @@ really_set_composing_text (struct frame *f, ptrdiff_t 
position,
       /* end should be PT after the edit.  */
       eassert (end == PT);
 
-      if (INT_ADD_WRAPV (wanted, position - 1, &wanted)
-         || wanted > ZV)
+      if (ckd_add (&wanted, wanted, position - 1) || wanted > ZV)
        wanted = ZV;
 
       if (wanted < BEGV)
@@ -1256,8 +1250,7 @@ really_replace_text (struct frame *f, ptrdiff_t start, 
ptrdiff_t end,
 
   if (position <= 0)
     {
-      if (INT_ADD_WRAPV (wanted, position, &wanted)
-         || wanted < BEGV)
+      if (ckd_add (&wanted, wanted, position) || wanted < BEGV)
        wanted = BEGV;
 
       if (wanted > ZV)
@@ -1269,8 +1262,7 @@ really_replace_text (struct frame *f, ptrdiff_t start, 
ptrdiff_t end,
     {
       wanted = PT;
 
-      if (INT_ADD_WRAPV (wanted, position - 1, &wanted)
-         || wanted > ZV)
+      if (ckd_add (&wanted, wanted, position - 1) || wanted > ZV)
        wanted = ZV;
 
       if (wanted < BEGV)
@@ -1311,7 +1303,7 @@ struct complete_edit_check_context
 
 /* Convert PTR to CONTEXT.  If CONTEXT->check is false, then update
    CONTEXT->w's ephemeral last point and give it to the input method,
-   the assumption being that an editing operation signalled.  */
+   the assumption being that an editing operation signaled.  */
 
 static void
 complete_edit_check (void *ptr)
@@ -1379,7 +1371,7 @@ handle_pending_conversion_events_1 (struct frame *f,
      or not the editing operation completed successfully.  */
   context.check = false;
 
-  /* Make sure completion is signalled.  */
+  /* Make sure completion is signaled.  */
   count = SPECPDL_INDEX ();
   record_unwind_protect_ptr (complete_edit, &token);
   w = NULL;
@@ -2020,8 +2012,8 @@ get_surrounding_text (struct frame *f, ptrdiff_t left,
 
   /* And subtract left and right.  */
 
-  if (INT_SUBTRACT_WRAPV (start, left, &start)
-      || INT_ADD_WRAPV (end, right, &end))
+  if (ckd_sub (&start, start, left)
+      || ckd_add (&end, end, right))
     goto finish;
 
   start = max (start, BEGV);
diff --git a/src/textconv.h b/src/textconv.h
index c677c07e9aa..61f13ebcb43 100644
--- a/src/textconv.h
+++ b/src/textconv.h
@@ -1,6 +1,6 @@
 /* String conversion support for graphics terminals.
 
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/textprop.c b/src/textprop.c
index f88fff19c59..7d9aae0d2c5 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -1,5 +1,5 @@
 /* Interface code for dealing with text properties.
-   Copyright (C) 1993-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/thread.c b/src/thread.c
index b8ca56fd372..040ca39511e 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -1,5 +1,5 @@
 /* Threading code.
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/thread.h b/src/thread.h
index 9b14cc44f35..6ce2b7f30df 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -1,5 +1,5 @@
 /* Thread definitions
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/timefns.c b/src/timefns.c
index 151f5b482a3..1541583b485 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -1,6 +1,6 @@
 /* Timestamp functions for Emacs
 
-Copyright (C) 1985-1987, 1989, 1993-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-1987, 1989, 1993-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/tparam.c b/src/tparam.c
index a0d2ee74d99..d19d484430d 100644
--- a/src/tparam.c
+++ b/src/tparam.c
@@ -1,5 +1,5 @@
 /* Merge parameters into a termcap entry string.
-   Copyright (C) 1985, 1987, 1993, 1995, 2000-2008, 2013-2023 Free
+   Copyright (C) 1985, 1987, 1993, 1995, 2000-2008, 2013-2024 Free
    Software Foundation, Inc.
 
 This program is free software; you can redistribute it and/or modify
@@ -183,7 +183,7 @@ tparam1 (const char *string, char *outstring, int len,
              argp++;
              break;
 
-           case 'b':           /* %b means back up one arg (and re-use it).  */
+           case 'b':           /* %b means back up one arg (and reuse it).  */
              argp--;
              break;
 
diff --git a/src/tparam.h b/src/tparam.h
index 898ee38a64b..eab3613ffd3 100644
--- a/src/tparam.h
+++ b/src/tparam.h
@@ -1,6 +1,6 @@
 /* Interface definitions for termcap entries.
 
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/treesit.c b/src/treesit.c
index 69b59fca111..12915ea9a10 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -1,6 +1,6 @@
 /* Tree-sitter integration for GNU Emacs.
 
-Copyright (C) 2021-2023 Free Software Foundation, Inc.
+Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 Maintainer: Yuan Fu <casouri@gmail.com>
 
@@ -600,8 +600,6 @@ treesit_load_language (Lisp_Object language_symbol,
   /* First push just the filenames to the candidate list, which will
      make dynlib_open look under standard system load paths.  */
   treesit_load_language_push_for_each_suffix (lib_base_name, &path_candidates);
-  /* This is used for reporting errors (i.e., just filenames).  */
-  Lisp_Object base_candidates = path_candidates;
   /* Then push ~/.emacs.d/tree-sitter paths.  */
   Lisp_Object lib_name
     = Fexpand_file_name (concat2 (build_string ("tree-sitter/"), 
lib_base_name),
@@ -624,6 +622,7 @@ treesit_load_language (Lisp_Object language_symbol,
      fail.  */
   dynlib_handle_ptr handle;
   const char *error;
+  Lisp_Object error_list = Qnil;
 
   tail = path_candidates;
   error = NULL;
@@ -637,13 +636,17 @@ treesit_load_language (Lisp_Object language_symbol,
       error = dynlib_error ();
       if (error == NULL)
        break;
+      else
+       error_list = Fcons (build_string (error), error_list);
     }
 
   if (error != NULL)
     {
+      /* Yes, the error message list gets a bit verbose, but those
+         messages will be helpful for certain errors like libc version
+         mismatch.  */
       *signal_symbol = Qtreesit_load_language_error;
-      *signal_data = list3 (Qnot_found, base_candidates,
-                           build_string ("No such file or directory"));
+      *signal_data = Fcons (Qnot_found, Fnreverse (error_list));
       return NULL;
     }
 
@@ -945,7 +948,10 @@ treesit_sync_visible_region (Lisp_Object parser)
      this function is called), we need to reparse.  */
   if (visible_beg != BUF_BEGV_BYTE (buffer)
       || visible_end != BUF_ZV_BYTE (buffer))
-    XTS_PARSER (parser)->need_reparse = true;
+    {
+      XTS_PARSER (parser)->need_reparse = true;
+      XTS_PARSER (parser)->timestamp++;
+    }
 
   /* Before we parse or set ranges, catch up with the narrowing
      situation.  We change visible_beg and visible_end to match
@@ -1040,7 +1046,7 @@ treesit_call_after_change_functions (TSTree *old_tree, 
TSTree *new_tree,
      for each of them.  */
   Lisp_Object functions = XTS_PARSER (parser)->after_change_functions;
   FOR_EACH_TAIL (functions)
-    safe_call2 (XCAR (functions), lisp_ranges, parser);
+    safe_calln (XCAR (functions), lisp_ranges, parser);
 
   unbind_to (count, Qnil);
 }
@@ -1719,6 +1725,7 @@ buffer.  */)
              ranges);
 
   XTS_PARSER (parser)->need_reparse = true;
+  XTS_PARSER (parser)->timestamp++;
   return Qnil;
 }
 
@@ -3247,9 +3254,9 @@ treesit_traverse_child_helper (TSTreeCursor *cursor,
       /* First go to the last child.  */
       while (ts_tree_cursor_goto_next_sibling (cursor));
 
-      if (!named)
+      if (!named || (named && ts_node_is_named 
(ts_tree_cursor_current_node(cursor))))
        return true;
-      /* Else named... */
+      /* Else named is required and last child is not named node.  */
       if (treesit_traverse_sibling_helper(cursor, false, true))
        return true;
       else
@@ -3286,7 +3293,7 @@ treesit_traverse_get_predicate (Lisp_Object thing, 
Lisp_Object language)
    there's an error, set SIGNAL_DATA to (ERR . DATA), where ERR is an
    error symbol, and DATA is something signal accepts, and return
    false, otherwise return true.  This function also check for
-   recusion levels: we place a arbitrary 100 level limit on recursive
+   recursion levels: we place a arbitrary 100 level limit on recursive
    predicates.  RECURSION_LEVEL is the current recursion level (that
    starts at 0), if it goes over 99, return false and set SIGNAL_DATA.
    LANGUAGE is a LANGUAGE symbol.  */
@@ -3335,7 +3342,7 @@ treesit_traverse_validate_predicate (Lisp_Object pred,
          if (!CONSP (cdr))
            {
              *signal_data = list3 (Qtreesit_invalid_predicate,
-                                   build_string ("Invalide `not' "
+                                   build_string ("Invalid `not' "
                                                  "predicate"),
                                    pred);
              return false;
diff --git a/src/treesit.h b/src/treesit.h
index ef7e2e15317..bb81bf0e2b3 100644
--- a/src/treesit.h
+++ b/src/treesit.h
@@ -1,6 +1,6 @@
 /* Header file for the tree-sitter integration.
 
-Copyright (C) 2021-2023 Free Software Foundation, Inc.
+Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -61,7 +61,9 @@ struct Lisp_TS_Parser
   /* Re-parsing an unchanged buffer is not free for tree-sitter, so we
      only make it re-parse when need_reparse == true.  That usually
      means some change is made in the buffer.  But others could set
-     this field to true to force tree-sitter to re-parse.  */
+     this field to true to force tree-sitter to re-parse.  When you
+     set this to true, you should _always_ also increment
+     timestamp.  */
   bool need_reparse;
   /* These two positions record the buffer byte position (1-based) of
      the "visible region" that tree-sitter sees.  Before re-parse, we
diff --git a/src/undo.c b/src/undo.c
index 75cfd6058d2..afab89067ec 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -1,5 +1,5 @@
 /* undo handling for GNU Emacs.
-   Copyright (C) 1990, 1993-1994, 2000-2023 Free Software Foundation,
+   Copyright (C) 1990, 1993-1994, 2000-2024 Free Software Foundation,
    Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/unexaix.c b/src/unexaix.c
index e50452c519a..f9bc39cf927 100644
--- a/src/unexaix.c
+++ b/src/unexaix.c
@@ -1,5 +1,5 @@
 /* Dump an executable file.
-   Copyright (C) 1985-1988, 1999, 2001-2023 Free Software Foundation,
+   Copyright (C) 1985-1988, 1999, 2001-2024 Free Software Foundation,
    Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/unexcoff.c b/src/unexcoff.c
index 05a4edfe89d..4a981da4a04 100644
--- a/src/unexcoff.c
+++ b/src/unexcoff.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1985-1988, 1992-1994, 2001-2023 Free Software
+/* Copyright (C) 1985-1988, 1992-1994, 2001-2024 Free Software
  * Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/unexcw.c b/src/unexcw.c
index fe2f120a01f..5c91498cc6c 100644
--- a/src/unexcw.c
+++ b/src/unexcw.c
@@ -1,7 +1,7 @@
 /* unexec() support for Cygwin;
    complete rewrite of xemacs Cygwin unexec() code
 
-   Copyright (C) 2004-2023 Free Software Foundation, Inc.
+   Copyright (C) 2004-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/unexelf.c b/src/unexelf.c
index 607ac0cd6a2..feb26ffaeaf 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1985-1988, 1990, 1992, 1999-2023 Free Software
+/* Copyright (C) 1985-1988, 1990, 1992, 1999-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/unexmacosx.c b/src/unexmacosx.c
index 33c20358116..7b2326441b4 100644
--- a/src/unexmacosx.c
+++ b/src/unexmacosx.c
@@ -1,5 +1,5 @@
 /* Dump Emacs in Mach-O format for use on macOS.
-   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/unexw32.c b/src/unexw32.c
index 92e02b29850..d8329be522d 100644
--- a/src/unexw32.c
+++ b/src/unexw32.c
@@ -1,5 +1,5 @@
 /* unexec for GNU Emacs on Windows NT.
-   Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/verbose.mk.in b/src/verbose.mk.in
index 97799cee813..e72c182f276 100644
--- a/src/verbose.mk.in
+++ b/src/verbose.mk.in
@@ -1,6 +1,6 @@
 ### verbose.mk --- Makefile fragment for GNU Emacs
 
-## Copyright (C) 2021-2023 Free Software Foundation, Inc.
+## Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ## This file is part of GNU Emacs.
 
diff --git a/src/vm-limit.c b/src/vm-limit.c
index a118f36edc5..698a1d8a7eb 100644
--- a/src/vm-limit.c
+++ b/src/vm-limit.c
@@ -1,5 +1,5 @@
 /* Functions for memory limit warnings.
-   Copyright (C) 1990, 1992, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1990, 1992, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/w16select.c b/src/w16select.c
index dce37fc1396..ed450c665ff 100644
--- a/src/w16select.c
+++ b/src/w16select.c
@@ -1,6 +1,6 @@
 /* 16-bit Windows Selection processing for emacs on MS-Windows
 
-Copyright (C) 1996-1997, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1996-1997, 2001-2024 Free Software Foundation, Inc.
 
 Author: Dale P. Smith <dpsm@en.com>
 
@@ -275,7 +275,7 @@ set_clipboard_data (unsigned Format, void *Data, unsigned 
Size, int Raw)
     {
       clipboard_storage_size = truelen + 100;
       last_clipboard_text =
-       (char *) xrealloc (last_clipboard_text, clipboard_storage_size);
+       xrealloc (last_clipboard_text, clipboard_storage_size);
     }
   if (last_clipboard_text)
     dosmemget (xbuf_addr, truelen, last_clipboard_text);
diff --git a/src/w32.c b/src/w32.c
index 81201509e2d..df5465c2135 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -1,6 +1,6 @@
 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
 
-Copyright (C) 1994-1995, 2000-2023 Free Software Foundation, Inc.
+Copyright (C) 1994-1995, 2000-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -9414,7 +9414,7 @@ sys_write (int fd, const void * buffer, unsigned int 
count)
       errno = 0;
       while (count > 0)
        {
-         unsigned this_chunk = count < chunk ? count : chunk;
+         unsigned this_chunk = min (count, chunk);
          int n = _write (fd, p, this_chunk);
 
          if (n > 0)
diff --git a/src/w32.h b/src/w32.h
index a3d0b75359a..cf470ae9901 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -2,7 +2,7 @@
 #define EMACS_W32_H
 
 /* Support routines for the NT version of Emacs.
-   Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/w32common.h b/src/w32common.h
index 26b114441ef..9475481b64e 100644
--- a/src/w32common.h
+++ b/src/w32common.h
@@ -1,5 +1,5 @@
 /* Common functions for Microsoft Windows builds of Emacs
-   Copyright (C) 2012-2023 Free Software Foundation, Inc.
+   Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/w32console.c b/src/w32console.c
index bb7d2162403..0936b5f37e6 100644
--- a/src/w32console.c
+++ b/src/w32console.c
@@ -1,5 +1,5 @@
 /* Terminal hooks for GNU Emacs on the Microsoft Windows API.
-   Copyright (C) 1992, 1999, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1992, 1999, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -705,6 +705,10 @@ initialize_w32_display (struct terminal *term, int *width, 
int *height)
   /* Remember original console settings.  */
   keyboard_handle = GetStdHandle (STD_INPUT_HANDLE);
   GetConsoleMode (keyboard_handle, &prev_console_mode);
+  /* Make sure ENABLE_EXTENDED_FLAGS is set in console settings,
+     otherwise restoring the original setting of ENABLE_MOUSE_INPUT
+     will not work.  */
+  prev_console_mode |= ENABLE_EXTENDED_FLAGS;
 
   prev_screen = GetStdHandle (STD_OUTPUT_HANDLE);
 
diff --git a/src/w32cygwinx.c b/src/w32cygwinx.c
index dd1c4044e8e..7fd670499d1 100644
--- a/src/w32cygwinx.c
+++ b/src/w32cygwinx.c
@@ -1,6 +1,6 @@
 /* Common functions for the Microsoft Windows and Cygwin builds.
 
-Copyright (C) 2018-2023 Free Software Foundation, Inc.
+Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/w32fns.c b/src/w32fns.c
index 01644eff826..8d4bd00b91c 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -1,6 +1,6 @@
 /* Graphical user interface functions for the Microsoft Windows API.
 
-Copyright (C) 1989, 1992-2023 Free Software Foundation, Inc.
+Copyright (C) 1989, 1992-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -2376,7 +2376,7 @@ w32_init_class (HINSTANCE hinst)
 static void
 w32_applytheme (HWND hwnd)
 {
-  if (w32_darkmode)
+  if (w32_darkmode && w32_follow_system_dark_mode)
     {
       /* Set window theme to that of a built-in Windows app (Explorer),
         because it has dark scroll bars and other UI elements.  */
@@ -11121,12 +11121,20 @@ my_exception_handler (EXCEPTION_POINTERS * 
exception_data)
     return prev_exception_handler (exception_data);
   return EXCEPTION_EXECUTE_HANDLER;
 }
-#endif
+#endif /* !CYGWIN */
 
 typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *,
                                                      PULONG);
 
 #define BACKTRACE_LIMIT_MAX 62
+/* The below must be kept in sync with the value of the
+   -Wl,-image-base switch we use in LD_SWITCH_SYSTEM_TEMACS, see
+   configure.ac.  */
+#if defined MINGW_W64 && EMACS_INT_MAX > LONG_MAX
+# define DEFAULT_IMAGE_BASE (ptrdiff_t)0x400000000
+#else  /* 32-bit MinGW build */
+# define DEFAULT_IMAGE_BASE (ptrdiff_t)0x01000000
+#endif
 
 static int
 w32_backtrace (void **buffer, int limit)
@@ -11181,6 +11189,13 @@ emacs_abort (void)
       {
        void *stack[BACKTRACE_LIMIT_MAX + 1];
        int i = w32_backtrace (stack, BACKTRACE_LIMIT_MAX + 1);
+#ifdef CYGWIN
+       ptrdiff_t addr_offset = 0;
+#else   /* MinGW */
+       /* The offset below is zero unless ASLR is in effect.  */
+       ptrdiff_t addr_offset
+         = DEFAULT_IMAGE_BASE - (ptrdiff_t)GetModuleHandle (NULL);
+#endif /* MinGW */
 
        if (i)
          {
@@ -11231,8 +11246,13 @@ emacs_abort (void)
              {
                /* stack[] gives the return addresses, whereas we want
                   the address of the call, so decrease each address
-                  by approximate size of 1 CALL instruction.  */
-               sprintf (buf, "%p\r\n", (char *)stack[j] - sizeof(void *));
+                  by approximate size of 1 CALL instruction.  We add
+                  ADDR_OFFSET to account for ASLR which changes the
+                  base address of the program's image in memory,
+                  whereas 'addr2line' needs to see addresses relative
+                  to the fixed base recorded in the PE header.  */
+               sprintf (buf, "%p\r\n",
+                        (char *)stack[j] - sizeof(void *) + addr_offset);
                if (stderr_fd >= 0)
                  write (stderr_fd, buf, strlen (buf));
                if (errfile_fd >= 0)
@@ -11373,6 +11393,14 @@ This variable is used for debugging, and takes 
precedence over any
 value of the `inhibit-double-buffering' frame parameter.  */);
   w32_disable_double_buffering = false;
 
+  DEFVAR_BOOL ("w32-follow-system-dark-mode", w32_follow_system_dark_mode,
+              doc: /* Whether to follow the system's Dark mode on MS-Windows.
+If this is nil, Emacs on MS-Windows will not follow the system's Dark
+mode as far as the appearance of title bars and scroll bars is
+concerned, it will always use the default Light mode instead.
+Changing the value takes effect only for frames created after the change.  */);
+  w32_follow_system_dark_mode = true;
+
   if (os_subtype == OS_SUBTYPE_NT)
     w32_unicode_gui = 1;
   else
diff --git a/src/w32font.c b/src/w32font.c
index 45b6c499745..56061c0d9ce 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -1,5 +1,5 @@
 /* Font backend for the Microsoft Windows API.
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -2265,14 +2265,14 @@ font_supported_scripts (FONTSIGNATURE * sig)
   /* Match a single subrange. SYM is set if bit N is set in subranges.  */
 #define SUBRANGE(n,sym) \
   if (subranges[(n) / 32] & (1U << ((n) % 32))) \
-    supported = Fcons ((sym), supported)
+    supported = Fcons (sym, supported)
 
   /* Match multiple subranges. SYM is set if any MASK bit is set in
      subranges[0 - 3].  */
 #define MASK_ANY(mask0,mask1,mask2,mask3,sym)      \
   if ((subranges[0] & (mask0)) || (subranges[1] & (mask1))     \
       || (subranges[2] & (mask2)) || (subranges[3] & (mask3))) \
-    supported = Fcons ((sym), supported)
+    supported = Fcons (sym, supported)
 
   /* 0: ASCII (a.k.a. "Basic Latin"),
      1: Latin-1 supplement, 2: Latin Extended A, 3: Latin Extended B,
diff --git a/src/w32font.h b/src/w32font.h
index 3f1c86adff9..3f780c1d866 100644
--- a/src/w32font.h
+++ b/src/w32font.h
@@ -1,5 +1,5 @@
 /* Shared GDI and Uniscribe Font backend declarations for the Windows API.
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/w32gui.h b/src/w32gui.h
index 55e2e90c634..739a790911e 100644
--- a/src/w32gui.h
+++ b/src/w32gui.h
@@ -1,5 +1,5 @@
 /* Definitions and headers for communication on the Microsoft Windows API.
-   Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/w32heap.c b/src/w32heap.c
index 96881c3923d..601686f5331 100644
--- a/src/w32heap.c
+++ b/src/w32heap.c
@@ -1,5 +1,5 @@
 /* Heap management routines for GNU Emacs on the Microsoft Windows API.
-   Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 
    This file is part of GNU Emacs.
 
diff --git a/src/w32heap.h b/src/w32heap.h
index 2f0ac61e6a0..24b02fabbfc 100644
--- a/src/w32heap.h
+++ b/src/w32heap.h
@@ -1,5 +1,5 @@
 /* Heap management routines (including unexec) for GNU Emacs on Windows NT.
-   Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/w32image.c b/src/w32image.c
index 32967bab9e8..9010338a267 100644
--- a/src/w32image.c
+++ b/src/w32image.c
@@ -1,6 +1,6 @@
 /* Implementation of MS-Windows native image API via the GDI+ library.
 
-Copyright (C) 2020-2023 Free Software Foundation, Inc.
+Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/w32inevt.c b/src/w32inevt.c
index 630a9f4e5fb..35d3420e39f 100644
--- a/src/w32inevt.c
+++ b/src/w32inevt.c
@@ -1,5 +1,5 @@
 /* Input event support for Emacs on the Microsoft Windows API.
-   Copyright (C) 1992-1993, 1995, 2001-2023 Free Software Foundation,
+   Copyright (C) 1992-1993, 1995, 2001-2024 Free Software Foundation,
    Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/w32inevt.h b/src/w32inevt.h
index 9310873c872..da8f0f7d06f 100644
--- a/src/w32inevt.h
+++ b/src/w32inevt.h
@@ -1,5 +1,5 @@
 /* Input routines for GNU Emacs on the Microsoft Windows API.
-   Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/w32menu.c b/src/w32menu.c
index 239355946fc..cea4f4892a4 100644
--- a/src/w32menu.c
+++ b/src/w32menu.c
@@ -1,5 +1,5 @@
 /* Menu support for GNU Emacs on the Microsoft Windows API.
-   Copyright (C) 1986, 1988, 1993-1994, 1996, 1998-1999, 2001-2023 Free
+   Copyright (C) 1986, 1988, 1993-1994, 1996, 1998-1999, 2001-2024 Free
    Software Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/w32notify.c b/src/w32notify.c
index 541d2f0fcd4..c93e8796fe2 100644
--- a/src/w32notify.c
+++ b/src/w32notify.c
@@ -1,6 +1,6 @@
 /* Filesystem notifications support for GNU Emacs on the Microsoft Windows API.
 
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 Author: Eli Zaretskii <eliz@gnu.org>
 
@@ -350,6 +350,7 @@ start_watching (const char *file, HANDLE hdir, BOOL 
subdirs, DWORD flags)
       xfree (dirwatch->io_info);
       xfree (dirwatch->watchee);
       xfree (dirwatch);
+      return NULL;
     }
   return dirwatch;
 }
@@ -412,10 +413,7 @@ add_watch (const char *parent_dir, const char *file, BOOL 
subdirs, DWORD flags)
     return NULL;
 
   if ((dirwatch = start_watching (file, hdir, subdirs, flags)) == NULL)
-    {
-      CloseHandle (hdir);
-      dirwatch->dir = NULL;
-    }
+    CloseHandle (hdir);
 
   return dirwatch;
 }
diff --git a/src/w32proc.c b/src/w32proc.c
index edc4394b17f..55ead13647b 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -1,6 +1,6 @@
 /* Process support for GNU Emacs on the Microsoft Windows API.
 
-Copyright (C) 1992, 1995, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1992, 1995, 1999-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/w32reg.c b/src/w32reg.c
index 9c390d6cd41..16ade86b436 100644
--- a/src/w32reg.c
+++ b/src/w32reg.c
@@ -1,6 +1,6 @@
 /* Emulate the X Resource Manager through the registry.
 
-Copyright (C) 1990, 1993-1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1990, 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 Author: Kevin Gallo
 
diff --git a/src/w32select.c b/src/w32select.c
index 193bc00c6e0..006bf408b47 100644
--- a/src/w32select.c
+++ b/src/w32select.c
@@ -1,6 +1,6 @@
 /* Selection processing for Emacs on the Microsoft Windows API.
 
-Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 Author: Kevin Gallo
        Benjamin Riefenstahl
diff --git a/src/w32select.h b/src/w32select.h
index e4ef82aff46..07b85401c0e 100644
--- a/src/w32select.h
+++ b/src/w32select.h
@@ -1,6 +1,6 @@
 /* Selection processing for Emacs on the Microsoft W32 API.
 
-Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/w32term.c b/src/w32term.c
index 301d8f4ef12..7afd1303b4d 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -1,6 +1,6 @@
 /* Implementation of GUI terminal on the Microsoft Windows API.
 
-Copyright (C) 1989, 1993-2023 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -776,12 +776,13 @@ w32_buffer_flipping_unblocked_hook (struct frame *f)
 
 /* Flip buffers on F if drawing has happened.  This function is not
    called to flush the display connection of a frame (which doesn't
-   exist on MS Windows), but also called in some situations in
+   exist on MS Windows), but is called in some situations in
    minibuf.c to make the contents of the back buffer visible.  */
 void
 w32_flip_buffers_if_dirty (struct frame *f)
 {
-  if (FRAME_OUTPUT_DATA (f)->paint_buffer
+  if (FRAME_W32_P (f)  /* do nothing in TTY frames */
+      && FRAME_OUTPUT_DATA (f)->paint_buffer
       && FRAME_OUTPUT_DATA (f)->paint_buffer_dirty
       && !f->garbaged && !buffer_flipping_blocked_p ())
     w32_show_back_buffer (f);
@@ -949,7 +950,7 @@ w32_define_fringe_bitmap (int which, unsigned short *bits, 
int h, int wd)
     {
       int i = max_fringe_bmp;
       max_fringe_bmp = which + 20;
-      fringe_bmp = (HBITMAP *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof 
(HBITMAP));
+      fringe_bmp = xrealloc (fringe_bmp, max_fringe_bmp * sizeof (HBITMAP));
       while (i < max_fringe_bmp)
        fringe_bmp[i++] = 0;
     }
diff --git a/src/w32term.h b/src/w32term.h
index 68237bfff1d..29ace0b2797 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -1,5 +1,5 @@
 /* Definitions and headers for communication on the Microsoft Windows API.
-   Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c
index 67df0c8aebd..84d0d95b2ab 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -1,6 +1,6 @@
 /* Font backend for the Microsoft W32 Uniscribe API.
    Windows-specific parts of the HarfBuzz font backend.
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -330,8 +330,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object 
direction)
     {
       /* If that wasn't enough, keep trying with one more run.  */
       max_items++;
-      items = (SCRIPT_ITEM *) xrealloc (items,
-                                       sizeof (SCRIPT_ITEM) * max_items + 1);
+      items = xrealloc (items, sizeof (SCRIPT_ITEM) * max_items + 1);
     }
 
   if (FAILED (result))
diff --git a/src/w32xfns.c b/src/w32xfns.c
index 2df9577460f..fa7d5fbdb61 100644
--- a/src/w32xfns.c
+++ b/src/w32xfns.c
@@ -1,5 +1,5 @@
 /* Functions taken directly from X sources for use with the Microsoft Windows 
API.
-   Copyright (C) 1989, 1992-1995, 1999, 2001-2023 Free Software
+   Copyright (C) 1989, 1992-1995, 1999, 2001-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/src/widget.c b/src/widget.c
index 26696a975e3..d22732ff93a 100644
--- a/src/widget.c
+++ b/src/widget.c
@@ -1,5 +1,5 @@
 /* The emacs frame widget.
-   Copyright (C) 1992-1993, 2000-2023 Free Software Foundation, Inc.
+   Copyright (C) 1992-1993, 2000-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/widget.h b/src/widget.h
index 317b14cc523..116e909a643 100644
--- a/src/widget.h
+++ b/src/widget.h
@@ -1,5 +1,5 @@
 /* The emacs frame widget public header file.
-   Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/widgetprv.h b/src/widgetprv.h
index e264d157edb..b9cd72a4bc2 100644
--- a/src/widgetprv.h
+++ b/src/widgetprv.h
@@ -1,5 +1,5 @@
 /* The emacs frame widget private header file.
-   Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/window.c b/src/window.c
index e802ffb3fe2..915f591221d 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1,6 +1,6 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
-   Copyright (C) 1985-1987, 1993-1998, 2000-2023 Free Software
+   Copyright (C) 1985-1987, 1993-1998, 2000-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -526,7 +526,7 @@ select_window (Lisp_Object window, Lisp_Object norecord,
     /* Do not select a tooltip window (Bug#47207).  */
     error ("Cannot select a tooltip window");
 
-  /* We deinitely want to select WINDOW, not the mini-window.  */
+  /* We definitely want to select WINDOW, not the mini-window.  */
   f->select_mini_window_flag = false;
 
   /* Make the selected window's buffer current.  */
@@ -3829,7 +3829,7 @@ run_window_change_functions_1 (Lisp_Object symbol, 
Lisp_Object buffer,
             frame.  Make sure to record changes for each live frame
             in window_change_record later.  */
          window_change_record_frames = true;
-         safe_call1 (XCAR (funs), window_or_frame);
+         safe_calln (XCAR (funs), window_or_frame);
        }
 
       funs = XCDR (funs);
@@ -5331,7 +5331,17 @@ resize_mini_window_apply (struct window *w, int delta)
   w->pixel_top = r->pixel_top + r->pixel_height;
   w->top_line = r->top_line + r->total_lines;
 
-  /* Enforce full redisplay of the frame.  */
+  /* Enforce full redisplay of the frame.  If f->redisplay is already
+     set, which it generally is in the wake of a ConfigureNotify
+     (frame resize) event, merely setting f->redisplay is insufficient
+     for redisplay_internal to continue redisplaying the frame, as
+     redisplay_internal cannot distinguish between f->redisplay set
+     before it calls redisplay_window and that after, so garbage the
+     frame as well.  */
+
+  if (f->redisplay)
+    SET_FRAME_GARBAGED (f);
+
   /* FIXME: Shouldn't some of the caller do it?  */
   fset_redisplay (f);
   adjust_frame_glyphs (f);
@@ -7826,7 +7836,11 @@ means no margin.
 
 Leave margins unchanged if WINDOW is not large enough to accommodate
 margins of the desired width.  Return t if any margin was actually
-changed and nil otherwise.  */)
+changed and nil otherwise.
+
+The margins specified by calling this function may be later overridden
+by invoking `set-window-buffer' for the same WINDOW, with its
+KEEP-MARGINS argument nil or omitted.  */)
   (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
 {
   struct window *w = set_window_margins (decode_live_window (window),
diff --git a/src/window.h b/src/window.h
index 9ef8434af18..19283725931 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1,5 +1,5 @@
 /* Window definitions for GNU Emacs.
-   Copyright (C) 1985-1986, 1993, 1995, 1997-2023 Free Software
+   Copyright (C) 1985-1986, 1993, 1995, 1997-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -292,7 +292,7 @@ struct window
 
        `last_point' is normally used during redisplay to indicate the
        position of point as seem by the input method.  However, it is
-       not updated if consequtive conversions are processed at the
+       not updated if consecutive conversions are processed at the
        same time.
 
        This `ephemeral_last_point' field is either the last point as
@@ -595,11 +595,11 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 
 /* Non-nil if window W is leaf window (has a buffer).  */
 #define WINDOW_LEAF_P(W) \
-  (BUFFERP ((W)->contents))
+  BUFFERP ((W)->contents)
 
 /* Non-nil if window W is internal (is a parent window).  */
 #define WINDOW_INTERNAL_P(W) \
-  (WINDOWP ((W)->contents))
+  WINDOWP ((W)->contents)
 
 /* True if window W is a horizontal combination of windows.  */
 #define WINDOW_HORIZONTAL_COMBINATION_P(W) \
@@ -610,7 +610,7 @@ wset_next_buffers (struct window *w, Lisp_Object val)
   (WINDOW_INTERNAL_P (W) && !(W)->horizontal)
 
 /* Window W's XFRAME.  */
-#define WINDOW_XFRAME(W) (XFRAME (WINDOW_FRAME ((W))))
+#define WINDOW_XFRAME(W) XFRAME (WINDOW_FRAME (W))
 
 /* Whether window W is a pseudo window.  */
 #define WINDOW_PSEUDO_P(W) ((W)->pseudo_window_p)
@@ -630,11 +630,11 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 
 /* Return the canonical column width of the frame of window W.  */
 #define WINDOW_FRAME_COLUMN_WIDTH(W) \
-  (FRAME_COLUMN_WIDTH (WINDOW_XFRAME ((W))))
+  FRAME_COLUMN_WIDTH (WINDOW_XFRAME (W))
 
 /* Return the canonical line height of the frame of window W.  */
 #define WINDOW_FRAME_LINE_HEIGHT(W) \
-  (FRAME_LINE_HEIGHT (WINDOW_XFRAME ((W))))
+  FRAME_LINE_HEIGHT (WINDOW_XFRAME (W))
 
 /* Return the pixel width of window W.  This includes dividers, scroll
    bars, fringes and margins, if any.  */
@@ -666,7 +666,7 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 #define MIN_SAFE_WINDOW_HEIGHT (1)
 
 #define MIN_SAFE_WINDOW_PIXEL_HEIGHT(W) \
-  (WINDOW_FRAME_LINE_HEIGHT (W))
+  WINDOW_FRAME_LINE_HEIGHT (W)
 
 /* True if window W has no other windows to its left on its frame.  */
 #define WINDOW_LEFTMOST_P(W)                   \
@@ -1011,7 +1011,7 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 /* Height in pixels of the mode line.
    May be zero if W doesn't have a mode line.  */
 #define WINDOW_MODE_LINE_HEIGHT(W)     \
-  (window_wants_mode_line ((W))                \
+  (window_wants_mode_line (W)          \
    ? CURRENT_MODE_LINE_HEIGHT (W)      \
    : 0)
 
@@ -1049,7 +1049,7 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 /* Pixel height of window W without mode and header/tab line and bottom
    divider.  */
 #define WINDOW_BOX_TEXT_HEIGHT(W)      \
-  (WINDOW_PIXEL_HEIGHT ((W))           \
+  (WINDOW_PIXEL_HEIGHT (W)             \
    - WINDOW_BOTTOM_DIVIDER_WIDTH (W)   \
    - WINDOW_SCROLL_BAR_AREA_HEIGHT (W) \
    - WINDOW_MODE_LINE_HEIGHT (W)       \
@@ -1065,7 +1065,7 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 
 /* Convert window W relative pixel X to frame pixel coordinates.  */
 #define WINDOW_TO_FRAME_PIXEL_X(W, X)  \
-  ((X) + WINDOW_BOX_LEFT_EDGE_X ((W)))
+  ((X) + WINDOW_BOX_LEFT_EDGE_X (W))
 
 /* Convert window W relative pixel Y to frame pixel coordinates.  */
 #define WINDOW_TO_FRAME_PIXEL_Y(W, Y)          \
@@ -1073,7 +1073,7 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 
 /* Convert frame relative pixel X to window relative pixel X.  */
 #define FRAME_TO_WINDOW_PIXEL_X(W, X)          \
-  ((X) - WINDOW_BOX_LEFT_EDGE_X ((W)))
+  ((X) - WINDOW_BOX_LEFT_EDGE_X (W))
 
 /* Convert frame relative pixel Y to window relative pixel Y.  */
 #define FRAME_TO_WINDOW_PIXEL_Y(W, Y)          \
@@ -1082,7 +1082,7 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 /* Convert a text area relative x-position in window W to frame X
    pixel coordinates.  */
 #define WINDOW_TEXT_TO_FRAME_PIXEL_X(W, X)     \
-  (window_box_left ((W), TEXT_AREA) + (X))
+  window_box_left (W, TEXT_AREA) + (X)
 
 /* This is the window in which the terminal's cursor should be left when
    nothing is being done with it.  This must always be a leaf window, and its
diff --git a/src/xdisp.c b/src/xdisp.c
index 75d769600c4..4ff689b2df7 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -1,6 +1,6 @@
 /* Display generation from window structure and buffer text.
 
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -3031,10 +3031,10 @@ hscrolling_current_line_p (struct window *w)
                        Lisp form evaluation
  ***********************************************************************/
 
-/* Error handler for safe_eval and safe_call.  */
+/* Error handler for dsafe_eval and dsafe_call.  */
 
 static Lisp_Object
-safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
+dsafe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
 {
   add_to_log ("Error during redisplay: %S signaled %S",
              Flist (nargs, args), arg);
@@ -3045,8 +3045,11 @@ safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, 
Lisp_Object *args)
    following.  Return the result, or nil if something went
    wrong.  Prevent redisplay during the evaluation.  */
 
+/* FIXME: What's the guiding principle behind the choice
+   of which calls should set 'inhibit_quit' and which don't.  */
 static Lisp_Object
-safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
+dsafe__call (bool inhibit_quit, Lisp_Object (f) (ptrdiff_t, Lisp_Object *),
+            ptrdiff_t nargs, Lisp_Object *args)
 {
   Lisp_Object val;
 
@@ -3054,84 +3057,52 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, 
Lisp_Object func, va_list ap)
     val = Qnil;
   else
     {
-      ptrdiff_t i;
       specpdl_ref count = SPECPDL_INDEX ();
-      Lisp_Object *args;
-      USE_SAFE_ALLOCA;
-      SAFE_ALLOCA_LISP (args, nargs);
-
-      args[0] = func;
-      for (i = 1; i < nargs; i++)
-       args[i] = va_arg (ap, Lisp_Object);
 
       specbind (Qinhibit_redisplay, Qt);
       if (inhibit_quit)
        specbind (Qinhibit_quit, Qt);
       /* Use Qt to ensure debugger does not run,
         so there is no possibility of wanting to redisplay.  */
-      val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
-                                      safe_eval_handler);
-      val = SAFE_FREE_UNBIND_TO (count, val);
+      val = internal_condition_case_n (f, nargs, args, Qt,
+                                      dsafe_eval_handler);
+      val = unbind_to (count, val);
     }
 
   return val;
 }
 
-Lisp_Object
-safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
-{
-  Lisp_Object retval;
-  va_list ap;
-
-  va_start (ap, func);
-  retval = safe__call (false, nargs, func, ap);
-  va_end (ap);
-  return retval;
-}
-
-/* Call function FN with one argument ARG.
-   Return the result, or nil if something went wrong.  */
-
-Lisp_Object
-safe_call1 (Lisp_Object fn, Lisp_Object arg)
-{
-  return safe_call (2, fn, arg);
-}
-
 static Lisp_Object
-safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
+funcall_with_backtraces (ptrdiff_t nargs, Lisp_Object *args)
 {
-  Lisp_Object retval;
-  va_list ap;
-
-  va_start (ap, fn);
-  retval = safe__call (inhibit_quit, 2, fn, ap);
-  va_end (ap);
-  return retval;
+  /* If an error is signaled during a Lisp hook in redisplay, write a
+     backtrace into the buffer *Redisplay-trace*.  */
+  push_handler_bind (list_of_error, Qdebug_early__muted, 0);
+  Lisp_Object res = Ffuncall (nargs, args);
+  pop_handler ();
+  return res;
 }
 
-Lisp_Object
-safe_eval (Lisp_Object sexpr)
-{
-  return safe__call1 (false, Qeval, sexpr);
-}
+#define SAFE_CALLMANY(inhibit_quit, f, array) \
+  dsafe__call (inhibit_quit, f, ARRAYELTS (array), array)
+#define dsafe_calln(inhibit_quit, ...)                 \
+  SAFE_CALLMANY (inhibit_quit,                        \
+                 backtrace_on_redisplay_error          \
+                 ? funcall_with_backtraces : Ffuncall, \
+                 ((Lisp_Object []) {__VA_ARGS__}))
 
 static Lisp_Object
-safe__eval (bool inhibit_quit, Lisp_Object sexpr)
+dsafe_call1 (Lisp_Object f, Lisp_Object arg)
 {
-  return safe__call1 (inhibit_quit, Qeval, sexpr);
+  return dsafe_calln (false, f, arg);
 }
 
-/* Call function FN with two arguments ARG1 and ARG2.
-   Return the result, or nil if something went wrong.  */
-
-Lisp_Object
-safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
+static Lisp_Object
+dsafe_eval (Lisp_Object sexpr)
 {
-  return safe_call (3, fn, arg1, arg2);
+  return dsafe_calln (true, Qeval, sexpr, Qt);
 }
 
-
 
 /***********************************************************************
                              Debugging
@@ -3850,7 +3821,7 @@ start_display (struct it *it, struct window *w, struct 
text_pos pos)
 
          it->current_y = first_y;
          it->vpos = 0;
-         it->current_x = it->hpos = 0;
+         it->current_x = it->hpos = it->wrap_prefix_width = 0;
        }
     }
 }
@@ -4615,7 +4586,7 @@ handle_fontified_prop (struct it *it)
       it->f->inhibit_clear_image_cache = true;
 
       if (!CONSP (val) || EQ (XCAR (val), Qlambda))
-       safe_call1 (val, pos);
+       dsafe_call1 (val, pos);
       else
        {
          Lisp_Object fns, fn;
@@ -4639,11 +4610,11 @@ handle_fontified_prop (struct it *it)
                    {
                      fn = XCAR (fns);
                      if (!EQ (fn, Qt))
-                       safe_call1 (fn, pos);
+                       dsafe_call1 (fn, pos);
                    }
                }
              else
-               safe_call1 (fn, pos);
+               dsafe_call1 (fn, pos);
            }
        }
 
@@ -5561,7 +5532,13 @@ display_min_width (struct it *it, ptrdiff_t bufpos,
          it->object = list3 (Qspace, QCwidth, w);
          produce_stretch_glyph (it);
          if (it->area == TEXT_AREA)
-           it->current_x += it->pixel_width;
+           {
+             it->current_x += it->pixel_width;
+
+             if (it->continuation_lines_width
+                 && it->string_from_prefix_prop_p)
+               it->wrap_prefix_width = it->current_x;
+           }
          it->min_width_property = Qnil;
        }
     }
@@ -5855,7 +5832,7 @@ handle_single_display_spec (struct it *it, Lisp_Object 
spec, Lisp_Object object,
       /* Save and restore the bidi cache, since FORM could be crazy
         enough to re-enter redisplay, e.g., by calling 'message'.  */
       itdata = bidi_shelve_cache ();
-      form = safe_eval (form);
+      form = dsafe_eval (form);
       bidi_unshelve_cache (itdata, false);
       form = unbind_to (count, form);
     }
@@ -5897,7 +5874,7 @@ handle_single_display_spec (struct it *it, Lisp_Object 
spec, Lisp_Object object,
                  struct face *face = FACE_FROM_ID (it->f, it->face_id);
                  Lisp_Object height;
                  itdata = bidi_shelve_cache ();
-                 height = safe_call1 (it->font_height,
+                 height = dsafe_call1 (it->font_height,
                                       face->lface[LFACE_HEIGHT_INDEX]);
                  bidi_unshelve_cache (itdata, false);
                  if (NUMBERP (height))
@@ -5922,7 +5899,7 @@ handle_single_display_spec (struct it *it, Lisp_Object 
spec, Lisp_Object object,
 
                  specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
                  itdata = bidi_shelve_cache ();
-                 value = safe_eval (it->font_height);
+                 value = dsafe_eval (it->font_height);
                  bidi_unshelve_cache (itdata, false);
                  value = unbind_to (count, value);
 
@@ -6804,7 +6781,7 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos)
                                                                        \
       entries[n].string = (STRING);                                    \
       entries[n].overlay = (OVERLAY);                                  \
-      priority = Foverlay_get ((OVERLAY), Qpriority);                  \
+      priority = Foverlay_get (OVERLAY, Qpriority);                    \
       entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0;  \
       entries[n].after_string_p = (AFTER_P);                           \
       ++n;                                                             \
@@ -9762,6 +9739,13 @@ move_it_in_display_line_to (struct it *it,
   ptrdiff_t prev_pos = IT_CHARPOS (*it);
   bool saw_smaller_pos = prev_pos < to_charpos;
   bool line_number_pending = false;
+  int this_line_subject_to_line_prefix = 0;
+
+#ifdef GLYPH_DEBUG
+  /* atx_flag, atpos_flag and wrap_flag are assigned but never used;
+     these hold information useful while debugging.  */
+  int atx_flag, atpos_flag, wrap_flag;
+#endif /* GLYPH_DEBUG */
 
   /* Don't produce glyphs in produce_glyphs.  */
   saved_glyph_row = it->glyph_row;
@@ -9827,6 +9811,11 @@ move_it_in_display_line_to (struct it *it,
       /* If there's a line-/wrap-prefix, handle it, if we didn't already.  */
       if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
        handle_line_prefix (it);
+
+      /* Save whether this line has received a wrap prefix, as this
+        affects whether Emacs attempts to move glyphs into
+        continuation lines.  */
+      this_line_subject_to_line_prefix = it->string_from_prefix_prop_p;
     }
 
   if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
@@ -9870,10 +9859,15 @@ move_it_in_display_line_to (struct it *it,
              break;
            }
          else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
-           /* If wrap_it is valid, the current position might be in a
-              word that is wrapped.  So, save the iterator in
-              atpos_it and continue to see if wrapping happens.  */
-           SAVE_IT (atpos_it, *it, atpos_data);
+           {
+             /* If wrap_it is valid, the current position might be in
+                a word that is wrapped.  So, save the iterator in
+                atpos_it and continue to see if wrapping happens.  */
+             SAVE_IT (atpos_it, *it, atpos_data);
+#ifdef GLYPH_DEBUG
+             atpos_flag = this_line_subject_to_line_prefix;
+#endif /* GLYPH_DEBUG */
+           }
        }
 
       /* Stop when ZV reached.
@@ -9935,6 +9929,9 @@ move_it_in_display_line_to (struct it *it,
                    }
                  /* Otherwise, we can wrap here.  */
                  SAVE_IT (wrap_it, *it, wrap_data);
+#ifdef GLYPH_DEBUG
+                 wrap_flag = this_line_subject_to_line_prefix;
+#endif /* GLYPH_DEBUG */
                }
               /* Update may_wrap for the next iteration.  */
               may_wrap = next_may_wrap;
@@ -10013,6 +10010,9 @@ move_it_in_display_line_to (struct it *it,
                        {
                          SAVE_IT (atpos_it, *it, atpos_data);
                          IT_RESET_X_ASCENT_DESCENT (&atpos_it);
+#ifdef GLYPH_DEBUG
+                         atpos_flag = this_line_subject_to_line_prefix;
+#endif /* GLYPH_DEBUG */
                        }
                    }
                  else
@@ -10027,6 +10027,9 @@ move_it_in_display_line_to (struct it *it,
                        {
                          SAVE_IT (atx_it, *it, atx_data);
                          IT_RESET_X_ASCENT_DESCENT (&atx_it);
+#ifdef GLYPH_DEBUG
+                         atx_flag = this_line_subject_to_line_prefix;
+#endif /* GLYPH_DEBUG */
                        }
                    }
                }
@@ -10041,12 +10044,27 @@ move_it_in_display_line_to (struct it *it,
                          && FRAME_WINDOW_P (it->f)
                          && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
                              ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
-                             : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
+                             : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
+                 /* There is no line prefix, next to which the
+                    iterator _must_ produce a minimum of one actual
+                    glyph.  */
+                 && (!this_line_subject_to_line_prefix
+                     /* Or this is the second glyph to be produced
+                        beyond the confines of the line.  */
+                     || (i != 0
+                         && (x > it->last_visible_x
+                             || (x == it->last_visible_x
+                                 && FRAME_WINDOW_P (it->f)
+                                 && ((it->bidi_p
+                                      && it->bidi_it.paragraph_dir == R2L)
+                                     ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                                     : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))))
                {
                  bool moved_forward = false;
 
                  if (/* IT->hpos == 0 means the very first glyph
-                        doesn't fit on the line, e.g. a wide image.  */
+                        doesn't fit on the line, e.g. a wide
+                        image.  */
                      it->hpos == 0
                      || (new_x == it->last_visible_x
                          && FRAME_WINDOW_P (it->f)))
@@ -10107,6 +10125,9 @@ move_it_in_display_line_to (struct it *it,
                                  SAVE_IT (atpos_it, *it, atpos_data);
                                  atpos_it.current_x = x_before_this_char;
                                  atpos_it.hpos = hpos_before_this_char;
+#ifdef GLYPH_DEBUG
+                                 atpos_flag = this_line_subject_to_line_prefix;
+#endif /* GLYPH_DEBUG */
                                }
                            }
 
@@ -10204,6 +10225,9 @@ move_it_in_display_line_to (struct it *it,
                  if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
                    {
                      SAVE_IT (atpos_it, *it, atpos_data);
+#ifdef GLYPH_DEBUG
+                     atpos_flag = this_line_subject_to_line_prefix;
+#endif /* GLYPH_DEBUG */
                      IT_RESET_X_ASCENT_DESCENT (&atpos_it);
                    }
                }
@@ -10302,24 +10326,24 @@ move_it_in_display_line_to (struct it *it,
       if (it->method == GET_FROM_BUFFER)
        prev_pos = IT_CHARPOS (*it);
 
-      /* Detect overly-wide wrap-prefixes made of (space ...) display
-        properties.  When such a wrap prefix reaches past the right
-        margin of the window, we need to avoid the call to
-        set_iterator_to_next below, so that it->line_wrap is left at
-        its TRUNCATE value wisely set by handle_line_prefix.
-        Otherwise, set_iterator_to_next will pop the iterator stack,
-        restore it->line_wrap, and we might miss the opportunity to
-        exit the loop and return.  */
-      bool overwide_wrap_prefix =
-       CONSP (it->object) && EQ (XCAR (it->object), Qspace)
-       && it->sp > 0 && it->method == GET_FROM_STRETCH
-       && it->current_x >= it->last_visible_x
-       && it->continuation_lines_width > 0
-       && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
-      /* The current display element has been consumed.  Advance
-        to the next.  */
-      if (!overwide_wrap_prefix)
-       set_iterator_to_next (it, true);
+      /* The current display element has been consumed.  Advance to
+        the next.  */
+      set_iterator_to_next (it, true);
+
+      /* If IT has just finished producing glyphs for the wrap prefix
+        and is proceeding to the next method, there might not be
+        sufficient space remaining in this line to accommodate its
+        glyphs, and one real glyph must be produced to prevent an
+        infinite loop.  Next, clear this flag if such a glyph has
+        already been produced.  */
+
+      if (this_line_subject_to_line_prefix == 1
+         && !it->string_from_prefix_prop_p)
+       this_line_subject_to_line_prefix = 2;
+      else if (this_line_subject_to_line_prefix == 2
+              && !it->string_from_prefix_prop_p)
+       this_line_subject_to_line_prefix = 0;
+
       if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
        SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
       if (IT_CHARPOS (*it) < to_charpos)
@@ -10403,11 +10427,26 @@ move_it_in_display_line_to (struct it *it,
       && wrap_it.sp >= 0
       && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
          || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
-    RESTORE_IT (it, &wrap_it, wrap_data);
+    {
+#ifdef GLYPH_DEBUG
+      this_line_subject_to_line_prefix = wrap_flag;
+#endif /* GLYPH_DEBUG */
+      RESTORE_IT (it, &wrap_it, wrap_data);
+    }
   else if (atpos_it.sp >= 0)
-    RESTORE_IT (it, &atpos_it, atpos_data);
+    {
+#ifdef GLYPH_DEBUG
+      this_line_subject_to_line_prefix = atpos_flag;
+#endif /* GLYPH_DEBUG */
+      RESTORE_IT (it, &atpos_it, atpos_data);
+    }
   else if (atx_it.sp >= 0)
-    RESTORE_IT (it, &atx_it, atx_data);
+    {
+#ifdef GLYPH_DEBUG
+      this_line_subject_to_line_prefix = atx_flag;
+#endif /* GLYPH_DEBUG */
+      RESTORE_IT (it, &atx_it, atx_data);
+    }
 
  done:
 
@@ -10481,13 +10520,9 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int 
to_x, int to_y, int to_vpos
   int line_height, line_start_x = 0, reached = 0;
   int max_current_x = 0;
   void *backup_data = NULL;
-  ptrdiff_t orig_charpos = -1;
-  enum it_method orig_method = NUM_IT_METHODS;
 
   for (;;)
     {
-      orig_charpos = IT_CHARPOS (*it);
-      orig_method = it->method;
       if (op & MOVE_TO_VPOS)
        {
          /* If no TO_CHARPOS and no TO_X specified, stop at the
@@ -10759,21 +10794,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int 
to_x, int to_y, int to_vpos
                }
            }
          else
-           {
-             /* Make sure we do advance, otherwise we might infloop.
-                This could happen when the first display element is
-                wider than the window, or if we have a wrap-prefix
-                that doesn't leave enough space after it to display
-                even a single character.  We only do this for moving
-                through buffer text, as with display/overlay strings
-                we'd need to also compare it->object's, and this is
-                unlikely to happen in that case anyway.  */
-             if (IT_CHARPOS (*it) == orig_charpos
-                 && it->method == orig_method
-                 && orig_method == GET_FROM_BUFFER)
-               set_iterator_to_next (it, false);
-             it->continuation_lines_width += it->current_x;
-           }
+           it->continuation_lines_width += it->current_x;
          break;
 
        default:
@@ -10782,6 +10803,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int 
to_x, int to_y, int to_vpos
 
       /* Reset/increment for the next run.  */
       it->current_x = line_start_x;
+      it->wrap_prefix_width = 0;
       line_start_x = 0;
       it->hpos = 0;
       it->line_number_produced_p = false;
@@ -10812,6 +10834,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int 
to_x, int to_y, int to_vpos
     {
       it->continuation_lines_width += it->current_x;
       it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
+      it->wrap_prefix_width = 0;
       it->current_y += it->max_ascent + it->max_descent;
       ++it->vpos;
       last_height = it->max_ascent + it->max_descent;
@@ -10871,6 +10894,7 @@ move_it_vertically_backward (struct it *it, int dy)
   reseat_1 (it, it->current.pos, true);
 
   /* We are now surely at a line start.  */
+  it->wrap_prefix_width = 0;
   it->current_x = it->hpos = 0;        /* FIXME: this is incorrect when bidi
                                   reordering is in effect.  */
   it->continuation_lines_width = 0;
@@ -11149,7 +11173,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
          dvpos--;
        }
 
-      it->current_x = it->hpos = 0;
+      it->current_x = it->hpos = it->wrap_prefix_width = 0;
 
       /* Above call may have moved too far if continuation lines
         are involved.  Scan forward and see if it did.  */
@@ -11158,7 +11182,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
       move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
       it->vpos -= it2.vpos;
       it->current_y -= it2.current_y;
-      it->current_x = it->hpos = 0;
+      it->current_x = it->hpos = it->wrap_prefix_width = 0;
 
       /* If we moved too far back, move IT some lines forward.  */
       if (it2.vpos > -dvpos)
@@ -11437,7 +11461,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object 
from, Lisp_Object to,
         IT.current_x will be incorrectly set to zero at some arbitrary
         non-zero X coordinate.  */
       move_it_by_lines (&it, 0);
-      it.current_x = it.hpos = 0;
+      it.current_x = it.hpos = it.wrap_prefix_width = 0;
       if (IT_CHARPOS (it) != start)
        {
          void *it1data = NULL;
@@ -11490,7 +11514,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object 
from, Lisp_Object to,
   /* If FROM is on a newline, pretend that we start at the beginning
      of the next line, because the newline takes no place on display.  */
   if (FETCH_BYTE (start) == '\n')
-    it.current_x = 0;
+    it.current_x = 0, it.wrap_prefix_width = 0;
   if (!NILP (x_limit))
     {
       it.last_visible_x = max_x;
@@ -12801,7 +12825,7 @@ resize_mini_window (struct window *w, bool exact_p)
      displaying changes from under them.  Such a resizing can happen,
      for instance, when which-func prints a long message while
      we are running fontification-functions.  We're running these
-     functions with safe_call which binds inhibit-redisplay to t.  */
+     functions with dsafe_call which binds inhibit-redisplay to t.  */
   if (!NILP (Vinhibit_redisplay))
     return false;
 
@@ -12820,7 +12844,7 @@ resize_mini_window (struct window *w, bool exact_p)
   if (FRAME_MINIBUF_ONLY_P (f))
     {
       if (!NILP (resize_mini_frames))
-       safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
+       dsafe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
     }
   else
     {
@@ -13067,7 +13091,7 @@ set_message (Lisp_Object string)
     {
       specpdl_ref count = SPECPDL_INDEX ();
       specbind (Qinhibit_quit, Qt);
-      message = safe_call1 (Vset_message_function, string);
+      message = dsafe_call1 (Vset_message_function, string);
       unbind_to (count, Qnil);
 
       if (STRINGP (message))
@@ -13146,7 +13170,7 @@ clear_message (bool current_p, bool last_displayed_p)
         {
           specpdl_ref count = SPECPDL_INDEX ();
           specbind (Qinhibit_quit, Qt);
-          preserve = safe_call (1, Vclear_message_function);
+          preserve = dsafe_calln (false, Vclear_message_function);
           unbind_to (count, Qnil);
         }
 
@@ -13757,7 +13781,7 @@ prepare_menu_bars (void)
                windows = Fcons (this, windows);
            }
        }
-      safe__call1 (true, Vpre_redisplay_function, windows);
+      dsafe_calln (true, Vpre_redisplay_function, windows);
     }
 
   /* Update all frame titles based on their buffer names, etc.  We do
@@ -14402,7 +14426,7 @@ display_tab_bar_line (struct it *it, int height)
   row->truncated_on_left_p = false;
   row->truncated_on_right_p = false;
 
-  it->current_x = it->hpos = 0;
+  it->current_x = it->hpos = it->wrap_prefix_width = 0;
   it->current_y += row->height;
   ++it->vpos;
   ++it->glyph_row;
@@ -15426,7 +15450,7 @@ display_tool_bar_line (struct it *it, int height)
   row->truncated_on_left_p = false;
   row->truncated_on_right_p = false;
 
-  it->current_x = it->hpos = 0;
+  it->current_x = it->hpos = it->wrap_prefix_width = 0;
   it->current_y += row->height;
   ++it->vpos;
   ++it->glyph_row;
@@ -17126,6 +17150,7 @@ redisplay_internal (void)
                         NULL, DEFAULT_FACE_ID);
          it.current_x = this_line_start_x;
          it.current_y = this_line_y;
+         it.wrap_prefix_width = 0;
          it.vpos = this_line_vpos;
 
          if (current_buffer->long_line_optimizations_p
@@ -18591,11 +18616,8 @@ run_window_scroll_functions (Lisp_Object window, 
struct text_pos startp)
 
   if (!NILP (Vwindow_scroll_functions))
     {
-      specpdl_ref count = SPECPDL_INDEX ();
-      specbind (Qinhibit_quit, Qt);
       safe_run_hooks_2
        (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
-      unbind_to (count, Qnil);
       SET_TEXT_POS_FROM_MARKER (startp, w->start);
       /* In case the hook functions switch buffers.  */
       set_buffer_internal (XBUFFER (w->contents));
@@ -18647,7 +18669,7 @@ cursor_row_fully_visible_p (struct window *w, bool 
force_p,
       XSETWINDOW (window, w);
       /* Implementation note: if the function we call here signals an
         error, we will NOT scroll when the cursor is partially-visible.  */
-      Lisp_Object val = safe_call1 (mclfv_p, window);
+      Lisp_Object val = dsafe_call1 (mclfv_p, window);
       if (NILP (val))
        return true;
       else if (just_test_user_preference_p)
@@ -20215,7 +20237,7 @@ redisplay_window (Lisp_Object window, bool 
just_this_one_p)
             propagated its info to `w' anyway.  */
          w->redisplay = false;
          XBUFFER (w->contents)->text->redisplay = false;
-         safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
+         dsafe_calln (true, Vpre_redisplay_function, Fcons (window, Qnil));
 
          if (w->redisplay || XBUFFER (w->contents)->text->redisplay
              || ((EQ (Vdisplay_line_numbers, Qrelative)
@@ -20575,7 +20597,7 @@ redisplay_window (Lisp_Object window, bool 
just_this_one_p)
       it.current_y = 0;
     }
 
-  it.current_x = it.hpos = 0;
+  it.current_x = it.wrap_prefix_width = it.hpos = 0;
 
   /* Set the window start position here explicitly, to avoid an
      infinite loop in case the functions in window-scroll-functions
@@ -22543,7 +22565,7 @@ try_window_id (struct window *w)
       /* We may start in a continuation line.  If so, we have to
         get the right continuation_lines_width and current_x.  */
       it.continuation_lines_width = last_row->continuation_lines_width;
-      it.hpos = it.current_x = 0;
+      it.hpos = it.current_x = it.wrap_prefix_width = 0;
 
       /* Display the rest of the lines at the window end.  */
       it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
@@ -23148,6 +23170,7 @@ insert_left_trunc_glyphs (struct it *it)
   /* Get the truncation glyphs.  */
   truncate_it = *it;
   truncate_it.current_x = 0;
+  truncate_it.wrap_prefix_width = 0;
   truncate_it.face_id = DEFAULT_FACE_ID;
   truncate_it.glyph_row = &scratch_glyph_row;
   truncate_it.area = TEXT_AREA;
@@ -23910,6 +23933,10 @@ extend_face_to_end_of_line (struct it *it)
          for (it->current_x = 0; g < e; g++)
            it->current_x += g->pixel_width;
 
+         if (it->continuation_lines_width
+             && it->string_from_prefix_prop_p)
+           it->wrap_prefix_width = it->current_x;
+
          it->area = LEFT_MARGIN_AREA;
          it->face_id = default_face->id;
          while (it->glyph_row->used[LEFT_MARGIN_AREA]
@@ -24680,7 +24707,7 @@ maybe_produce_line_number (struct it *it)
   /* Produce the glyphs for the line number.  */
   struct it tem_it;
   char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
-  bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
+  bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE;
   ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */
   int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
   int current_lnum_face_id
@@ -24975,6 +25002,7 @@ display_line (struct it *it, int cursor_vpos)
   int first_visible_x = it->first_visible_x;
   int last_visible_x = it->last_visible_x;
   int x_incr = 0;
+  int this_line_subject_to_line_prefix = 0;
 
   /* We always start displaying at hpos zero even if hscrolled.  */
   eassert (it->hpos == 0 && it->current_x == 0);
@@ -25051,7 +25079,10 @@ display_line (struct it *it, int cursor_vpos)
       if (it->current_x < it->first_visible_x
          && (move_result == MOVE_NEWLINE_OR_CR
              || move_result == MOVE_POS_MATCH_OR_ZV))
-       it->current_x = it->first_visible_x;
+       {
+         it->current_x = it->first_visible_x;
+         it->wrap_prefix_width = 0;
+       }
 
       /* In case move_it_in_display_line_to above "produced" the line
         number.  */
@@ -25080,6 +25111,7 @@ display_line (struct it *it, int cursor_vpos)
       /* We only do this when not calling move_it_in_display_line_to
         above, because that function calls itself handle_line_prefix.  */
       handle_line_prefix (it);
+      this_line_subject_to_line_prefix = it->string_from_prefix_prop_p;
     }
   else
     {
@@ -25246,12 +25278,15 @@ display_line (struct it *it, int cursor_vpos)
             process the prefix now.  */
          if (it->area == TEXT_AREA && pending_handle_line_prefix)
            {
-             /* Line numbers should precede the line-prefix or wrap-prefix.  */
+             /* Line numbers should precede the line-prefix or
+                wrap-prefix.  */
              if (line_number_needed)
                maybe_produce_line_number (it);
 
              pending_handle_line_prefix = false;
              handle_line_prefix (it);
+             this_line_subject_to_line_prefix
+               = it->string_from_prefix_prop_p;
            }
          continue;
        }
@@ -25272,7 +25307,16 @@ display_line (struct it *it, int cursor_vpos)
       if (/* Not a newline.  */
          nglyphs > 0
          /* Glyphs produced fit entirely in the line.  */
-         && it->current_x < it->last_visible_x)
+         && (it->current_x < it->last_visible_x
+             /* Or a line or wrap prefix is in effect, and not
+                truncating the glyph produced immediately after it
+                would cause an infinite cycle.  */
+             || (it->line_wrap != TRUNCATE
+                 /* This code is not valid if multiple glyphs were
+                    produced, as some of these glyphs might remain
+                    within this line.  */
+                 && nglyphs == 1
+                 && this_line_subject_to_line_prefix)))
        {
          it->hpos += nglyphs;
          row->ascent = max (row->ascent, it->max_ascent);
@@ -25323,7 +25367,20 @@ display_line (struct it *it, int cursor_vpos)
                          && FRAME_WINDOW_P (it->f)
                          && (row->reversed_p
                              ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
-                             : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
+                             : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
+                 /* There is no line prefix, next to which the
+                    iterator _must_ produce a minimum of one actual
+                    glyph.  */
+                 && (!this_line_subject_to_line_prefix
+                     /* Or this is the second glyph to be produced
+                        beyond the confines of the line.  */
+                     || (i != 0
+                         && (x > it->last_visible_x
+                             || (x == it->last_visible_x
+                                 && FRAME_WINDOW_P (it->f)
+                                 && (row->reversed_p
+                                     ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
+                                     : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))))
                {
                  /* End of a continued line.  */
 
@@ -25620,24 +25677,23 @@ display_line (struct it *it, int cursor_vpos)
          break;
        }
 
-      /* Detect overly-wide wrap-prefixes made of (space ...) display
-        properties.  When such a wrap prefix reaches past the right
-        margin of the window, we need to avoid the call to
-        set_iterator_to_next below, so that it->line_wrap is left at
-        its TRUNCATE value wisely set by handle_line_prefix.
-        Otherwise, set_iterator_to_next will pop the iterator stack,
-        restore it->line_wrap, and redisplay might infloop.  */
-      bool overwide_wrap_prefix =
-       CONSP (it->object) && EQ (XCAR (it->object), Qspace)
-       && it->sp > 0 && it->method == GET_FROM_STRETCH
-       && it->current_x >= it->last_visible_x
-       && it->continuation_lines_width > 0
-       && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
-
       /* Proceed with next display element.  Note that this skips
         over lines invisible because of selective display.  */
-      if (!overwide_wrap_prefix)
-       set_iterator_to_next (it, true);
+      set_iterator_to_next (it, true);
+
+      /* If IT has just finished producing glyphs for the wrap prefix
+        and is proceeding to the next method, there might not be
+        sufficient space remaining in this line to accommodate its
+        glyphs, and one real glyph must be produced to prevent an
+        infinite loop.  Next, clear this flag if such a glyph has
+        already been produced.  */
+
+      if (this_line_subject_to_line_prefix == 1
+         && !it->string_from_prefix_prop_p)
+       this_line_subject_to_line_prefix = 2;
+      else if (this_line_subject_to_line_prefix == 2
+              && !it->string_from_prefix_prop_p)
+       this_line_subject_to_line_prefix = 0;
 
       /* If we truncate lines, we are done when the last displayed
         glyphs reach past the right margin of the window.  */
@@ -25883,7 +25939,7 @@ display_line (struct it *it, int cursor_vpos)
      HPOS) = (0 0).  Vertical positions are incremented.  As a
      convenience for the caller, IT->glyph_row is set to the next
      row to be used.  */
-  it->current_x = it->hpos = 0;
+  it->wrap_prefix_width = it->current_x = it->hpos = 0;
   it->current_y += row->height;
   /* Restore the first and last visible X if we adjusted them for
      current-line hscrolling.  */
@@ -26362,7 +26418,7 @@ Value is the new character position of point.  */)
     {
       struct text_pos pt;
       struct it it;
-      int pt_x, target_x, pixel_width, pt_vpos;
+      int pt_x, pt_wrap_prefix_x, target_x, pixel_width, pt_vpos;
       bool at_eol_p;
       bool overshoot_expected = false;
       bool target_is_eol_p = false;
@@ -26394,6 +26450,7 @@ Value is the new character position of point.  */)
     reseat:
       reseat_at_previous_visible_line_start (&it);
       it.current_x = it.hpos = it.current_y = it.vpos = 0;
+      it.wrap_prefix_width = 0;
       if (IT_CHARPOS (it) != PT)
        {
          move_it_to (&it, overshoot_expected ? PT - 1 : PT,
@@ -26412,6 +26469,7 @@ Value is the new character position of point.  */)
            move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
        }
       pt_x = it.current_x;
+      pt_wrap_prefix_x = it.wrap_prefix_width;
       pt_vpos = it.vpos;
       if (dir > 0 || overshoot_expected)
        {
@@ -26426,10 +26484,11 @@ Value is the new character position of point.  */)
          it.glyph_row = NULL;
          PRODUCE_GLYPHS (&it); /* compute it.pixel_width */
          it.glyph_row = row;
-         /* PRODUCE_GLYPHS advances it.current_x, so we must restore
-            it, lest it will become out of sync with it's buffer
+         /* PRODUCE_GLYPHS advances it.current_x, so it must be
+            restored, lest it become out of sync with its buffer
             position.  */
          it.current_x = pt_x;
+         it.wrap_prefix_width = pt_wrap_prefix_x;
        }
       else
        at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
@@ -26474,6 +26533,7 @@ Value is the new character position of point.  */)
                it.last_visible_x = DISP_INFINITY;
              reseat_at_previous_visible_line_start (&it);
              it.current_x = it.current_y = it.hpos = 0;
+             it.wrap_prefix_width = 0;
              if (pt_vpos != 0)
                move_it_by_lines (&it, pt_vpos);
            }
@@ -27092,7 +27152,7 @@ display_mode_lines (struct window *w)
         can reasonably tell whether a mouse click will select w.  */
       XSETWINDOW (window, w);
       if (FUNCTIONP (default_help))
-       wset_mode_line_help_echo (w, safe_call1 (default_help, window));
+       wset_mode_line_help_echo (w, dsafe_call1 (default_help, window));
       else if (STRINGP (default_help))
        wset_mode_line_help_echo (w, default_help);
       else
@@ -27431,6 +27491,7 @@ display_mode_element (struct it *it, int depth, int 
field_width, int precision,
                    /* PROPS might cause set-text-properties to signal
                       an error, so we call it via internal_condition_case_n,
                       to avoid an infloop in redisplay due to the error.  */
+                   /* FIXME: Use 'SAFE_CALLMANY'?  */
                    internal_condition_case_n (safe_set_text_properties,
                                               4,
                                               ((Lisp_Object [])
@@ -27438,7 +27499,7 @@ display_mode_element (struct it *it, int depth, int 
field_width, int precision,
                                                   Flength (elt),
                                                   props,
                                                   elt}),
-                                              Qt, safe_eval_handler);
+                                              Qt, dsafe_eval_handler);
                    /* Add this item to mode_line_proptrans_alist.  */
                    mode_line_proptrans_alist
                      = Fcons (Fcons (elt, props),
@@ -27691,7 +27752,7 @@ display_mode_element (struct it *it, int depth, int 
field_width, int precision,
            if (CONSP (XCDR (elt)))
              {
                Lisp_Object spec;
-               spec = safe__eval (true, XCAR (XCDR (elt)));
+               spec = dsafe_eval (XCAR (XCDR (elt)));
                /* The :eval form could delete the frame stored in the
                   iterator, which will cause a crash if we try to
                   access faces and other fields (e.g., FRAME_KBOARD)
@@ -28663,7 +28724,7 @@ decode_mode_spec (struct window *w, register int c, int 
field_width,
        Lisp_Object val = Qnil;
 
        if (STRINGP (curdir))
-         val = safe_call1 (intern ("file-remote-p"), curdir);
+         val = dsafe_call1 (intern ("file-remote-p"), curdir);
 
        val = unbind_to (count, val);
 
@@ -29554,9 +29615,9 @@ dump_glyph_string (struct glyph_string *s)
 # define ALLOCATE_HDC(hdc, f)                  \
   Lisp_Object prev_quit = Vinhibit_quit;       \
   Vinhibit_quit = Qt;                          \
-  HDC hdc = get_frame_dc ((f))
+  HDC hdc = get_frame_dc (f)
 # define RELEASE_HDC(hdc, f)                   \
-  release_frame_dc ((f), (hdc));               \
+  release_frame_dc (f, hdc);                   \
   Vinhibit_quit = prev_quit
 #else
 # define ALLOCATE_HDC(hdc, f)
@@ -30985,6 +31046,26 @@ draw_glyphs (struct window *w, int x, struct glyph_row 
*row,
          }
     }
 
+#ifdef HAVE_RSVG
+  /* Update SVG image glyphs with mouse face features.  FIXME: it
+     should be possible to have this behavior with transparent
+     background PNG.  */
+  if (hl == DRAW_MOUSE_FACE)
+    {
+      Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
+      for (s = head; s; s = s->next)
+       if (s->first_glyph->type == IMAGE_GLYPH)
+         if (s->img
+             && (EQ (image_spec_value (s->img->spec, QCtype, NULL), Qsvg)))
+           {
+             ptrdiff_t id;
+             id = lookup_image (f, s->img->spec, hlinfo->mouse_face_face_id);
+             s->img = IMAGE_FROM_ID (f, id);
+             prepare_image_for_display (f, s->img);
+           }
+    }
+#endif
+
   /* Draw all strings.  */
   for (s = head; s; s = s->next)
     FRAME_RIF (f)->draw_glyph_string (s);
@@ -32600,7 +32681,19 @@ gui_produce_glyphs (struct it *it)
          if (font->space_width > 0)
            {
              int tab_width = it->tab_width * font->space_width;
-             int x = it->current_x + it->continuation_lines_width;
+             /* wrap-prefix strings are prepended to continuation
+                lines, so the width of tab characters inside should
+                be computed from the start of this screen line rather
+                than as a product of the total width of the physical
+                line being wrapped.  */
+             int x = it->current_x + (it->string_from_prefix_prop_p
+                                      /* Subtract the width of the
+                                         prefix from it->current_x if
+                                         it exists.  */
+                                      ? 0 : (it->continuation_lines_width
+                                             ? (it->continuation_lines_width
+                                                - it->wrap_prefix_width)
+                                             : 0));
              int x0 = x;
              /* Adjust for line numbers, if needed.   */
              if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
@@ -33071,7 +33164,13 @@ gui_produce_glyphs (struct it *it)
      because this isn't true for images with `:ascent 100'.  */
   eassert (it->ascent >= 0 && it->descent >= 0);
   if (it->area == TEXT_AREA)
-    it->current_x += it->pixel_width;
+    {
+      it->current_x += it->pixel_width;
+
+      if (it->continuation_lines_width
+         && it->string_from_prefix_prop_p)
+       it->wrap_prefix_width = it->current_x;
+    }
 
   if (extra_line_spacing > 0)
     {
@@ -33590,13 +33689,18 @@ notice_overwritten_cursor (struct window *w, enum 
glyph_row_area area,
 
 void
 gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
-                       enum glyph_row_area area, int overlaps)
+                         enum glyph_row_area area, int overlaps)
 {
   int i, x;
 
   block_input ();
 
-  x = 0;
+  /* row->x might be smaller than zero when produced from an iterator
+     under horizontal scrolling.  Offset all measurements by this
+     basic value, lest hscrolled text with overlaps be displayed with
+     its overlapping portions misaligned.  */
+  x = row->x;
+
   for (i = 0; i < row->used[area];)
     {
       if (row->glyphs[area][i].overlaps_vertically_p)
@@ -37773,6 +37877,8 @@ cursor shapes.  */);
   DEFSYM (Qthin_space, "thin-space");
   DEFSYM (Qzero_width, "zero-width");
 
+  DEFSYM (Qdebug_early__muted, "debug-early--muted");
+
   DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
               doc: /* Function run just before redisplay.
 It is called with one argument, which is the set of windows that are to
diff --git a/src/xfaces.c b/src/xfaces.c
index 7385c4c7dd2..b9a78328661 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -1,6 +1,6 @@
 /* xfaces.c -- "Face" primitives.
 
-Copyright (C) 1993-1994, 1998-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1994, 1998-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -293,15 +293,15 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 
 /* True if face attribute ATTR is unspecified.  */
 
-#define UNSPECIFIEDP(ATTR) EQ ((ATTR), Qunspecified)
+#define UNSPECIFIEDP(ATTR) EQ (ATTR, Qunspecified)
 
 /* True if face attribute ATTR is `ignore-defface'.  */
 
-#define IGNORE_DEFFACE_P(ATTR) EQ ((ATTR), QCignore_defface)
+#define IGNORE_DEFFACE_P(ATTR) EQ (ATTR, QCignore_defface)
 
 /* True if face attribute ATTR is `reset'.  */
 
-#define RESET_P(ATTR) EQ ((ATTR), Qreset)
+#define RESET_P(ATTR) EQ (ATTR, Qreset)
 
 /* Size of hash table of realized faces in face caches (should be a
    prime number).  */
@@ -1756,26 +1756,26 @@ the WIDTH times as wide as FACE on FRAME.  */)
 
 /* Access face attributes of face LFACE, a Lisp vector.  */
 
-#define LFACE_FAMILY(LFACE)        AREF ((LFACE), LFACE_FAMILY_INDEX)
-#define LFACE_FOUNDRY(LFACE)       AREF ((LFACE), LFACE_FOUNDRY_INDEX)
-#define LFACE_HEIGHT(LFACE)        AREF ((LFACE), LFACE_HEIGHT_INDEX)
-#define LFACE_WEIGHT(LFACE)        AREF ((LFACE), LFACE_WEIGHT_INDEX)
-#define LFACE_SLANT(LFACE)         AREF ((LFACE), LFACE_SLANT_INDEX)
-#define LFACE_UNDERLINE(LFACE)      AREF ((LFACE), LFACE_UNDERLINE_INDEX)
-#define LFACE_INVERSE(LFACE)       AREF ((LFACE), LFACE_INVERSE_INDEX)
-#define LFACE_FOREGROUND(LFACE)     AREF ((LFACE), LFACE_FOREGROUND_INDEX)
-#define LFACE_BACKGROUND(LFACE)     AREF ((LFACE), LFACE_BACKGROUND_INDEX)
-#define LFACE_STIPPLE(LFACE)       AREF ((LFACE), LFACE_STIPPLE_INDEX)
-#define LFACE_SWIDTH(LFACE)        AREF ((LFACE), LFACE_SWIDTH_INDEX)
-#define LFACE_OVERLINE(LFACE)      AREF ((LFACE), LFACE_OVERLINE_INDEX)
-#define LFACE_STRIKE_THROUGH(LFACE) AREF ((LFACE), LFACE_STRIKE_THROUGH_INDEX)
-#define LFACE_BOX(LFACE)           AREF ((LFACE), LFACE_BOX_INDEX)
-#define LFACE_FONT(LFACE)          AREF ((LFACE), LFACE_FONT_INDEX)
-#define LFACE_INHERIT(LFACE)       AREF ((LFACE), LFACE_INHERIT_INDEX)
-#define LFACE_FONTSET(LFACE)       AREF ((LFACE), LFACE_FONTSET_INDEX)
-#define LFACE_EXTEND(LFACE)        AREF ((LFACE), LFACE_EXTEND_INDEX)
+#define LFACE_FAMILY(LFACE)        AREF (LFACE, LFACE_FAMILY_INDEX)
+#define LFACE_FOUNDRY(LFACE)       AREF (LFACE, LFACE_FOUNDRY_INDEX)
+#define LFACE_HEIGHT(LFACE)        AREF (LFACE, LFACE_HEIGHT_INDEX)
+#define LFACE_WEIGHT(LFACE)        AREF (LFACE, LFACE_WEIGHT_INDEX)
+#define LFACE_SLANT(LFACE)         AREF (LFACE, LFACE_SLANT_INDEX)
+#define LFACE_UNDERLINE(LFACE)      AREF (LFACE, LFACE_UNDERLINE_INDEX)
+#define LFACE_INVERSE(LFACE)       AREF (LFACE, LFACE_INVERSE_INDEX)
+#define LFACE_FOREGROUND(LFACE)     AREF (LFACE, LFACE_FOREGROUND_INDEX)
+#define LFACE_BACKGROUND(LFACE)     AREF (LFACE, LFACE_BACKGROUND_INDEX)
+#define LFACE_STIPPLE(LFACE)       AREF (LFACE, LFACE_STIPPLE_INDEX)
+#define LFACE_SWIDTH(LFACE)        AREF (LFACE, LFACE_SWIDTH_INDEX)
+#define LFACE_OVERLINE(LFACE)      AREF (LFACE, LFACE_OVERLINE_INDEX)
+#define LFACE_STRIKE_THROUGH(LFACE) AREF (LFACE, LFACE_STRIKE_THROUGH_INDEX)
+#define LFACE_BOX(LFACE)           AREF (LFACE, LFACE_BOX_INDEX)
+#define LFACE_FONT(LFACE)          AREF (LFACE, LFACE_FONT_INDEX)
+#define LFACE_INHERIT(LFACE)       AREF (LFACE, LFACE_INHERIT_INDEX)
+#define LFACE_FONTSET(LFACE)       AREF (LFACE, LFACE_FONTSET_INDEX)
+#define LFACE_EXTEND(LFACE)        AREF (LFACE, LFACE_EXTEND_INDEX)
 #define LFACE_DISTANT_FOREGROUND(LFACE) \
-  AREF ((LFACE), LFACE_DISTANT_FOREGROUND_INDEX)
+  AREF (LFACE, LFACE_DISTANT_FOREGROUND_INDEX)
 
 /* True if LFACE is a Lisp face.  A Lisp face is a vector of size
    LFACE_VECTOR_SIZE which has the symbol `face' in slot 0.  */
@@ -2232,7 +2232,7 @@ merge_face_heights (Lisp_Object from, Lisp_Object to, 
Lisp_Object invalid)
     {
       /* Call function with current height as argument.
         From is the new height.  */
-      result = safe_call1 (from, to);
+      result = safe_calln (from, to);
 
       /* Ensure that if TO was absolute, so is the result.  */
       if (FIXNUMP (to) && !FIXNUMP (result))
@@ -6646,7 +6646,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
   /* Get the `face' or `mouse_face' text property at POS, and
      determine the next position at which the property changes.  */
   prop = Fget_text_property (position, propname, w->contents);
-  XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
+  XSETFASTINT (limit1, min (limit, endpos));
   end = Fnext_single_property_change (position, propname, w->contents, limit1);
   if (FIXNUMP (end))
     endpos = XFIXNUM (end);
@@ -6782,7 +6782,7 @@ face_for_overlay_string (struct window *w, ptrdiff_t pos,
   /* Get the `face' or `mouse_face' text property at POS, and
      determine the next position at which the property changes.  */
   prop = Fget_text_property (position, propname, w->contents);
-  XSETFASTINT (limit1, (limit < endpos ? limit : endpos));
+  XSETFASTINT (limit1, min (limit, endpos));
   end = Fnext_single_property_change (position, propname, w->contents, limit1);
   if (FIXNUMP (end))
     endpos = XFIXNUM (end);
@@ -7333,8 +7333,7 @@ only for this purpose.  */);
     doc: /* Hash table of global face definitions (for internal use only.)  
*/);
   Vface_new_frame_defaults =
     /* 33 entries is enough to fit all basic faces */
-    make_hash_table (hashtest_eq, 33, DEFAULT_REHASH_SIZE,
-                     DEFAULT_REHASH_THRESHOLD, Qnil, false);
+    make_hash_table (&hashtest_eq, 33, Weak_None, false);
 
   DEFVAR_LISP ("face-default-stipple", Vface_default_stipple,
     doc: /* Default stipple pattern used on monochrome displays.
diff --git a/src/xfns.c b/src/xfns.c
index eadf46b44c4..d610c839bfc 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -1,6 +1,6 @@
 /* Functions for the X Window System.
 
-Copyright (C) 1989, 1992-2023 Free Software Foundation, Inc.
+Copyright (C) 1989, 1992-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/xfont.c b/src/xfont.c
index ce32c7a2188..b112bb4fb39 100644
--- a/src/xfont.c
+++ b/src/xfont.c
@@ -1,5 +1,5 @@
 /* xfont.c -- X core font driver.
-   Copyright (C) 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006-2024 Free Software Foundation, Inc.
    Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H13PRO009
@@ -238,7 +238,7 @@ xfont_chars_supported (Lisp_Object chars, XFontStruct 
*xfont,
 
 static Lisp_Object xfont_scripts_cache;
 
-/* Re-usable vector to store characteristic font properties.   */
+/* Reusable vector to store characteristic font properties.   */
 static Lisp_Object xfont_scratch_props;
 
 /* Return a list of scripts supported by the font of FONTNAME whose
diff --git a/src/xftfont.c b/src/xftfont.c
index 4d5b855f178..41941509bc2 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -1,5 +1,5 @@
 /* xftfont.c -- XFT font driver.
-   Copyright (C) 2006-2023 Free Software Foundation, Inc.
+   Copyright (C) 2006-2024 Free Software Foundation, Inc.
    Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H13PRO009
diff --git a/src/xgselect.c b/src/xgselect.c
index 7f4f2b04811..252f430b0ec 100644
--- a/src/xgselect.c
+++ b/src/xgselect.c
@@ -1,6 +1,6 @@
 /* Function for handling the GLib event loop.
 
-Copyright (C) 2009-2023 Free Software Foundation, Inc.
+Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/xgselect.h b/src/xgselect.h
index cfc872558b7..87b3591f8cc 100644
--- a/src/xgselect.h
+++ b/src/xgselect.h
@@ -1,6 +1,6 @@
 /* Header for xg_select.
 
-Copyright (C) 2009-2023 Free Software Foundation, Inc.
+Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/xmenu.c b/src/xmenu.c
index 2d405d54deb..ef1eeb5925f 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -1,6 +1,6 @@
 /* X Communication module for terminals which understand the X protocol.
 
-Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2023 Free Software
+Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2024 Free Software
 Foundation, Inc.
 
 Author: Jon Arnold
diff --git a/src/xml.c b/src/xml.c
index b4c849e6a65..85f16746289 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -1,5 +1,5 @@
 /* Interface to libxml2.
-   Copyright (C) 2010-2023 Free Software Foundation, Inc.
+   Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/xrdb.c b/src/xrdb.c
index 046200f0d19..548b1ffca30 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -1,5 +1,5 @@
 /* Deal with the X Resource Manager.
-   Copyright (C) 1990, 1993-1994, 2000-2023 Free Software Foundation,
+   Copyright (C) 1990, 1993-1994, 2000-2024 Free Software Foundation,
    Inc.
 
 Author: Joseph Arceneaux
diff --git a/src/xselect.c b/src/xselect.c
index c38a1f8b6a9..fd0f06eeed9 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -1,5 +1,5 @@
 /* X Selection processing for Emacs.
-   Copyright (C) 1993-1997, 2000-2023 Free Software Foundation, Inc.
+   Copyright (C) 1993-1997, 2000-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -19,6 +19,12 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 /* Rewritten by jwz */
 
 #include <config.h>
+
+/* Work around GCC bug 102671.  */
+#if 10 <= __GNUC__
+# pragma GCC diagnostic ignored "-Wanalyzer-null-dereference"
+#endif
+
 #include <limits.h>
 
 #ifdef HAVE_SYS_TYPES_H
@@ -897,7 +903,7 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, 
Window requestor,
 
       /* Find a valid (non-zero) serial for the selection transfer.
         Any asynchronously trapped errors will then cause the
-        selection transfer to be cancelled.  */
+        selection transfer to be canceled.  */
       transfer->serial = (++selection_serial
                          ? selection_serial
                          : ++selection_serial);
diff --git a/src/xsettings.c b/src/xsettings.c
index f366c9d7fc5..764ccd04a09 100644
--- a/src/xsettings.c
+++ b/src/xsettings.c
@@ -1,6 +1,6 @@
 /* Functions for handling font and other changes dynamically.
 
-Copyright (C) 2009-2023 Free Software Foundation, Inc.
+Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/xsettings.h b/src/xsettings.h
index f1c6f7af1f1..06fcbe183bc 100644
--- a/src/xsettings.h
+++ b/src/xsettings.h
@@ -1,6 +1,6 @@
 /* Functions for handle font changes dynamically.
 
-Copyright (C) 2009-2023 Free Software Foundation, Inc.
+Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/xsmfns.c b/src/xsmfns.c
index 3cf5165242e..8827d08af3e 100644
--- a/src/xsmfns.c
+++ b/src/xsmfns.c
@@ -1,7 +1,7 @@
 /* Session management module for systems which understand the X Session
    management protocol.
 
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/xterm.c b/src/xterm.c
index d01c4da0564..c8a43785564 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1,6 +1,6 @@
 /* X Communication module for terminals which understand the X protocol.
 
-Copyright (C) 1989, 1993-2023 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -616,9 +616,9 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
     - x_clear_errors
 
   Callers using this set should consult the comment(s) on top of the
-  aformentioned functions.  They should not be used when the requests
+  aforementioned functions.  They should not be used when the requests
   being made do not require roundtrips to the X server, and obtaining
-  the details of any error generated is unecessary, as
+  the details of any error generated is unnecessary, as
   `x_uncatch_errors' will always synchronize with the X server, which
   is a potentially slow operation.  */
 
@@ -5036,7 +5036,7 @@ x_dnd_note_self_drop (struct x_display_info *dpyinfo, 
Window target,
   XSETFRAME (lval, f);
   x_dnd_action = None;
   x_dnd_action_symbol
-    = safe_call2 (Vx_dnd_native_test_function,
+    = safe_calln (Vx_dnd_native_test_function,
                  Fposn_at_x_y (make_fixnum (win_x),
                                make_fixnum (win_y),
                                lval, Qnil),
@@ -5173,7 +5173,7 @@ record_event (char *locus, int type)
 
 
 
-/* Miscelaneous event handling functions.  */
+/* Miscellaneous event handling functions.  */
 
 static void
 x_toolkit_position (struct frame *f, int x, int y,
@@ -11296,7 +11296,7 @@ x_clear_frame (struct frame *f)
 
 /* Send a message to frame F telling the event loop to track whether
    or not an hourglass is being displayed.  This is required to ignore
-   the right events when the hourglass is mapped without callig XSync
+   the right events when the hourglass is mapped without calling XSync
    after displaying or hiding the hourglass.  */
 
 static void
@@ -12564,7 +12564,7 @@ x_dnd_process_quit (struct frame *f, Time timestamp)
 /* This function is defined far away from the rest of the XDND code so
    it can utilize `x_any_window_to_frame'.  */
 
-/* Implementors beware!  On most other platforms (where drag-and-drop
+/* Implementers beware!  On most other platforms (where drag-and-drop
    data is not provided via selections, but some kind of serialization
    mechanism), it is usually much easier to implement a suitable
    primitive instead of copying the C code here, and then to build
@@ -13370,13 +13370,12 @@ xi_focus_handle_for_device (struct x_display_info 
*dpyinfo,
         frame's user time.  */
       x_display_set_last_user_time (dpyinfo, event->time,
                                    event->send_event, false);
-
       device->focus_frame = NULL;
 
       /* So, unfortunately, the X Input Extension is implemented such
-        that means XI_Leave events will not have their focus field
-        set if the core focus is transferred to another window after
-        an entry event that pretends to (or really does) set the
+        that XI_Leave events will not have their focus field set if
+        the core focus is transferred to another window after an
+        entry event that pretends to (or really does) set the
         implicit focus.  In addition, if the core focus is set, but
         the extension focus on the client pointer is not, all
         XI_Enter events will have their focus fields set, despite not
@@ -27202,7 +27201,7 @@ xim_open_dpy (struct x_display_info *dpyinfo, char 
*resource_name)
          /* Now try to determine the coding system that should be
             used.  locale is in Host Portable Character Encoding, and
             as such can be passed to build_string as is.  */
-         dpyinfo->xim_coding = safe_call1 (Vx_input_coding_function,
+         dpyinfo->xim_coding = safe_calln (Vx_input_coding_function,
                                            build_string (locale));
        }
     }
@@ -28805,6 +28804,36 @@ x_focus_frame (struct frame *f, bool noactivate)
      friends being set.  */
   block_input ();
 
+#ifdef HAVE_GTK3
+  /* read_minibuf assumes that calling Fx_focus_frame on a frame that
+     is already selected won't move the focus elsewhere, and thereby
+     disrupt any focus redirection to e.g. a minibuffer frame that
+     might be activated between that call being made and the
+     consequent XI_FocusIn/Out events arriving.  This is true whether
+     the focus is ultimately transferred back to the frame it was
+     initially on or not.
+
+     GTK 3 moves the keyboard focus to the edit widget's window
+     whenever it receives a FocusIn event targeting the outer window.
+     This operation gives rise to a FocusOut event that clears
+     device->focus_frame, which in turn prompts xi_handle_focus_change
+     to clear the display's focus frame.  The next FocusIn event
+     destined for the same frame registers as a new focus, which
+     cancels any focus redirection from that frame.
+
+     To prevent this chain of events from disrupting focus redirection
+     when the minibuffer is activated twice in rapid succession while
+     configured to redirect focus to a minibuffer frame, ignore frames
+     which hold the input focus and are connected to a minibuffer
+     window.  (bug#65116)*/
+
+  if (f == dpyinfo->x_focus_frame && !FRAME_HAS_MINIBUF_P (f))
+    {
+      unblock_input ();
+      return;
+    }
+#endif /* HAVE_GTK3 */
+
   if (FRAME_X_EMBEDDED_P (f))
     /* For Xembedded frames, normally the embedder forwards key
        events.  See XEmbed Protocol Specification at
@@ -30661,7 +30690,7 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
            terminal_list = terminal->next_terminal;
            unblock_input ();
            kset_system_key_alist (terminal->kboard,
-                                  safe_call1 (Qvendor_specific_keysyms,
+                                  safe_calln (Qvendor_specific_keysyms,
                                               (vendor
                                                ? build_string (vendor)
                                                : empty_unibyte_string)));
@@ -31503,7 +31532,6 @@ x_term_init (Lisp_Object display_name, char 
*xrm_option, char *resource_name)
                                      dpyinfo->selection_tracking_window,
                                      selection_name,
                                      (XFixesSetSelectionOwnerNotifyMask
-                                      | XFixesSetSelectionOwnerNotifyMask
                                       | XFixesSelectionClientCloseNotifyMask));
        }
 
@@ -32094,7 +32122,7 @@ x_initialize (void)
 
 #ifdef HAVE_X_I18N
 
-/* Notice that a change has occured on F that requires its input
+/* Notice that a change has occurred on F that requires its input
    method state to be reset.  */
 
 static void
@@ -32555,10 +32583,7 @@ If set to a non-float value, there will be no wait at 
all.  */);
 
   DEFVAR_LISP ("x-keysym-table", Vx_keysym_table,
     doc: /* Hash table of character codes indexed by X keysym codes.  */);
-  Vx_keysym_table = make_hash_table (hashtest_eql, 900,
-                                    DEFAULT_REHASH_SIZE,
-                                    DEFAULT_REHASH_THRESHOLD,
-                                    Qnil, false);
+  Vx_keysym_table = make_hash_table (&hashtest_eql, 900, Weak_None, false);
 
   DEFVAR_BOOL ("x-frame-normalize-before-maximize",
               x_frame_normalize_before_maximize,
diff --git a/src/xterm.h b/src/xterm.h
index cb477645bfa..2c00b1e7bec 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1,5 +1,5 @@
 /* Definitions and headers for communication with X protocol.
-   Copyright (C) 1989, 1993-1994, 1998-2023 Free Software Foundation,
+   Copyright (C) 1989, 1993-1994, 1998-2024 Free Software Foundation,
    Inc.
 
 This file is part of GNU Emacs.
@@ -84,7 +84,7 @@ typedef GtkWidget *xt_or_gtk_widget;
 #undef XSync
 /* gdk_window_process_all_updates is deprecated in GDK 3.22.  */
 #if GTK_CHECK_VERSION (3, 22, 0)
-#define XSync(d, b) do { XSync ((d), (b)); } while (false)
+#define XSync(d, b) do { XSync (d, b); } while (false)
 #else
 #define XSync(d, b) do { gdk_window_process_all_updates (); \
                          XSync (d, b);  } while (false)
@@ -1402,7 +1402,7 @@ extern void x_mark_frame_dirty (struct frame *f);
    code after any drawing command, but we can run code whenever
    someone asks for the handle necessary to draw.  */
 #define FRAME_X_DRAWABLE(f)                             \
-  (x_mark_frame_dirty ((f)), FRAME_X_RAW_DRAWABLE ((f)))
+  (x_mark_frame_dirty (f), FRAME_X_RAW_DRAWABLE (f))
 
 #ifdef HAVE_XDBE
 #define FRAME_X_DOUBLE_BUFFERED_P(f)            \
@@ -1447,7 +1447,7 @@ extern void x_mark_frame_dirty (struct frame *f);
          FRAME_X_WINDOW (f))
 
 #else /* !USE_GTK */
-#define FRAME_OUTER_WINDOW(f) (FRAME_X_WINDOW (f))
+#define FRAME_OUTER_WINDOW(f) FRAME_X_WINDOW (f)
 #endif /* !USE_GTK */
 #endif
 
diff --git a/src/xwidget.c b/src/xwidget.c
index 7f30e48c954..58910459142 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -1,6 +1,6 @@
 /* Support for embedding graphical components in a buffer.
 
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/src/xwidget.h b/src/xwidget.h
index 171924e0aaa..34cae383abf 100644
--- a/src/xwidget.h
+++ b/src/xwidget.h
@@ -1,6 +1,6 @@
 /* Support for embedding graphical components in a buffer.
 
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/test/ChangeLog.1 b/test/ChangeLog.1
index 2c412a64519..9693f59c311 100644
--- a/test/ChangeLog.1
+++ b/test/ChangeLog.1
@@ -2952,7 +2952,7 @@
 ;; coding: utf-8
 ;; End:
 
-  Copyright (C) 2008-2023 Free Software Foundation, Inc.
+  Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
   This file is part of GNU Emacs.
 
diff --git a/test/Makefile.in b/test/Makefile.in
index 226fb2f20bc..d19b71a431b 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 2010-2023 Free Software Foundation, Inc.
+# Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/test/README b/test/README
index 9255dbed513..7a3cf871a57 100644
--- a/test/README
+++ b/test/README
@@ -1,4 +1,4 @@
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
 See the end of the file for license conditions.
 
 This directory contains files intended to test various aspects of
diff --git a/test/infra/Dockerfile.emba b/test/infra/Dockerfile.emba
index e29098ec270..8e583fade9f 100644
--- a/test/infra/Dockerfile.emba
+++ b/test/infra/Dockerfile.emba
@@ -1,4 +1,4 @@
-# Copyright (C) 2021-2023 Free Software Foundation, Inc.
+# Copyright (C) 2021-2024 Free Software Foundation, Inc.
 #
 #  This file is part of GNU Emacs.
 #
diff --git a/test/infra/Makefile.in b/test/infra/Makefile.in
index fff7281b566..5ae32e7e005 100644
--- a/test/infra/Makefile.in
+++ b/test/infra/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 2021-2023 Free Software Foundation, Inc.
+# Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/test/infra/gitlab-ci.yml b/test/infra/gitlab-ci.yml
index f106ea4d8de..5299aee746b 100644
--- a/test/infra/gitlab-ci.yml
+++ b/test/infra/gitlab-ci.yml
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2023 Free Software Foundation, Inc.
+# Copyright (C) 2017-2024 Free Software Foundation, Inc.
 #
 #  This file is part of GNU Emacs.
 #
diff --git a/test/lib-src/emacsclient-tests.el 
b/test/lib-src/emacsclient-tests.el
index 8e44f4fe4bf..d7001b0fe9b 100644
--- a/test/lib-src/emacsclient-tests.el
+++ b/test/lib-src/emacsclient-tests.el
@@ -1,6 +1,6 @@
 ;;; emacsclient-tests.el --- Test emacsclient  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/abbrev-tests.el b/test/lisp/abbrev-tests.el
index abac8dd6f0b..bfdfac8be1b 100644
--- a/test/lisp/abbrev-tests.el
+++ b/test/lisp/abbrev-tests.el
@@ -1,6 +1,6 @@
 ;;; abbrev-tests.el --- Test suite for abbrevs  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Eli Zaretskii <eliz@gnu.org>
 ;; Keywords: abbrevs
diff --git a/test/lisp/align-tests.el b/test/lisp/align-tests.el
index f8dd7dcfb9b..cd309ea07bf 100644
--- a/test/lisp/align-tests.el
+++ b/test/lisp/align-tests.el
@@ -1,6 +1,6 @@
 ;;; align-tests.el --- Test suite for aligns  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/allout-tests.el b/test/lisp/allout-tests.el
index 9b70f86c09a..bdf159f54e4 100644
--- a/test/lisp/allout-tests.el
+++ b/test/lisp/allout-tests.el
@@ -1,6 +1,6 @@
 ;;; allout-tests.el --- Tests for allout.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/allout-widgets-tests.el 
b/test/lisp/allout-widgets-tests.el
index 67b796d69c5..24f5d3dc6b9 100644
--- a/test/lisp/allout-widgets-tests.el
+++ b/test/lisp/allout-widgets-tests.el
@@ -1,6 +1,6 @@
 ;;; allout-widgets-tests.el --- Tests for allout-widgets.el  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/ansi-color-tests.el b/test/lisp/ansi-color-tests.el
index 996a0512814..a1257a063f0 100644
--- a/test/lisp/ansi-color-tests.el
+++ b/test/lisp/ansi-color-tests.el
@@ -1,6 +1,6 @@
 ;;; ansi-color-tests.el --- Test suite for ansi-color  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Pablo Barbáchano <pablob@amazon.com>
 
diff --git a/test/lisp/ansi-osc-tests.el b/test/lisp/ansi-osc-tests.el
index 616ea0d0d34..c0a5f3c640a 100644
--- a/test/lisp/ansi-osc-tests.el
+++ b/test/lisp/ansi-osc-tests.el
@@ -1,6 +1,6 @@
 ;;; osc-tests.el --- Tests for osc.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Matthias Meulien <orontee@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/apropos-tests.el b/test/lisp/apropos-tests.el
index c899087634b..fd484ca699c 100644
--- a/test/lisp/apropos-tests.el
+++ b/test/lisp/apropos-tests.el
@@ -1,6 +1,6 @@
 ;;; apropos-tests.el --- Tests for apropos.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/arc-mode-tests.el b/test/lisp/arc-mode-tests.el
index c42fd8d432c..acc416d6f78 100644
--- a/test/lisp/arc-mode-tests.el
+++ b/test/lisp/arc-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; arc-mode-tests.el --- Test suite for arc-mode. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/auth-source-pass-tests.el 
b/test/lisp/auth-source-pass-tests.el
index ed14289bade..6455c3393d5 100644
--- a/test/lisp/auth-source-pass-tests.el
+++ b/test/lisp/auth-source-pass-tests.el
@@ -1,6 +1,6 @@
 ;;; auth-source-pass-tests.el --- Tests for auth-source-pass.el  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2013, 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013, 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Damien Cassou <damien.cassou@gmail.com>
 
diff --git a/test/lisp/auth-source-tests.el b/test/lisp/auth-source-tests.el
index ab1a437b303..0a3c1cce590 100644
--- a/test/lisp/auth-source-tests.el
+++ b/test/lisp/auth-source-tests.el
@@ -1,6 +1,6 @@
 ;;; auth-source-tests.el --- Tests for auth-source.el  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Damien Cassou <damien@cassou.me>,
 ;;         Nicolas Petton <nicolas@petton.fr>
@@ -411,7 +411,7 @@ machine c1 port c2 user c3 password c4\n"
       ;; this is actually the same as `auth-source-search'.
       (should (equal found expected)))))
 
-(ert-deftest test-netrc-credentials ()
+(ert-deftest auth-source-test-netrc-credentials ()
   (let ((data (auth-source-netrc-parse-all (ert-resource-file "authinfo"))))
     (should data)
     (let ((imap (seq-find (lambda (elem)
@@ -427,7 +427,7 @@ machine c1 port c2 user c3 password c4\n"
       (should (equal (cdr (assoc "login" imap)) "jrh"))
       (should (equal (cdr (assoc "password" imap)) "*baz*")))))
 
-(ert-deftest test-netrc-credentials-2 ()
+(ert-deftest auth-source-test-netrc-credentials-2 ()
   (let ((data (auth-source-netrc-parse-all
                (ert-resource-file "netrc-folding"))))
     (should
@@ -435,25 +435,33 @@ machine c1 port c2 user c3 password c4\n"
             '((("machine" . "XM") ("login" . "XL") ("password" . "XP"))
               (("machine" . "YM") ("login" . "YL") ("password" . "YP")))))))
 
-(ert-deftest test-macos-keychain-search ()
+(ert-deftest auth-source-test-macos-keychain-search ()
   "Test if the constructed command line arglist is correct."
   (let ((auth-sources '(macos-keychain-internet macos-keychain-generic)))
     ;; Redefine `call-process' to check command line arguments.
     (cl-letf (((symbol-function 'call-process)
                (lambda (_program _infile _destination _display
                                  &rest args)
-                 ;; Arguments must be all strings
+                 ;; Arguments must be all strings.
                  (should (cl-every #'stringp args))
-                 ;; Argument number should be even
+                 ;; Argument number should be even.
                  (should (cl-evenp (length args)))
-                 (should (cond ((string= (car args) "find-internet-password")
-                                (let ((protocol (cl-member "-r" args :test 
#'string=)))
-                                  (if protocol
-                                      (= 4 (length (cadr protocol)))
-                                    t)))
-                               ((string= (car args) "find-generic-password")
-                                t))))))
-      (auth-source-search :user '("a" "b") :host '("example.org") :port 
'("irc" "ftp" "https")))))
+                 (should
+                  (cond
+                   ((string= (car args) "find-internet-password")
+                    (let ((protocol-r (cl-member "-r" args :test #'string=))
+                          (protocol-P (cl-member "-P" args :test #'string=)))
+                      (cond (protocol-r
+                             (= 4 (length (cadr protocol-r))))
+                            (protocol-P
+                             (string-match-p
+                              "\\`[[:digit:]]+\\'" (cadr protocol-P)))
+                            (t))))
+                   ((string= (car args) "find-generic-password")
+                    t))))))
+      (auth-source-search
+       :user '("a" "b") :host '("example.org")
+       :port '("irc" "ftp" "https" 123)))))
 
 (provide 'auth-source-tests)
 ;;; auth-source-tests.el ends here
diff --git a/test/lisp/autoinsert-tests.el b/test/lisp/autoinsert-tests.el
index fc4e2bdab5b..8c2279d8371 100644
--- a/test/lisp/autoinsert-tests.el
+++ b/test/lisp/autoinsert-tests.el
@@ -1,6 +1,6 @@
 ;;; autoinsert-tests.el --- Tests for autoinsert.el  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el
index e01ce82858b..c202970e0b2 100644
--- a/test/lisp/autorevert-tests.el
+++ b/test/lisp/autorevert-tests.el
@@ -1,6 +1,6 @@
 ;;; autorevert-tests.el --- Tests of auto-revert   -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 
diff --git a/test/lisp/battery-tests.el b/test/lisp/battery-tests.el
index e8fa1a6d017..f1796a4b628 100644
--- a/test/lisp/battery-tests.el
+++ b/test/lisp/battery-tests.el
@@ -1,6 +1,6 @@
 ;;; battery-tests.el --- tests for battery.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/bookmark-tests.el b/test/lisp/bookmark-tests.el
index 12a9f24e66e..b1eef38b165 100644
--- a/test/lisp/bookmark-tests.el
+++ b/test/lisp/bookmark-tests.el
@@ -1,6 +1,6 @@
 ;;; bookmark-tests.el --- Tests for bookmark.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/buff-menu-tests.el b/test/lisp/buff-menu-tests.el
index b3a54093c54..c4817ad61c5 100644
--- a/test/lisp/buff-menu-tests.el
+++ b/test/lisp/buff-menu-tests.el
@@ -1,6 +1,6 @@
 ;;; buff-menu-tests.el --- Test suite for buff-menu.el -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Tino Calancha <tino.calancha@gmail.com>
 
diff --git a/test/lisp/button-tests.el b/test/lisp/button-tests.el
index 46371b01f3f..b923b0ddd6a 100644
--- a/test/lisp/button-tests.el
+++ b/test/lisp/button-tests.el
@@ -1,6 +1,6 @@
 ;;; button-tests.el --- tests for button.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/calc/calc-tests.el b/test/lisp/calc/calc-tests.el
index 5b11dd950ba..b64c1682efe 100644
--- a/test/lisp/calc/calc-tests.el
+++ b/test/lisp/calc/calc-tests.el
@@ -1,6 +1,6 @@
 ;;; calc-tests.el --- tests for calc                 -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Leo Liu <sdl.web@gmail.com>
 ;; Keywords: maint
@@ -734,6 +734,31 @@ An existing calc stack is reused, otherwise a new one is 
created."
                             (var c var-c))))))
     (calc-set-language nil)))
 
+(ert-deftest calc-frac-input ()
+  ;; precomposed fraction
+  (should (equal (math-read-expr "½")
+                 '(frac 1 2)))
+  ;; ascii solidus
+  (should (equal (math-read-expr "123/456")
+                 '(/ 123 456)))
+  (should (equal (math-read-expr "a/b")
+                 '(/ (var a var-a) (var b var-b))))
+  ;; fraction slash
+  (should (equal (math-read-expr "123⁄456")
+                 '(frac 41 152)))
+  (should (equal (math-read-expr "a⁄b")
+                 '(error 1 "Syntax error")))
+  ;; division slash
+  (should (equal (math-read-expr "123∕456")
+                 '(/ 123 456)))
+  (should (equal (math-read-expr "a∕b")
+                 '(/ (var a var-a) (var b var-b))))
+  ;; division sign
+  (should (equal (math-read-expr "123÷456")
+                 '(frac 41 152)))
+  (should (equal (math-read-expr "a÷b") ; I think this one is wrong
+                 '(error 1 "Syntax error"))))
+
 (defvar var-g)
 
 ;; Test `let'.
@@ -816,5 +841,43 @@ An existing calc stack is reused, otherwise a new one is 
created."
          (x (calc-tests--calc-to-number (math-pow 8 '(frac 1 6)))))
     (should (< (abs (- x (sqrt 2.0))) 1.0e-10))))
 
+(require 'calc-aent)
+
+(ert-deftest calc-math-read-preprocess-string ()
+  "Test replacement of allowed special Unicode symbols."
+  ;; ... doesn't change an empty string
+  (should (string= "" (math-read-preprocess-string "")))
+  ;; ... doesn't change a string without characters from
+  ;; ‘math-read-replacement-list’
+  (let ((str "don't replace here"))
+    (should (string= str (math-read-preprocess-string str))))
+  ;; ... replaces irrespective of position in input string
+  (should (string= "^(1)" (math-read-preprocess-string "¹")))
+  (should (string= "some^(1)" (math-read-preprocess-string "some¹")))
+  (should (string= "^(1)time" (math-read-preprocess-string "¹time")))
+  (should (string= "some^(1)else" (math-read-preprocess-string "some¹else")))
+  ;; ... replaces every element of ‘math-read-replacement-list’ correctly,
+  ;; in particular combining consecutive super-/subscripts into one
+  ;; exponent/subscript
+  (should (string= (concat "+/-*:-/*inf<=>=<=>=μ(1:4)(1:2)(3:4)(1:3)(2:3)"
+                           "(1:5)(2:5)(3:5)(4:5)(1:6)(5:6)"
+                           "(1:8)(3:8)(5:8)(7:8)1::^(0123456789+-()ni)"
+                           "_(0123456789+-())")
+                   (math-read-preprocess-string
+                    (mapconcat #'car math-read-replacement-list))))
+  ;; ... replaces strings of more than a single character correctly
+  (let ((math-read-replacement-list (append
+                                     math-read-replacement-list
+                                     '(("𝚤𝚥" "ij"))
+                                     '(("¼½" "(1:4)(1:2)")))))
+    (should (string= "(1:4)(1:2)ij"
+                     (math-read-preprocess-string "¼½𝚤𝚥"))))
+  ;; ... handles an empty replacement list gracefully
+  (let ((math-read-replacement-list '()))
+    (should (string= "¼" (math-read-preprocess-string "¼"))))
+  ;; ... signals an error if the argument is not a string
+  (should-error (math-read-preprocess-string nil))
+  (should-error (math-read-preprocess-string 42)))
+
 (provide 'calc-tests)
 ;;; calc-tests.el ends here
diff --git a/test/lisp/calculator-tests.el b/test/lisp/calculator-tests.el
index 8786d5c6c3b..5b485fe6dc5 100644
--- a/test/lisp/calculator-tests.el
+++ b/test/lisp/calculator-tests.el
@@ -1,6 +1,6 @@
 ;;; calculator-tests.el --- Test suite for calculator. -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/calendar/cal-french-tests.el 
b/test/lisp/calendar/cal-french-tests.el
index aad0eae5514..160bbe6ce1c 100644
--- a/test/lisp/calendar/cal-french-tests.el
+++ b/test/lisp/calendar/cal-french-tests.el
@@ -1,6 +1,6 @@
 ;;; cal-french-tests.el --- tests for cal-french.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/calendar/cal-julian-tests.el 
b/test/lisp/calendar/cal-julian-tests.el
index 4207d1ee285..072087e70a7 100644
--- a/test/lisp/calendar/cal-julian-tests.el
+++ b/test/lisp/calendar/cal-julian-tests.el
@@ -1,6 +1,6 @@
 ;;; cal-julian-tests.el --- tests for calendar/cal-julian.el  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/calendar/icalendar-tests.el 
b/test/lisp/calendar/icalendar-tests.el
index 9071607005d..7d3af25ea49 100644
--- a/test/lisp/calendar/icalendar-tests.el
+++ b/test/lisp/calendar/icalendar-tests.el
@@ -1,6 +1,6 @@
 ;;; icalendar-tests.el --- Test suite for icalendar.el  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2005, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2008-2024 Free Software Foundation, Inc.
 
 ;; Author:         Ulf Jasper <ulf.jasper@web.de>
 ;; Created:        March 2005
diff --git a/test/lisp/calendar/iso8601-tests.el 
b/test/lisp/calendar/iso8601-tests.el
index f68ea2a4e4d..aef221df7a0 100644
--- a/test/lisp/calendar/iso8601-tests.el
+++ b/test/lisp/calendar/iso8601-tests.el
@@ -1,6 +1,6 @@
 ;;; iso8601-tests.el --- tests for calendar/iso8601.el    -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/calendar/lunar-tests.el 
b/test/lisp/calendar/lunar-tests.el
index e19965d1034..d9f6f6ca56a 100644
--- a/test/lisp/calendar/lunar-tests.el
+++ b/test/lisp/calendar/lunar-tests.el
@@ -1,6 +1,6 @@
 ;;; lunar-tests.el --- tests for calendar/lunar.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/calendar/parse-time-tests.el 
b/test/lisp/calendar/parse-time-tests.el
index 95f1b83d851..5db0035e7bf 100644
--- a/test/lisp/calendar/parse-time-tests.el
+++ b/test/lisp/calendar/parse-time-tests.el
@@ -1,6 +1,6 @@
 ;;; parse-time-tests.el --- Test suite for parse-time.el  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Ingebrigtsen <larsi@gnus.org>
 
diff --git a/test/lisp/calendar/solar-tests.el 
b/test/lisp/calendar/solar-tests.el
index 1f1ad0578f6..4b1417b3ba8 100644
--- a/test/lisp/calendar/solar-tests.el
+++ b/test/lisp/calendar/solar-tests.el
@@ -1,6 +1,6 @@
 ;;; solar-tests.el --- tests for solar.el            -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/calendar/time-date-tests.el 
b/test/lisp/calendar/time-date-tests.el
index 53afd372057..01f9f8a5108 100644
--- a/test/lisp/calendar/time-date-tests.el
+++ b/test/lisp/calendar/time-date-tests.el
@@ -1,6 +1,6 @@
 ;;; time-date-tests.el --- tests for calendar/time-date.el    -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/calendar/todo-mode-tests.el 
b/test/lisp/calendar/todo-mode-tests.el
index 3b49dd56b69..8c76792ec41 100644
--- a/test/lisp/calendar/todo-mode-tests.el
+++ b/test/lisp/calendar/todo-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; todo-mode-tests.el --- tests for todo-mode.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Stephen Berman <stephen.berman@gmx.net>
 ;; Keywords: calendar
diff --git a/test/lisp/cedet/cedet-files-tests.el 
b/test/lisp/cedet/cedet-files-tests.el
index 751101065ba..d10dad4be24 100644
--- a/test/lisp/cedet/cedet-files-tests.el
+++ b/test/lisp/cedet/cedet-files-tests.el
@@ -1,6 +1,6 @@
 ;;; cedet-files-tests.el --- Tests for cedet-files.el  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-c.el 
b/test/lisp/cedet/semantic-utest-c.el
index 2569c1c9478..05ad47976c3 100644
--- a/test/lisp/cedet/semantic-utest-c.el
+++ b/test/lisp/cedet/semantic-utest-c.el
@@ -1,6 +1,6 @@
 ;;; semantic-utest-c.el --- C based parsing tests.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/test.srt 
b/test/lisp/cedet/semantic-utest-ia-resources/test.srt
index b1094ffb52f..69c3b772812 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/test.srt
+++ b/test/lisp/cedet/semantic-utest-ia-resources/test.srt
@@ -1,6 +1,6 @@
 ;; test.srt --- unit test support file for semantic-utest-ia
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.cpp 
b/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.cpp
index e192c4f7f83..e7b4d06e7a2 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.cpp
@@ -1,6 +1,6 @@
 // testdoublens.cpp --- semantic-ia-utest completion engine unit tests
 
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 // Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.hpp 
b/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.hpp
index 5c55a0fc6f0..580a023f6cb 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.hpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.hpp
@@ -1,6 +1,6 @@
 // testdoublens.hpp --- Header file used in one of the Semantic tests
 
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 // Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testjavacomp.java 
b/test/lisp/cedet/semantic-utest-ia-resources/testjavacomp.java
index 639ed95e9da..43c3ee8290c 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testjavacomp.java
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testjavacomp.java
@@ -1,6 +1,6 @@
 //  testjavacomp.java --- Semantic unit test for Java
 
-// Copyright (C) 2009-2023 Free Software Foundation, Inc.
+// Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 //  Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp 
b/test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp
index fbe20dade9c..f43e61eb45d 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp
@@ -1,6 +1,6 @@
 //  testlocalvars.java --- Semantic unit test for Java
 
-// Copyright (C) 2009-2023 Free Software Foundation, Inc.
+// Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 //  Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp 
b/test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp
index e88bd37c808..9881243269c 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp
@@ -1,6 +1,6 @@
 /* testnsp.cpp --- semantic-ia-utest completion engine unit tests
 
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
    Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c 
b/test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c
index 2458bf433aa..1c8efe9082e 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c
@@ -1,6 +1,6 @@
 /* testesppcomplete.cpp --- semantic-ia-utest completion engine unit tests
 
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
    Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp 
b/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp
index 894f53754ea..c06f4b35c25 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp
@@ -1,6 +1,6 @@
 // teststruct.cpp --- semantic-ia-utest completion engine unit tests
 
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 // Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.cpp 
b/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.cpp
index a507f1bf418..30971feef61 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.cpp
@@ -1,6 +1,6 @@
 // testsubclass.cpp --- unit test for analyzer and complex C++ inheritance
 
-// Copyright (C) 2007-2023 Free Software Foundation, Inc.
+// Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 // Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.hh 
b/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.hh
index a6c31ac8fab..79e12f2fe27 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.hh
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.hh
@@ -1,6 +1,6 @@
 // testsubclass.hh --- unit test for analyzer and complex C++ inheritance
 
-// Copyright (C) 2007-2023 Free Software Foundation, Inc.
+// Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 // Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp 
b/test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp
index f4c48edd562..b3c64ba8574 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp
@@ -1,6 +1,6 @@
 // testtemplates.cpp --- semantic-ia-utest completion engine unit tests
 
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 // Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testtypedefs.cpp 
b/test/lisp/cedet/semantic-utest-ia-resources/testtypedefs.cpp
index 13f0f288212..b0bf22d16c2 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testtypedefs.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testtypedefs.cpp
@@ -1,6 +1,6 @@
 // testtypedefs.cpp --- Sample with some fake bits out of std::string
 
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 // Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp 
b/test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp
index 940e7caa0cf..a0e763f072a 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp
@@ -1,6 +1,6 @@
 // testusing.cpp --- semantic-ia-utest completion engine unit tests
 
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 // Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testusing.hh 
b/test/lisp/cedet/semantic-utest-ia-resources/testusing.hh
index 1effa00686d..bb130732fec 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testusing.hh
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testusing.hh
@@ -1,6 +1,6 @@
 // testusing.hh --- semantic-ia-utest completion engine unit tests
 
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 // Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.c 
b/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.c
index f8202296385..b027bd24d20 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.c
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.c
@@ -1,6 +1,6 @@
 /* testvarnames.cpp --- semantic-ia-utest completion engine unit tests
 
-   Copyright (C) 2008-2023 Free Software Foundation, Inc.
+   Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
    Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java 
b/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java
index 8934bb8d97d..1e4df4956f7 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java
@@ -1,6 +1,6 @@
 //  testvarnames.java --- Semantic unit test for Java
 
-// Copyright (C) 2009-2023 Free Software Foundation, Inc.
+// Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 //  Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy 
b/test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy
index e00f2eb102e..8e260fe974a 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy
@@ -1,6 +1,6 @@
 ;; testwisent.wy --- unit test support file for semantic-utest-ia
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest-ia.el 
b/test/lisp/cedet/semantic-utest-ia.el
index f2b2dbc5a7d..ed18b41770d 100644
--- a/test/lisp/cedet/semantic-utest-ia.el
+++ b/test/lisp/cedet/semantic-utest-ia.el
@@ -1,6 +1,6 @@
 ;;; semantic-utest-ia.el --- Analyzer unit tests  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic-utest.el 
b/test/lisp/cedet/semantic-utest.el
index f53b7c41005..ca338a60046 100644
--- a/test/lisp/cedet/semantic-utest.el
+++ b/test/lisp/cedet/semantic-utest.el
@@ -1,6 +1,6 @@
 ;;; semantic-utest.el --- Tests for semantic's parsing system. -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic/bovine/gcc-tests.el 
b/test/lisp/cedet/semantic/bovine/gcc-tests.el
index 0b703fcaa2f..bfdf2a22286 100644
--- a/test/lisp/cedet/semantic/bovine/gcc-tests.el
+++ b/test/lisp/cedet/semantic/bovine/gcc-tests.el
@@ -1,6 +1,6 @@
 ;;; gcc-tests.el --- Tests for semantic/bovine/gcc.el  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic/format-resources/test-fmt.cpp 
b/test/lisp/cedet/semantic/format-resources/test-fmt.cpp
index 3b04542dcc1..211d9e28092 100644
--- a/test/lisp/cedet/semantic/format-resources/test-fmt.cpp
+++ b/test/lisp/cedet/semantic/format-resources/test-fmt.cpp
@@ -1,6 +1,6 @@
 /** test-fmt.cpp --- Signatures, and format answers for testing
  *
- * Copyright (C) 2012, 2016, 2019-2023 Free Software Foundation, Inc.
+ * Copyright (C) 2012, 2016, 2019-2024 Free Software Foundation, Inc.
  *
  * Author: Eric M. Ludlam <zappo@gnu.org>
  *
diff --git a/test/lisp/cedet/semantic/format-resources/test-fmt.el 
b/test/lisp/cedet/semantic/format-resources/test-fmt.el
index 3cef50e2395..a1bfdd0333d 100644
--- a/test/lisp/cedet/semantic/format-resources/test-fmt.el
+++ b/test/lisp/cedet/semantic/format-resources/test-fmt.el
@@ -1,6 +1,6 @@
 ;;; test-fmt.el --- test semantic tag formatting  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic/format-tests.el 
b/test/lisp/cedet/semantic/format-tests.el
index cc2bcc40ae3..3b922355d76 100644
--- a/test/lisp/cedet/semantic/format-tests.el
+++ b/test/lisp/cedet/semantic/format-tests.el
@@ -1,6 +1,6 @@
 ;;; semantic/format-tests.el --- Parsing / Formatting tests -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/semantic/fw-tests.el 
b/test/lisp/cedet/semantic/fw-tests.el
index 6da2632aa39..0363ef4f657 100644
--- a/test/lisp/cedet/semantic/fw-tests.el
+++ b/test/lisp/cedet/semantic/fw-tests.el
@@ -1,6 +1,6 @@
 ;;; fw-tests.el --- Tests for semantic/fw.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/srecode-utest-getset.el 
b/test/lisp/cedet/srecode-utest-getset.el
index c3c1e41c3d2..bfdae2d4c86 100644
--- a/test/lisp/cedet/srecode-utest-getset.el
+++ b/test/lisp/cedet/srecode-utest-getset.el
@@ -1,6 +1,6 @@
 ;;; srecode/test-getset.el --- Test the getset inserter. -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2008-2009, 2011, 2019-2023 Free Software Foundation,
+;; Copyright (C) 2008-2009, 2011, 2019-2024 Free Software Foundation,
 ;; Inc.
 
 ;; This file is part of GNU Emacs.
diff --git a/test/lisp/cedet/srecode-utest-template.el 
b/test/lisp/cedet/srecode-utest-template.el
index a43ea43ba30..37ddc57cc39 100644
--- a/test/lisp/cedet/srecode-utest-template.el
+++ b/test/lisp/cedet/srecode-utest-template.el
@@ -1,6 +1,6 @@
 ;;; srecode-utest-template.el --- SRecode Core Template tests. -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/cedet/srecode/document-tests.el 
b/test/lisp/cedet/srecode/document-tests.el
index b5f7f83e0cb..3f6f6adae73 100644
--- a/test/lisp/cedet/srecode/document-tests.el
+++ b/test/lisp/cedet/srecode/document-tests.el
@@ -1,6 +1,6 @@
 ;;; document-tests.el --- Tests for srecode/document.el  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/cedet/srecode/fields-tests.el 
b/test/lisp/cedet/srecode/fields-tests.el
index 21c2b329120..8b195bdcf71 100644
--- a/test/lisp/cedet/srecode/fields-tests.el
+++ b/test/lisp/cedet/srecode/fields-tests.el
@@ -1,6 +1,6 @@
 ;;; srecode/fields-tests.el --- Tests for srecode/fields.el  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/char-fold-tests.el b/test/lisp/char-fold-tests.el
index 6e265a5eb27..9a44ce11205 100644
--- a/test/lisp/char-fold-tests.el
+++ b/test/lisp/char-fold-tests.el
@@ -1,6 +1,6 @@
 ;;; char-fold-tests.el --- Tests for char-fold.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
 
diff --git a/test/lisp/color-tests.el b/test/lisp/color-tests.el
index d47373bf023..9b6b8c1f8dc 100644
--- a/test/lisp/color-tests.el
+++ b/test/lisp/color-tests.el
@@ -1,6 +1,6 @@
 ;;; color-tests.el --- Tests for color.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/comint-tests.el b/test/lisp/comint-tests.el
index 6d435908b35..10a4ff34239 100644
--- a/test/lisp/comint-tests.el
+++ b/test/lisp/comint-tests.el
@@ -1,6 +1,6 @@
 ;;; comint-tests.el --- Tests for comint.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/completion-preview-tests.el 
b/test/lisp/completion-preview-tests.el
index b5518e96254..190764e9125 100644
--- a/test/lisp/completion-preview-tests.el
+++ b/test/lisp/completion-preview-tests.el
@@ -1,6 +1,6 @@
 ;;; completion-preview-tests.el --- tests for completion-preview.el -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/completion-tests.el b/test/lisp/completion-tests.el
index d34691d93ae..33bafed625e 100644
--- a/test/lisp/completion-tests.el
+++ b/test/lisp/completion-tests.el
@@ -1,6 +1,6 @@
 ;;; completion-tests.el --- Tests for completion.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/cus-edit-tests.el b/test/lisp/cus-edit-tests.el
index 9ceab16e194..535711e02cf 100644
--- a/test/lisp/cus-edit-tests.el
+++ b/test/lisp/cus-edit-tests.el
@@ -1,6 +1,6 @@
 ;;; cus-edit-tests.el --- Tests for cus-edit.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/custom-tests.el b/test/lisp/custom-tests.el
index 376a13d5df5..c009abfe0d1 100644
--- a/test/lisp/custom-tests.el
+++ b/test/lisp/custom-tests.el
@@ -1,6 +1,6 @@
 ;;; custom-tests.el --- tests for custom.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/dabbrev-tests.el b/test/lisp/dabbrev-tests.el
index 48677a0b415..c7574403949 100644
--- a/test/lisp/dabbrev-tests.el
+++ b/test/lisp/dabbrev-tests.el
@@ -1,6 +1,6 @@
 ;;; dabbrev-tests.el --- Test suite for dabbrev.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Alan Third <alan@idiocy.org>
 ;; Keywords: dabbrev
diff --git a/test/lisp/delim-col-tests.el b/test/lisp/delim-col-tests.el
index a2721d8cdf8..f2d5d72f57f 100644
--- a/test/lisp/delim-col-tests.el
+++ b/test/lisp/delim-col-tests.el
@@ -1,6 +1,6 @@
 ;;; delim-col-tests.el --- Tests for delim-col.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/descr-text-tests.el b/test/lisp/descr-text-tests.el
index 96c5d90e449..a263c099a0c 100644
--- a/test/lisp/descr-text-tests.el
+++ b/test/lisp/descr-text-tests.el
@@ -1,6 +1,6 @@
 ;;; descr-text-tests.el --- ERT tests for descr-text.el -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2014, 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014, 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Michal Nazarewicz <mina86@mina86.com>
 
diff --git a/test/lisp/desktop-tests.el b/test/lisp/desktop-tests.el
index 07f0be6c90e..164e1ab1c36 100644
--- a/test/lisp/desktop-tests.el
+++ b/test/lisp/desktop-tests.el
@@ -1,6 +1,6 @@
 ;;; desktop-tests.el --- Tests for desktop.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020, 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020, 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/dired-aux-tests.el b/test/lisp/dired-aux-tests.el
index 62011d8b0f0..f1542cb5e83 100644
--- a/test/lisp/dired-aux-tests.el
+++ b/test/lisp/dired-aux-tests.el
@@ -1,6 +1,6 @@
 ;;; dired-aux-tests.el --- Test suite for dired-aux. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/dired-tests.el b/test/lisp/dired-tests.el
index 8f2b9af09c0..651b77500a1 100644
--- a/test/lisp/dired-tests.el
+++ b/test/lisp/dired-tests.el
@@ -1,6 +1,6 @@
 ;;; dired-tests.el --- Test suite. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -270,8 +270,8 @@
   "Test for https://debbugs.gnu.org/27631 ."
   ;; For dired using 'ls' emulation we test for this bug in
   ;; ls-lisp-tests.el and em-ls-tests.el.
-  (skip-unless (and (not (featurep 'ls-lisp))
-                    (not (featurep 'eshell))))
+  (skip-unless (not (or (featurep 'ls-lisp)
+                        (featurep 'eshell))))
   (ert-with-temp-directory dir
     (let* ((dir1 (expand-file-name "dir1" dir))
            (dir2 (expand-file-name "dir2" dir))
diff --git a/test/lisp/dired-x-tests.el b/test/lisp/dired-x-tests.el
index b64b115e69f..166ec54f9dd 100644
--- a/test/lisp/dired-x-tests.el
+++ b/test/lisp/dired-x-tests.el
@@ -1,6 +1,6 @@
 ;;; dired-x-tests.el --- Test suite for dired-x. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el
index 7a7f54ba0bb..3d4f28b9ae1 100644
--- a/test/lisp/dnd-tests.el
+++ b/test/lisp/dnd-tests.el
@@ -1,6 +1,6 @@
 ;;; dnd-tests.el --- Tests for window system independent DND support -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/dom-tests.el b/test/lisp/dom-tests.el
index abb586435a7..a4e913541bf 100644
--- a/test/lisp/dom-tests.el
+++ b/test/lisp/dom-tests.el
@@ -1,6 +1,6 @@
 ;;; dom-tests.el --- Tests for dom.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
@@ -209,6 +209,16 @@ child results in an error."
       (dom-pp node t)
       (should (equal (buffer-string) "(\"foo\" nil)")))))
 
+(ert-deftest dom-tests-print ()
+  "Test that `dom-print' correctly encodes HTML reserved characters."
+  (with-temp-buffer
+    (dom-print '(samp ((class . "samp")) "<div class=\"default\"> </div>"))
+    (should (equal
+             (buffer-string)
+             (concat "<samp class=\"samp\">"
+                     "&lt;div class=&quot;default&quot;&gt; &lt;/div&gt;"
+                     "</samp>")))))
+
 (ert-deftest dom-test-search ()
   (let ((dom '(a nil (b nil (c nil)))))
     (should (equal (dom-search dom (lambda (d) (eq (dom-tag d) 'a)))
diff --git a/test/lisp/edmacro-tests.el b/test/lisp/edmacro-tests.el
index f79529a2000..fb968d8e6da 100644
--- a/test/lisp/edmacro-tests.el
+++ b/test/lisp/edmacro-tests.el
@@ -1,6 +1,6 @@
 ;;; edmacro-tests.el --- Tests for edmacro.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/electric-tests.el b/test/lisp/electric-tests.el
index c577229c322..720313511a6 100644
--- a/test/lisp/electric-tests.el
+++ b/test/lisp/electric-tests.el
@@ -1,6 +1,6 @@
 ;;; electric-tests.el --- tests for electric.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: João Távora <joaotavora@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/elide-head-tests.el b/test/lisp/elide-head-tests.el
index 40a9d365f37..3f1db75928a 100644
--- a/test/lisp/elide-head-tests.el
+++ b/test/lisp/elide-head-tests.el
@@ -1,6 +1,6 @@
 ;;; elide-head-tests.el --- Tests for elide-head.el  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 
diff --git a/test/lisp/emacs-lisp/backquote-tests.el 
b/test/lisp/emacs-lisp/backquote-tests.el
index 79155cc0450..66764f40ec2 100644
--- a/test/lisp/emacs-lisp/backquote-tests.el
+++ b/test/lisp/emacs-lisp/backquote-tests.el
@@ -1,6 +1,6 @@
 ;;; backquote-tests.el --- Tests for backquote.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/backtrace-tests.el 
b/test/lisp/emacs-lisp/backtrace-tests.el
index e5899446ee4..3248403078f 100644
--- a/test/lisp/emacs-lisp/backtrace-tests.el
+++ b/test/lisp/emacs-lisp/backtrace-tests.el
@@ -1,6 +1,6 @@
 ;;; backtrace-tests.el --- Tests for backtraces -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Gemini Lasswell
 
diff --git a/test/lisp/emacs-lisp/benchmark-tests.el 
b/test/lisp/emacs-lisp/benchmark-tests.el
index 7fe3be2157f..72095ea5b09 100644
--- a/test/lisp/emacs-lisp/benchmark-tests.el
+++ b/test/lisp/emacs-lisp/benchmark-tests.el
@@ -1,6 +1,6 @@
 ;;; benchmark-tests.el --- Test suite for benchmark.  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/bindat-tests.el 
b/test/lisp/emacs-lisp/bindat-tests.el
index 1e4a511d036..99de0635aee 100644
--- a/test/lisp/emacs-lisp/bindat-tests.el
+++ b/test/lisp/emacs-lisp/bindat-tests.el
@@ -1,6 +1,6 @@
 ;;; bindat-tests.el --- tests for bindat.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/byte-run-tests.el 
b/test/lisp/emacs-lisp/byte-run-tests.el
index 59ce24ad251..6180022f198 100644
--- a/test/lisp/emacs-lisp/byte-run-tests.el
+++ b/test/lisp/emacs-lisp/byte-run-tests.el
@@ -1,6 +1,6 @@
 ;;; byte-run-tests.el --- Tests for byte-run.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el 
b/test/lisp/emacs-lisp/bytecomp-tests.el
index 6330bd7f5e3..cc9f872e785 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -1,6 +1,6 @@
 ;;; bytecomp-tests.el --- Tests for bytecomp.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Shigeru Fukaya <shigeru.fukaya@gmail.com>
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
@@ -717,7 +717,7 @@ inner loops respectively."
       (set (make-local-variable 'bytecomp-tests--xx) 2)
       bytecomp-tests--xx)
 
-    ;; Check for-effect optimisation of `condition-case' body form.
+    ;; Check for-effect optimization of `condition-case' body form.
     ;; With `condition-case' in for-effect context:
     (let ((x (bytecomp-test-identity ?A))
           (r nil))
@@ -797,7 +797,7 @@ inner loops respectively."
     (let ((x 0))
       (list (= (setq x 1))
             x))
-    ;; Aristotelian identity optimisation
+    ;; Aristotelian identity optimization
     (let ((x (bytecomp-test-identity 1)))
       (list (eq x x) (eql x x) (equal x x)))
     )
@@ -2087,18 +2087,12 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode 
js-mode python-mode)) \
 
 (defun bytecomp-tests--error-frame (fun args)
   "Call FUN with ARGS.  Return result or (ERROR . BACKTRACE-FRAME)."
-  (let* ((debugger
-          (lambda (&rest args)
-            ;; Make sure Emacs doesn't think our debugger is buggy.
-            (cl-incf num-nonmacro-input-events)
-            (throw 'bytecomp-tests--backtrace
-                   (cons args (cadr (backtrace-get-frames debugger))))))
-         (debug-on-error t)
-         (backtrace-on-error-noninteractive nil)
-         (debug-on-quit t)
-         (debug-ignored-errors nil))
+  (letrec ((handler (lambda (e)
+                      (throw 'bytecomp-tests--backtrace
+                             (cons e (cadr (backtrace-get-frames handler)))))))
     (catch 'bytecomp-tests--backtrace
-      (apply fun args))))
+      (handler-bind ((error handler))
+        (apply fun args)))))
 
 (defconst bytecomp-tests--byte-op-error-cases
   '(((car a) (wrong-type-argument listp a))
@@ -2120,7 +2114,7 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode 
python-mode)) \
     ))
 
 (ert-deftest bytecomp--byte-op-error-backtrace ()
-  "Check that signalling byte ops show up in the backtrace."
+  "Check that signaling byte ops show up in the backtrace."
   (dolist (case bytecomp-tests--byte-op-error-cases)
     (ert-info ((prin1-to-string case) :prefix "case: ")
       (let* ((call (nth 0 case))
@@ -2143,7 +2137,7 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode 
python-mode)) \
                               `(lambda ,formals (,fun-sym ,@formals)))))))
                    (error-frame (bytecomp-tests--error-frame fun actuals)))
               (should (consp error-frame))
-              (should (equal (car error-frame) (list 'error expected-error)))
+              (should (equal (car error-frame) expected-error))
               (let ((frame (cdr error-frame)))
                 (should (equal (type-of frame) 'backtrace-frame))
                 (should (equal (cons (backtrace-frame-fun frame)
@@ -2151,7 +2145,7 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode 
python-mode)) \
                                call))))))))))
 
 (ert-deftest bytecomp--eq-symbols-with-pos-enabled ()
-  ;; Verify that we don't optimise away a binding of
+  ;; Verify that we don't optimize away a binding of
   ;; `symbols-with-pos-enabled' around an application of `eq' (bug#65017).
   (let* ((sym-with-pos1 (read-positioning-symbols "sym"))
          (sym-with-pos2 (read-positioning-symbols " sym"))  ; <- space!
diff --git a/test/lisp/emacs-lisp/cconv-tests.el 
b/test/lisp/emacs-lisp/cconv-tests.el
index 6da2e90c4ac..5bbade0ae6e 100644
--- a/test/lisp/emacs-lisp/cconv-tests.el
+++ b/test/lisp/emacs-lisp/cconv-tests.el
@@ -1,6 +1,6 @@
 ;;; cconv-tests.el --- Tests for cconv.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/check-declare-tests.el 
b/test/lisp/emacs-lisp/check-declare-tests.el
index 840b6d22e1e..2d445542cb7 100644
--- a/test/lisp/emacs-lisp/check-declare-tests.el
+++ b/test/lisp/emacs-lisp/check-declare-tests.el
@@ -1,6 +1,6 @@
 ;;; check-declare-tests.el --- Tests for check-declare.el  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/emacs-lisp/checkdoc-tests.el 
b/test/lisp/emacs-lisp/checkdoc-tests.el
index 57694bd424b..049d2d953a0 100644
--- a/test/lisp/emacs-lisp/checkdoc-tests.el
+++ b/test/lisp/emacs-lisp/checkdoc-tests.el
@@ -1,6 +1,6 @@
 ;;; checkdoc-tests.el --- unit tests for checkdoc.el  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Philipp Stephani <phst@google.com>
 
@@ -37,6 +37,15 @@
     (insert "(defun foo())")
     (should-error (checkdoc-defun) :type 'user-error)))
 
+(ert-deftest checkdoc-docstring-avoid-false-positive-ok ()
+  "Check that Bug#68002 is fixed."
+  (with-temp-buffer
+    (emacs-lisp-mode)
+    (insert "(defvar org-element--cache-interrupt-C-g-count 0
+  \"Current number of `org-element--cache-sync' calls.
+See `org-element--cache-interrupt-C-g'.\")")
+    (checkdoc-defun)))
+
 (ert-deftest checkdoc-cl-defmethod-ok ()
   "Checkdoc should be happy with a simple correct cl-defmethod."
   (with-temp-buffer
diff --git a/test/lisp/emacs-lisp/cl-extra-tests.el 
b/test/lisp/emacs-lisp/cl-extra-tests.el
index 84f878900b5..020a0d93f78 100644
--- a/test/lisp/emacs-lisp/cl-extra-tests.el
+++ b/test/lisp/emacs-lisp/cl-extra-tests.el
@@ -1,6 +1,6 @@
 ;;; cl-extra-tests.el --- tests for emacs-lisp/cl-extra.el  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/cl-generic-tests.el 
b/test/lisp/emacs-lisp/cl-generic-tests.el
index 57b9c949342..086ac399352 100644
--- a/test/lisp/emacs-lisp/cl-generic-tests.el
+++ b/test/lisp/emacs-lisp/cl-generic-tests.el
@@ -1,6 +1,6 @@
 ;;; cl-generic-tests.el --- Tests for cl-generic.el functionality  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 
diff --git a/test/lisp/emacs-lisp/cl-lib-tests.el 
b/test/lisp/emacs-lisp/cl-lib-tests.el
index 2954d5418fb..9f4354d5546 100644
--- a/test/lisp/emacs-lisp/cl-lib-tests.el
+++ b/test/lisp/emacs-lisp/cl-lib-tests.el
@@ -1,6 +1,6 @@
 ;;; cl-lib-tests.el --- tests for emacs-lisp/cl-lib.el  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el 
b/test/lisp/emacs-lisp/cl-macs-tests.el
index 56a49fd865a..3fabcbc50c9 100644
--- a/test/lisp/emacs-lisp/cl-macs-tests.el
+++ b/test/lisp/emacs-lisp/cl-macs-tests.el
@@ -1,6 +1,6 @@
 ;;; cl-macs-tests.el --- tests for emacs-lisp/cl-macs.el  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/cl-preloaded-tests.el 
b/test/lisp/emacs-lisp/cl-preloaded-tests.el
index 7c863b4d3eb..01c70478830 100644
--- a/test/lisp/emacs-lisp/cl-preloaded-tests.el
+++ b/test/lisp/emacs-lisp/cl-preloaded-tests.el
@@ -1,6 +1,6 @@
 ;;; cl-preloaded-tests.el --- unit tests for cl-preloaded.el  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 ;; Author: Philipp Stephani <phst@google.com>
 
 ;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/cl-print-tests.el 
b/test/lisp/emacs-lisp/cl-print-tests.el
index 631dd834a68..c752afaaf24 100644
--- a/test/lisp/emacs-lisp/cl-print-tests.el
+++ b/test/lisp/emacs-lisp/cl-print-tests.el
@@ -1,6 +1,6 @@
 ;;; cl-print-tests.el --- Test suite for the cl-print facility.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/cl-seq-tests.el 
b/test/lisp/emacs-lisp/cl-seq-tests.el
index adb74f0a6d5..bc05b17d007 100644
--- a/test/lisp/emacs-lisp/cl-seq-tests.el
+++ b/test/lisp/emacs-lisp/cl-seq-tests.el
@@ -1,6 +1,6 @@
 ;;; cl-seq-tests.el --- Tests for cl-seq.el functionality  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Richard <youngfrog@members.fsf.org>
 
diff --git a/test/lisp/emacs-lisp/comp-cstr-tests.el 
b/test/lisp/emacs-lisp/comp-cstr-tests.el
index cbedce0c47d..edc70b12d4b 100644
--- a/test/lisp/emacs-lisp/comp-cstr-tests.el
+++ b/test/lisp/emacs-lisp/comp-cstr-tests.el
@@ -1,6 +1,6 @@
 ;;; comp-cstr-tests.el --- unit tests for src/comp.c -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrea Corallo <acorallo@gnu.org>
 
@@ -29,218 +29,212 @@
 (require 'cl-lib)
 (require 'comp-cstr)
 
-(cl-eval-when (compile eval load)
+(defun comp-cstr-test-ts (type-spec)
+  "Create a constraint from TYPE-SPEC and convert it back to type specifier."
+  (let ((comp-ctxt (make-comp-cstr-ctxt)))
+    (comp-cstr-to-type-spec (comp-type-spec-to-cstr type-spec))))
 
-  (defun comp-cstr-test-ts (type-spec)
-    "Create a constraint from TYPE-SPEC and convert it back to type specifier."
-    (let ((comp-ctxt (make-comp-cstr-ctxt)))
-      (comp-cstr-to-type-spec (comp-type-spec-to-cstr type-spec))))
-
-  (defun comp-cstr-typespec-test (number type-spec expected-type-spec)
-    `(ert-deftest ,(intern (concat "comp-cstr-test-" (int-to-string number))) 
()
-       (should (equal (comp-cstr-test-ts ',type-spec)
-                      ',expected-type-spec))))
-
-  (defconst comp-cstr-typespec-tests-alist
-    '(;; 1
-      (symbol . symbol)
-      ;; 2
-      ((or string array) . array)
-      ;; 3
-      ((or symbol number) . (or number symbol))
-      ;; 4
-      ((or cons atom) . t) ;; SBCL return T
-      ;; 5
-      ((or integer number) . number)
-      ;; 6
-      ((or (or integer symbol) number) . (or number symbol))
-      ;; 7
-      ((or (or integer symbol) (or number list)) . (or list number symbol))
-      ;; 8
-      ((or (or integer number) nil) . number)
-      ;; 9
-      ((member foo) . (member foo))
-      ;; 10
-      ((member foo bar) . (member bar foo))
-      ;; 11
-      ((or (member foo) (member bar)) . (member bar foo))
-      ;; 12
-      ((or (member foo) symbol) . symbol) ;; SBCL return (OR SYMBOL (MEMBER 
FOO))
-      ;; 13
-      ((or (member foo) number) .  (or (member foo) number))
-      ;; 14
-      ((or (integer 1 3) number) . number)
-      ;; 15
-      (integer . integer)
-      ;; 16
-      ((integer 1 2) . (integer 1 2))
-      ;; 17
-      ((or (integer -1  0) (integer 3  4)) . (or (integer -1  0) (integer 3  
4)))
-      ;; 18
-      ((or (integer -1  2) (integer 3  4)) . (integer -1 4))
-      ;; 19
-      ((or (integer -1  3) (integer 3  4)) . (integer -1 4))
-      ;; 20
-      ((or (integer -1  4) (integer 3  4)) . (integer -1 4))
-      ;; 21
-      ((or (integer -1  5) (integer 3  4)) . (integer -1 5))
-      ;; 22
-      ((or (integer -1  *) (integer 3  4)) . (integer -1 *))
-      ;; 23
-      ((or (integer -1  2) (integer *  4)) . (integer * 4))
-      ;; 24
-      ((and string array) . string)
-      ;; 25
-      ((and cons atom) . nil)
-      ;; 26
-      ((and (member foo) (member foo bar baz)) . (member foo))
-      ;; 27
-      ((and (member foo) (member bar)) . nil)
-      ;; 28
-      ((and (member foo) symbol) . (member foo))
-      ;; 29
-      ((and (member foo) string) . nil)
-      ;; 30
-      ((and (member foo) (integer 1 2)) . nil)
-      ;; 31
-      ((and (member 1 2) (member 3 2)) . (integer 2 2))
-      ;; 32
-      ((and number (integer 1 2)) . (integer 1 2))
-      ;; 33
-      ((and integer (integer 1 2)) . (integer 1 2))
-      ;; 34
-      ((and (integer -1 0) (integer 3 5)) . nil)
-      ;; 35
-      ((and (integer -1 2) (integer 3 5)) . nil)
-      ;; 36
-      ((and (integer -1 3) (integer 3 5)) . (integer 3 3))
-      ;; 37
-      ((and (integer -1 4) (integer 3 5)) . (integer 3 4))
-      ;; 38
-      ((and (integer -1 5) nil) . nil)
-      ;; 39
-      ((not symbol) . (not symbol))
-      ;; 40
-      ((or (member foo) (not (member foo bar))) . (not (member bar)))
-      ;; 41
-      ((or (member foo bar) (not (member foo))) . t)
-      ;; 42
-      ((or symbol (not sequence)) . (not sequence))
-      ;; 43
-      ((or symbol (not symbol)) . t)
-      ;; 44
-      ((or symbol (not sequence)) . (not sequence))
-      ;; 45 Conservative.
-      ((or vector (not sequence)) . t)
-      ;; 46
-      ((or (integer 1 10) (not (integer * 5))) . (not (integer * 0)))
-      ;; 47
-      ((or symbol (integer 1 10) (not (integer * 5))) . (not (integer * 0)))
-      ;; 48
-      ((or (not symbol) (integer 1 10) (not (integer * 5))) . (not (or symbol 
(integer * 0))))
-      ;; 49
-      ((or symbol (not (member foo))) . (not (member foo)))
-      ;; 50
-      ((or (not symbol) (not (member foo))) . (not symbol))
-      ;; 51 Conservative.
-      ((or (not (member foo)) string) . (not (member foo)))
-      ;; 52 Conservative.
-      ((or (member foo) (not string)) . (not string))
-      ;; 53
-      ((or (not (integer 1 2)) integer) . t)
-      ;; 54
-      ((or (not (integer 1 2)) (not integer)) . (not integer))
-      ;; 55
-      ((or (integer 1 2) (not integer)) . (not (or (integer * 0) (integer 3 
*))))
-      ;; 56
-      ((or number (not (integer 1 2))) . t)
-      ;; 57
-      ((or atom (not (integer 1 2))) . t)
-      ;; 58
-      ((or atom (not (member foo))) . t)
-      ;; 59
-      ((and symbol (not cons)) . symbol)
-      ;; 60
-      ((and symbol (not symbol)) . nil)
-      ;; 61
-      ((and atom (not symbol)) . atom)
-      ;; 62
-      ((and atom (not string)) . (or array sequence atom))
-      ;; 63 Conservative
-      ((and symbol (not (member foo))) . symbol)
-      ;; 64 Conservative
-      ((and symbol (not (member 3))) . symbol)
-      ;; 65
-      ((and (not (member foo)) (integer 1 10)) . (integer 1 10))
-      ;; 66
-      ((and (member foo) (not (integer 1 10))) . (member foo))
-      ;; 67
-      ((and t (not (member foo))) . (not (member foo)))
-      ;; 68
-      ((and integer (not (integer 3 4))) . (or (integer * 2) (integer 5 *)))
-      ;; 69
-      ((and (integer 0 20) (not (integer 5 10))) . (or (integer 0 4) (integer 
11 20)))
-      ;; 70
-      ((and (not (member a)) (not (member b))) . (not (member a b)))
-      ;; 71
-      ((and (not boolean) (not (member b))) . (not (or (member b) boolean)))
-      ;; 72
-      ((and t (integer 1 1)) . (integer 1 1))
-      ;; 73
-      ((not (integer -1 5)) . (not (integer -1 5)))
-      ;; 74
-      ((and boolean (or number marker)) . nil)
-      ;; 75
-      ((and atom (or number marker)) . number-or-marker)
-      ;; 76
-      ((and symbol (or number marker)) . nil)
-      ;; 77
-      ((and (or symbol string) (or number marker)) . nil)
-      ;; 78
-      ((and t t) . t)
-      ;; 79
-      ((and (or marker number) (integer 0 0)) . (integer 0 0))
-      ;; 80
-      ((and t (not t)) . nil)
-      ;; 81
-      ((or (integer 1 1) (not (integer 1 1))) . t)
-      ;; 82
-      ((not t) . nil)
-      ;; 83
-      ((not nil) . t)
-      ;; 84
-      ((or (not string) t) . t)
-      ;; 85
-      ((or (not vector) sequence) . sequence)
-      ;; 86
-      ((or (not symbol) null) . t)
-      ;; 87
-      ((and (or null integer) (not (or null integer))) . nil)
-      ;; 88
-      ((and (or (member a b c)) (not (or (member a b)))) . (member c))
-      ;; 89
-      ((or cons symbol) . (or list symbol)) ;; FIXME: Why `list'?
-      ;; 90
-      ((or string char-table bool-vector vector) . array)
-      ;; 91
-      ((or string char-table bool-vector vector number) . (or array number))
-      ;; 92
-      ((or string char-table bool-vector vector cons symbol number) .
-       (or number sequence symbol))
-      ;; 93?
-      ;; FIXME: I get `cons' rather than `list'?
-      ;;((or null cons) . list)
-      )
-    "Alist type specifier -> expected type specifier."))
-
-(defmacro comp-cstr-synthesize-tests ()
-  "Generate all tests from `comp-cstr-typespec-tests-alist'."
+(defmacro comp-cstr-synthesize-tests (typespec-tests-alist)
+  "Generate all tests from TYPESPEC-TESTS-ALIST.
+The arg is an alist of: type specifier -> expected type specifier."
   `(progn
      ,@(cl-loop
         for i from 1
-        for (ts . exp-ts) in comp-cstr-typespec-tests-alist
-        append (list (comp-cstr-typespec-test i ts exp-ts)))))
-
-(comp-cstr-synthesize-tests)
+        for (type-spec . expected-type-spec) in typespec-tests-alist
+        collect
+        `(ert-deftest ,(intern (format "comp-cstr-test-%d" i)) ()
+          (should (equal (comp-cstr-test-ts ',type-spec)
+                         ',expected-type-spec))))))
+
+(comp-cstr-synthesize-tests
+ (;; 1
+  (symbol . symbol)
+  ;; 2
+  ((or string array) . array)
+  ;; 3
+  ((or symbol number) . (or number symbol))
+  ;; 4
+  ((or cons atom) . t) ;; Like SBCL
+  ;; 5
+  ((or integer number) . number)
+  ;; 6
+  ((or (or integer symbol) number) . (or number symbol))
+  ;; 7
+  ((or (or integer symbol) (or number list)) . (or list number symbol))
+  ;; 8
+  ((or (or integer number) nil) . number)
+  ;; 9
+  ((member foo) . (member foo))
+  ;; 10
+  ((member foo bar) . (member bar foo))
+  ;; 11
+  ((or (member foo) (member bar)) . (member bar foo))
+  ;; 12
+  ((or (member foo) symbol) . symbol) ;; SBCL return (OR SYMBOL (MEMBER FOO))
+  ;; 13
+  ((or (member foo) number) .  (or (member foo) number))
+  ;; 14
+  ((or (integer 1 3) number) . number)
+  ;; 15
+  (integer . integer)
+  ;; 16
+  ((integer 1 2) . (integer 1 2))
+  ;; 17
+  ((or (integer -1  0) (integer 3  4)) . (or (integer -1  0) (integer 3  4)))
+  ;; 18
+  ((or (integer -1  2) (integer 3  4)) . (integer -1 4))
+  ;; 19
+  ((or (integer -1  3) (integer 3  4)) . (integer -1 4))
+  ;; 20
+  ((or (integer -1  4) (integer 3  4)) . (integer -1 4))
+  ;; 21
+  ((or (integer -1  5) (integer 3  4)) . (integer -1 5))
+  ;; 22
+  ((or (integer -1  *) (integer 3  4)) . (integer -1 *))
+  ;; 23
+  ((or (integer -1  2) (integer *  4)) . (integer * 4))
+  ;; 24
+  ((and string array) . string)
+  ;; 25
+  ((and cons atom) . nil)
+  ;; 26
+  ((and (member foo) (member foo bar baz)) . (member foo))
+  ;; 27
+  ((and (member foo) (member bar)) . nil)
+  ;; 28
+  ((and (member foo) symbol) . (member foo))
+  ;; 29
+  ((and (member foo) string) . nil)
+  ;; 30
+  ((and (member foo) (integer 1 2)) . nil)
+  ;; 31
+  ((and (member 1 2) (member 3 2)) . (integer 2 2))
+  ;; 32
+  ((and number (integer 1 2)) . (integer 1 2))
+  ;; 33
+  ((and integer (integer 1 2)) . (integer 1 2))
+  ;; 34
+  ((and (integer -1 0) (integer 3 5)) . nil)
+  ;; 35
+  ((and (integer -1 2) (integer 3 5)) . nil)
+  ;; 36
+  ((and (integer -1 3) (integer 3 5)) . (integer 3 3))
+  ;; 37
+  ((and (integer -1 4) (integer 3 5)) . (integer 3 4))
+  ;; 38
+  ((and (integer -1 5) nil) . nil)
+  ;; 39
+  ((not symbol) . (not symbol))
+  ;; 40
+  ((or (member foo) (not (member foo bar))) . (not (member bar)))
+  ;; 41
+  ((or (member foo bar) (not (member foo))) . t)
+  ;; 42
+  ((or symbol (not sequence)) . (not sequence))
+  ;; 43
+  ((or symbol (not symbol)) . t)
+  ;; 44
+  ((or symbol (not sequence)) . (not sequence))
+  ;; 45 Conservative.
+  ((or vector (not sequence)) . t)
+  ;; 46
+  ((or (integer 1 10) (not (integer * 5))) . (not (integer * 0)))
+  ;; 47
+  ((or symbol (integer 1 10) (not (integer * 5))) . (not (integer * 0)))
+  ;; 48
+  ((or (not symbol) (integer 1 10) (not (integer * 5))) . (not (or symbol 
(integer * 0))))
+  ;; 49
+  ((or symbol (not (member foo))) . (not (member foo)))
+  ;; 50
+  ((or (not symbol) (not (member foo))) . (not symbol))
+  ;; 51 Conservative.
+  ((or (not (member foo)) string) . (not (member foo)))
+  ;; 52 Conservative.
+  ((or (member foo) (not string)) . (not string))
+  ;; 53
+  ((or (not (integer 1 2)) integer) . t)
+  ;; 54
+  ((or (not (integer 1 2)) (not integer)) . (not integer))
+  ;; 55
+  ((or (integer 1 2) (not integer)) . (not (or (integer * 0) (integer 3 *))))
+  ;; 56
+  ((or number (not (integer 1 2))) . t)
+  ;; 57
+  ((or atom (not (integer 1 2))) . t)
+  ;; 58
+  ((or atom (not (member foo))) . t)
+  ;; 59
+  ((and symbol (not cons)) . symbol)
+  ;; 60
+  ((and symbol (not symbol)) . nil)
+  ;; 61
+  ((and atom (not symbol)) . atom)
+  ;; 62
+  ((and atom (not string)) . (or array sequence atom))
+  ;; 63 Conservative
+  ((and symbol (not (member foo))) . symbol)
+  ;; 64 Conservative
+  ((and symbol (not (member 3))) . symbol)
+  ;; 65
+  ((and (not (member foo)) (integer 1 10)) . (integer 1 10))
+  ;; 66
+  ((and (member foo) (not (integer 1 10))) . (member foo))
+  ;; 67
+  ((and t (not (member foo))) . (not (member foo)))
+  ;; 68
+  ((and integer (not (integer 3 4))) . (or (integer * 2) (integer 5 *)))
+  ;; 69
+  ((and (integer 0 20) (not (integer 5 10))) . (or (integer 0 4) (integer 11 
20)))
+  ;; 70
+  ((and (not (member a)) (not (member b))) . (not (member a b)))
+  ;; 71
+  ((and (not boolean) (not (member b))) . (not (or (member b) boolean)))
+  ;; 72
+  ((and t (integer 1 1)) . (integer 1 1))
+  ;; 73
+  ((not (integer -1 5)) . (not (integer -1 5)))
+  ;; 74
+  ((and boolean (or number marker)) . nil)
+  ;; 75
+  ((and atom (or number marker)) . number-or-marker)
+  ;; 76
+  ((and symbol (or number marker)) . nil)
+  ;; 77
+  ((and (or symbol string) (or number marker)) . nil)
+  ;; 78
+  ((and t t) . t)
+  ;; 79
+  ((and (or marker number) (integer 0 0)) . (integer 0 0))
+  ;; 80
+  ((and t (not t)) . nil)
+  ;; 81
+  ((or (integer 1 1) (not (integer 1 1))) . t)
+  ;; 82
+  ((not t) . nil)
+  ;; 83
+  ((not nil) . t)
+  ;; 84
+  ((or (not string) t) . t)
+  ;; 85
+  ((or (not vector) sequence) . sequence)
+  ;; 86
+  ((or (not symbol) null) . t)
+  ;; 87
+  ((and (or null integer) (not (or null integer))) . nil)
+  ;; 88
+  ((and (or (member a b c)) (not (or (member a b)))) . (member c))
+  ;; 89
+  ((or cons symbol) . (or list symbol)) ;; FIXME: Why `list'?
+  ;; 90
+  ((or string char-table bool-vector vector) . array)
+  ;; 91
+  ((or string char-table bool-vector vector number) . (or array number))
+  ;; 92
+  ((or string char-table bool-vector vector cons symbol number) .
+   (or number sequence symbol))
+  ;; 93?
+  ;; FIXME: I get `cons' rather than `list'?
+  ;;((or null cons) . list)
+  ))
 
 ;;; comp-cstr-tests.el ends here
diff --git a/test/lisp/emacs-lisp/comp-tests.el 
b/test/lisp/emacs-lisp/comp-tests.el
index 79345ac9a4e..44c8acf790a 100644
--- a/test/lisp/emacs-lisp/comp-tests.el
+++ b/test/lisp/emacs-lisp/comp-tests.el
@@ -1,6 +1,6 @@
 ;;; comp-tests.el --- Tests for comp.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/copyright-tests.el 
b/test/lisp/emacs-lisp/copyright-tests.el
index 5f8b5c67896..f69bb9f02d2 100644
--- a/test/lisp/emacs-lisp/copyright-tests.el
+++ b/test/lisp/emacs-lisp/copyright-tests.el
@@ -1,6 +1,6 @@
 ;;; copyright-tests.el --- tests for copyright.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/derived-tests.el 
b/test/lisp/emacs-lisp/derived-tests.el
index ca462c935f5..fa08b37c67d 100644
--- a/test/lisp/emacs-lisp/derived-tests.el
+++ b/test/lisp/emacs-lisp/derived-tests.el
@@ -1,6 +1,6 @@
 ;;; derived-tests.el --- tests for derived.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/easy-mmode-tests.el 
b/test/lisp/emacs-lisp/easy-mmode-tests.el
index 6d65c22f5f2..26b5450d072 100644
--- a/test/lisp/emacs-lisp/easy-mmode-tests.el
+++ b/test/lisp/emacs-lisp/easy-mmode-tests.el
@@ -1,6 +1,6 @@
 ;;; easy-mmode-tests.el --- tests for easy-mmode.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el 
b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
index b0211c915e6..ea1f7991a68 100644
--- a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
+++ b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
@@ -1,6 +1,6 @@
 ;;; edebug-test-code.el --- Sample code for the Edebug test suite  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Gemini Lasswell
 
diff --git a/test/lisp/emacs-lisp/edebug-tests.el 
b/test/lisp/emacs-lisp/edebug-tests.el
index 28a7f38c576..8c0f729dc39 100644
--- a/test/lisp/emacs-lisp/edebug-tests.el
+++ b/test/lisp/emacs-lisp/edebug-tests.el
@@ -1,6 +1,6 @@
 ;;; edebug-tests.el --- Edebug test suite   -*- lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Gemini Lasswell
 
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el 
b/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el
index bb19a579e83..b244a56779a 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el
@@ -1,6 +1,6 @@
 ;;; eieio-test-methodinvoke.el --- eieio tests for method invocation  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2005, 2008, 2010, 2013-2023 Free Software Foundation,
+;; Copyright (C) 2005, 2008, 2010, 2013-2024 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el 
b/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
index 4f13881dbd4..1bb75ae81f8 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
@@ -1,6 +1,6 @@
 ;;; eieio-test-persist.el --- Tests for eieio-persistent class  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el 
b/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
index a0507afe833..83fc476c911 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
@@ -1,6 +1,6 @@
 ;;; eieio-tests.el --- eieio test routines -*- lexical-binding: t -*-
 
-;; Copyright (C) 1999-2003, 2005-2010, 2012-2023 Free Software
+;; Copyright (C) 1999-2003, 2005-2010, 2012-2024 Free Software
 ;; Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/emacs-lisp/ert-font-lock-tests.el 
b/test/lisp/emacs-lisp/ert-font-lock-tests.el
index 33ef0c6eede..e0ba1e949b2 100644
--- a/test/lisp/emacs-lisp/ert-font-lock-tests.el
+++ b/test/lisp/emacs-lisp/ert-font-lock-tests.el
@@ -1,6 +1,6 @@
 ;;; ert-font-lock-tests.el --- ERT Font Lock tests  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: Vladimir Kazanov
 
diff --git a/test/lisp/emacs-lisp/ert-tests.el 
b/test/lisp/emacs-lisp/ert-tests.el
index 1379d40330e..d5237fa30f8 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -1,6 +1,6 @@
 ;;; ert-tests.el --- ERT's self-tests  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2007-2008, 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
 ;; Author: Christian Ohler <ohler@gnu.org>
 
@@ -93,16 +93,6 @@ failed or if there was a problem."
                      '(ert-test-failed "failure message"))
               t))))
 
-(ert-deftest ert-test-fail-debug-with-condition-case ()
-  (let ((test (make-ert-test :body (lambda () (ert-fail "failure message")))))
-    (condition-case condition
-        (progn
-          (let ((ert-debug-on-error t))
-            (ert-run-test test))
-          (cl-assert nil))
-      ((error)
-       (cl-assert (equal condition '(ert-test-failed "failure message")) t)))))
-
 (ert-deftest ert-test-fail-debug-with-debugger-1 ()
   (let ((test (make-ert-test :body (lambda () (ert-fail "failure message")))))
     (let ((debugger (lambda (&rest _args)
@@ -146,16 +136,6 @@ failed or if there was a problem."
                      '(error "Error message"))
               t))))
 
-(ert-deftest ert-test-error-debug ()
-  (let ((test (make-ert-test :body (lambda () (error "Error message")))))
-    (condition-case condition
-        (progn
-          (let ((ert-debug-on-error t))
-            (ert-run-test test))
-          (cl-assert nil))
-      ((error)
-       (cl-assert (equal condition '(error "Error message")) t)))))
-
 
 ;;; Test that `should' works.
 (ert-deftest ert-test-should ()
@@ -359,14 +339,10 @@ This macro is used to test if macroexpansion in `should' 
works."
      (,(lambda () (let ((_x t)) (should (error "Foo"))))
       (error "Foo")))
    do
-   (let ((test (make-ert-test :body body)))
-     (condition-case actual-condition
-         (progn
-           (let ((ert-debug-on-error t))
-             (ert-run-test test))
-           (cl-assert nil))
-       ((error)
-        (should (equal actual-condition expected-condition)))))))
+   (let* ((test (make-ert-test :body body))
+          (result (ert-run-test test)))
+     (should (ert-test-failed-p result))
+     (should (equal (ert-test-failed-condition result) expected-condition)))))
 
 (defun ert-test--which-file ()
   "Dummy function to help test `symbol-file' for tests.")
@@ -392,9 +368,9 @@ This macro is used to test if macroexpansion in `should' 
works."
          (result (ert-run-test test)))
     (should (ert-test-failed-p result))
     (should (memq (backtrace-frame-fun (car (ert-test-failed-backtrace 
result)))
-                  ;;; This is `ert-fail' on nativecomp and `signal'
-                  ;;; otherwise.  It's not clear whether that's a bug
-                  ;;; or not (bug#51308).
+                  ;; This is `ert-fail' on nativecomp and `signal'
+                  ;; otherwise.  It's not clear whether that's a bug
+                  ;; or not (bug#51308).
                   '(ert-fail signal)))))
 
 (ert-deftest ert-test-messages ()
@@ -880,7 +856,6 @@ This macro is used to test if macroexpansion in `should' 
works."
 
 (ert-deftest ert-test-with-demoted-errors ()
   "Check that ERT correctly handles `with-demoted-errors'."
-  :expected-result :failed  ;; FIXME!  Bug#11218
   (should-not (with-demoted-errors "FOO: %S" (error "Foo"))))
 
 (ert-deftest ert-test-fail-inside-should ()
diff --git a/test/lisp/emacs-lisp/ert-x-tests.el 
b/test/lisp/emacs-lisp/ert-x-tests.el
index 66fc14ceb86..0ad94b9b9e4 100644
--- a/test/lisp/emacs-lisp/ert-x-tests.el
+++ b/test/lisp/emacs-lisp/ert-x-tests.el
@@ -1,6 +1,6 @@
 ;;; ert-x-tests.el --- Tests for ert-x.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2008, 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008, 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Phil Hagelberg
 ;;        Christian Ohler <ohler@gnu.org>
diff --git a/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el 
b/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
index 4988babcfbd..9dc4f70a121 100644
--- a/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
+++ b/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
@@ -1,6 +1,6 @@
 ;;; faceup-test-mode.el --- Dummy major mode for testing `faceup'.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Anders Lindgren
 ;; Keywords: languages, faces
diff --git 
a/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el 
b/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el
index 9d677f48872..f92a8a9c421 100644
--- a/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el
+++ b/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el
@@ -1,6 +1,6 @@
 ;;; faceup-test-this-file-directory.el --- Support file for faceup tests  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Anders Lindgren
 ;; Keywords: languages, faces
diff --git a/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el 
b/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el
index c162354aa36..3f4f3835639 100644
--- a/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el
+++ b/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el
@@ -1,6 +1,6 @@
 ;;; faceup-test-basics.el --- Tests for the `faceup' package.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Anders Lindgren
 ;; Keywords: languages, faces
diff --git a/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el 
b/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el
index 99d3223f311..9c00505d93e 100644
--- a/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el
+++ b/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el
@@ -1,6 +1,6 @@
 ;;; faceup-test-files.el --- Self test of `faceup' using dummy major mode.  
-*- lexical-binding:t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Anders Lindgren
 ;; Keywords: languages, faces
diff --git a/test/lisp/emacs-lisp/find-func-tests.el 
b/test/lisp/emacs-lisp/find-func-tests.el
index 59ecb5ab187..a685a6cbabb 100644
--- a/test/lisp/emacs-lisp/find-func-tests.el
+++ b/test/lisp/emacs-lisp/find-func-tests.el
@@ -1,6 +1,6 @@
 ;;; find-func-tests.el --- Unit tests for find-func.el  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords:
diff --git a/test/lisp/emacs-lisp/float-sup-tests.el 
b/test/lisp/emacs-lisp/float-sup-tests.el
index f0e192d1e76..0d00050f75d 100644
--- a/test/lisp/emacs-lisp/float-sup-tests.el
+++ b/test/lisp/emacs-lisp/float-sup-tests.el
@@ -1,6 +1,6 @@
 ;;; float-sup-tests.el --- Tests for float-sup.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/generator-tests.el 
b/test/lisp/emacs-lisp/generator-tests.el
index fa4df77b9b7..68fdc9324e2 100644
--- a/test/lisp/emacs-lisp/generator-tests.el
+++ b/test/lisp/emacs-lisp/generator-tests.el
@@ -1,6 +1,6 @@
 ;;; generator-tests.el --- Testing generators -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Daniel Colascione <dancol@dancol.org>
 ;; Keywords:
diff --git a/test/lisp/emacs-lisp/gv-tests.el b/test/lisp/emacs-lisp/gv-tests.el
index f57b2c69fe4..4cc235c141f 100644
--- a/test/lisp/emacs-lisp/gv-tests.el
+++ b/test/lisp/emacs-lisp/gv-tests.el
@@ -1,6 +1,6 @@
 ;;; gv-tests.el --- tests for gv.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/hierarchy-tests.el 
b/test/lisp/emacs-lisp/hierarchy-tests.el
index 97a0f7ba52c..3333f4014e6 100644
--- a/test/lisp/emacs-lisp/hierarchy-tests.el
+++ b/test/lisp/emacs-lisp/hierarchy-tests.el
@@ -570,8 +570,9 @@ should fail as this function will crash."
 
 (defun hierarchy-examples-delayed--childrenfn (hier-elem)
   "Return the children of HIER-ELEM.
-Basially, feed the number, minus 1, to 
`hierarchy-examples-delayed--find-number'
-and then create a list of the number plus 0.0–0.9."
+Basically, feed the number, minus 1, to
+`hierarchy-examples-delayed--find-number' and then create a list of the
+number plus 0.0–0.9."
 
   (when (> hier-elem 1)
     (let ((next (hierarchy-examples-delayed--find-number (1- hier-elem))))
diff --git a/test/lisp/emacs-lisp/icons-tests.el 
b/test/lisp/emacs-lisp/icons-tests.el
index fdfbd1ff7cb..fa320a49866 100644
--- a/test/lisp/emacs-lisp/icons-tests.el
+++ b/test/lisp/emacs-lisp/icons-tests.el
@@ -1,6 +1,6 @@
 ;;; icons-tests.el --- Tests for icons.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/let-alist-tests.el 
b/test/lisp/emacs-lisp/let-alist-tests.el
index cf4cba50367..235e5908cc0 100644
--- a/test/lisp/emacs-lisp/let-alist-tests.el
+++ b/test/lisp/emacs-lisp/let-alist-tests.el
@@ -1,6 +1,6 @@
 ;;; let-alist.el --- tests for file handling. -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/lisp-mnt-tests.el 
b/test/lisp/emacs-lisp/lisp-mnt-tests.el
index c056761f0f9..e32480ada46 100644
--- a/test/lisp/emacs-lisp/lisp-mnt-tests.el
+++ b/test/lisp/emacs-lisp/lisp-mnt-tests.el
@@ -1,6 +1,6 @@
 ;;; lisp-mnt-tests.el --- Tests for lisp-mnt  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 
@@ -30,6 +30,26 @@
                  '(("Bob Weiner" . "rsw@gnu.org")
                    ("Mats Lidell" . "matsl@gnu.org")))))
 
+(ert-deftest lm--tests-lm-package-requires ()
+  (with-temp-buffer
+    (insert ";; Package-Requires: ((emacs 29.1))")
+    (should (equal (lm-package-requires) '((emacs 29.1)))))
+  (with-temp-buffer
+    (insert ";; Package-Requires: ((emacs \"26.3\") (jsonrpc \"1.0.16\") 
(flymake \"1.2.1\") (project \"0.9.8\") (xref \"1.6.2\") (eldoc \"1.14.0\") 
(seq \"2.23\") (external-completion \"0.1\"))")
+    (should (equal (lm-package-requires)
+                   '((emacs "26.3") (jsonrpc "1.0.16") (flymake "1.2.1")
+                     (project "0.9.8") (xref "1.6.2") (eldoc "1.14.0")
+                     (seq "2.23") (external-completion "0.1")))))
+  (with-temp-buffer
+    (insert ";; Package-Requires: ((emacs \"26.3\") (jsonrpc \"1.0.16\") 
(flymake \"1.2.1\")\n"
+            ";;                    (project \"0.9.8\") (xref \"1.6.2\") (eldoc 
\"1.14.0\")\n"
+            ";;                    (seq \"2.23\") (external-completion 
\"0.1\"))")
+    (should (equal (lm-package-requires)
+                   '((emacs "26.3") (jsonrpc "1.0.16") (flymake "1.2.1")
+                     (project "0.9.8") (xref "1.6.2") (eldoc "1.14.0")
+                     (seq "2.23") (external-completion "0.1"))))))
+
+
 (ert-deftest lm--tests-lm-website ()
   (with-temp-buffer
     (insert ";; URL: https://example.org/foo";)
diff --git a/test/lisp/emacs-lisp/lisp-mode-tests.el 
b/test/lisp/emacs-lisp/lisp-mode-tests.el
index 825e6b6ab80..da02be65d03 100644
--- a/test/lisp/emacs-lisp/lisp-mode-tests.el
+++ b/test/lisp/emacs-lisp/lisp-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; lisp-mode-tests.el --- Test Lisp editing commands  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/lisp-tests.el 
b/test/lisp/emacs-lisp/lisp-tests.el
index 2e5e2a740b1..0d627b01151 100644
--- a/test/lisp/emacs-lisp/lisp-tests.el
+++ b/test/lisp/emacs-lisp/lisp-tests.el
@@ -1,6 +1,6 @@
 ;;; lisp-tests.el --- Test Lisp editing commands     -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Aaron S. Hawley <aaron.s.hawley@gmail.com>
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
diff --git a/test/lisp/emacs-lisp/macroexp-resources/m1.el 
b/test/lisp/emacs-lisp/macroexp-resources/m1.el
index 5b35f60ad3d..940630cc319 100644
--- a/test/lisp/emacs-lisp/macroexp-resources/m1.el
+++ b/test/lisp/emacs-lisp/macroexp-resources/m1.el
@@ -1,6 +1,6 @@
 ;;; m1.el --- Some sample code for macroexp-tests    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords:
diff --git a/test/lisp/emacs-lisp/macroexp-resources/m2.el 
b/test/lisp/emacs-lisp/macroexp-resources/m2.el
index fb11b56c378..981ade30b4e 100644
--- a/test/lisp/emacs-lisp/macroexp-resources/m2.el
+++ b/test/lisp/emacs-lisp/macroexp-resources/m2.el
@@ -1,6 +1,6 @@
 ;;; m2.el --- More sample code for macroexp-tests    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords:
diff --git a/test/lisp/emacs-lisp/macroexp-resources/vk.el 
b/test/lisp/emacs-lisp/macroexp-resources/vk.el
index c892b279923..460b7a8e516 100644
--- a/test/lisp/emacs-lisp/macroexp-resources/vk.el
+++ b/test/lisp/emacs-lisp/macroexp-resources/vk.el
@@ -1,6 +1,6 @@
 ;;; vk.el --- test code for macroexp-tests    -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/macroexp-tests.el 
b/test/lisp/emacs-lisp/macroexp-tests.el
index d0efbfd28c1..2a57de248a2 100644
--- a/test/lisp/emacs-lisp/macroexp-tests.el
+++ b/test/lisp/emacs-lisp/macroexp-tests.el
@@ -1,6 +1,6 @@
 ;;; macroexp-tests.el --- Tests for macroexp.el      -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords:
diff --git a/test/lisp/emacs-lisp/map-tests.el 
b/test/lisp/emacs-lisp/map-tests.el
index 2204743f794..dc8121b0582 100644
--- a/test/lisp/emacs-lisp/map-tests.el
+++ b/test/lisp/emacs-lisp/map-tests.el
@@ -1,6 +1,6 @@
 ;;; map-tests.el --- Tests for map.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Petton <nicolas@petton.fr>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/emacs-lisp/memory-report-tests.el 
b/test/lisp/emacs-lisp/memory-report-tests.el
index 1bca74ca7c4..52dcb14b540 100644
--- a/test/lisp/emacs-lisp/memory-report-tests.el
+++ b/test/lisp/emacs-lisp/memory-report-tests.el
@@ -1,6 +1,6 @@
 ;;; memory-report-tests.el --- tests for memory-report.el -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/multisession-tests.el 
b/test/lisp/emacs-lisp/multisession-tests.el
index 639a8ab5219..edbc6bf02c4 100644
--- a/test/lisp/emacs-lisp/multisession-tests.el
+++ b/test/lisp/emacs-lisp/multisession-tests.el
@@ -1,6 +1,6 @@
 ;;; multisession-tests.el --- Tests for multisession.el  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/nadvice-tests.el 
b/test/lisp/emacs-lisp/nadvice-tests.el
index 7dfa936214a..1a0b8468841 100644
--- a/test/lisp/emacs-lisp/nadvice-tests.el
+++ b/test/lisp/emacs-lisp/nadvice-tests.el
@@ -1,6 +1,6 @@
 ;;; nadvice-tests.el --- Test suite for the new advice thingy.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/oclosure-tests.el 
b/test/lisp/emacs-lisp/oclosure-tests.el
index a7f2d1017a9..4760f403158 100644
--- a/test/lisp/emacs-lisp/oclosure-tests.el
+++ b/test/lisp/emacs-lisp/oclosure-tests.el
@@ -1,6 +1,6 @@
 ;;; oclosure-tests.e; --- Tests for Open Closures  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh 
b/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh
index 3f3e2fc70d2..8bb66da26dc 100755
--- a/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh
+++ b/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh
@@ -2,7 +2,7 @@
 
 # Generate a new key and update the signatures for tests.
 
-# Copyright (C) 2020-2023 Free Software Foundation, Inc.
+# Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/package-tests.el 
b/test/lisp/emacs-lisp/package-tests.el
index e44ad3677d1..d95b94f2145 100644
--- a/test/lisp/emacs-lisp/package-tests.el
+++ b/test/lisp/emacs-lisp/package-tests.el
@@ -1,6 +1,6 @@
 ;;; package-tests.el --- Tests for the Emacs package system  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Daniel Hackney <dan@haxney.org>
 ;; Version: 1.0
diff --git a/test/lisp/emacs-lisp/pcase-tests.el 
b/test/lisp/emacs-lisp/pcase-tests.el
index 799e8d36647..d062965952a 100644
--- a/test/lisp/emacs-lisp/pcase-tests.el
+++ b/test/lisp/emacs-lisp/pcase-tests.el
@@ -1,6 +1,6 @@
 ;;; pcase-tests.el --- Test suite for pcase macro.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/pp-tests.el b/test/lisp/emacs-lisp/pp-tests.el
index 1b248e19a31..b663fb365a8 100644
--- a/test/lisp/emacs-lisp/pp-tests.el
+++ b/test/lisp/emacs-lisp/pp-tests.el
@@ -1,6 +1,6 @@
 ;;; pp-tests.el --- Test suite for pretty printer.  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/range-tests.el 
b/test/lisp/emacs-lisp/range-tests.el
index c35a95a4c1e..c680ab5a9cd 100644
--- a/test/lisp/emacs-lisp/range-tests.el
+++ b/test/lisp/emacs-lisp/range-tests.el
@@ -1,6 +1,6 @@
 ;;; range-tests.el --- Tests for range.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/regexp-opt-tests.el 
b/test/lisp/emacs-lisp/regexp-opt-tests.el
index 1eefd7b210c..1f168d2895c 100644
--- a/test/lisp/emacs-lisp/regexp-opt-tests.el
+++ b/test/lisp/emacs-lisp/regexp-opt-tests.el
@@ -1,6 +1,6 @@
 ;;; regexp-opt-tests.el --- Tests for regexp-opt.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords:       internal
diff --git a/test/lisp/emacs-lisp/ring-tests.el 
b/test/lisp/emacs-lisp/ring-tests.el
index f8f2cfc37de..8cf81818c39 100644
--- a/test/lisp/emacs-lisp/ring-tests.el
+++ b/test/lisp/emacs-lisp/ring-tests.el
@@ -1,6 +1,6 @@
 ;;; ring-tests.el --- Tests for ring.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/emacs-lisp/rmc-tests.el 
b/test/lisp/emacs-lisp/rmc-tests.el
index bf0ff59151d..b1fbcd25bd0 100644
--- a/test/lisp/emacs-lisp/rmc-tests.el
+++ b/test/lisp/emacs-lisp/rmc-tests.el
@@ -1,6 +1,6 @@
 ;;; rmc-tests.el --- Test suite for rmc.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Tino Calancha <tino.calancha@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/emacs-lisp/rx-tests.el b/test/lisp/emacs-lisp/rx-tests.el
index e773ddf158e..072209bcbcc 100644
--- a/test/lisp/emacs-lisp/rx-tests.el
+++ b/test/lisp/emacs-lisp/rx-tests.el
@@ -1,6 +1,6 @@
 ;;; rx-tests.el --- tests for rx.el              -*- lexical-binding: t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/seq-tests.el 
b/test/lisp/emacs-lisp/seq-tests.el
index 71ff991c215..c06ceb00bdb 100644
--- a/test/lisp/emacs-lisp/seq-tests.el
+++ b/test/lisp/emacs-lisp/seq-tests.el
@@ -1,6 +1,6 @@
 ;;; seq-tests.el --- Tests for seq.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Petton <nicolas@petton.fr>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/emacs-lisp/shadow-tests.el 
b/test/lisp/emacs-lisp/shadow-tests.el
index d3b18aa5987..3c88bd42f06 100644
--- a/test/lisp/emacs-lisp/shadow-tests.el
+++ b/test/lisp/emacs-lisp/shadow-tests.el
@@ -1,6 +1,6 @@
 ;;; shadow-tests.el --- Test suite for shadow.  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/shortdoc-tests.el 
b/test/lisp/emacs-lisp/shortdoc-tests.el
index 596b47d2543..3aaccff707c 100644
--- a/test/lisp/emacs-lisp/shortdoc-tests.el
+++ b/test/lisp/emacs-lisp/shortdoc-tests.el
@@ -1,6 +1,6 @@
 ;;; shortdoc-tests.el --- tests for shortdoc.el   -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/subr-x-tests.el 
b/test/lisp/emacs-lisp/subr-x-tests.el
index 63d8fcd080c..162cad23b88 100644
--- a/test/lisp/emacs-lisp/subr-x-tests.el
+++ b/test/lisp/emacs-lisp/subr-x-tests.el
@@ -1,6 +1,6 @@
 ;;; subr-x-tests.el --- Testing the extended lisp routines  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Fabián E. Gallina <fgallina@gnu.org>
 ;; Keywords:
diff --git a/test/lisp/emacs-lisp/syntax-tests.el 
b/test/lisp/emacs-lisp/syntax-tests.el
index 6cdbca984ac..5b3a0fe32a8 100644
--- a/test/lisp/emacs-lisp/syntax-tests.el
+++ b/test/lisp/emacs-lisp/syntax-tests.el
@@ -1,6 +1,6 @@
 ;;; syntax-tests.el --- tests for syntax.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/tabulated-list-tests.el 
b/test/lisp/emacs-lisp/tabulated-list-tests.el
index 115a7e735a2..8be2be3139e 100644
--- a/test/lisp/emacs-lisp/tabulated-list-tests.el
+++ b/test/lisp/emacs-lisp/tabulated-list-tests.el
@@ -1,6 +1,6 @@
 ;;; tabulated-list-tests.el --- Tests for emacs-lisp/tabulated-list.el  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
 
diff --git a/test/lisp/emacs-lisp/testcover-resources/testcases.el 
b/test/lisp/emacs-lisp/testcover-resources/testcases.el
index 48c73648259..fd1ff0e1aa1 100644
--- a/test/lisp/emacs-lisp/testcover-resources/testcases.el
+++ b/test/lisp/emacs-lisp/testcover-resources/testcases.el
@@ -1,6 +1,6 @@
 ;;;; testcases.el -- Test cases for testcover-tests.el
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Gemini Lasswell
 
diff --git a/test/lisp/emacs-lisp/testcover-tests.el 
b/test/lisp/emacs-lisp/testcover-tests.el
index 989dd40b646..f0f30feecf4 100644
--- a/test/lisp/emacs-lisp/testcover-tests.el
+++ b/test/lisp/emacs-lisp/testcover-tests.el
@@ -1,6 +1,6 @@
 ;;; testcover-tests.el --- Testcover test suite   -*- lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Gemini Lasswell
 
diff --git a/test/lisp/emacs-lisp/text-property-search-tests.el 
b/test/lisp/emacs-lisp/text-property-search-tests.el
index 2c701c2c8e4..73946cba8ea 100644
--- a/test/lisp/emacs-lisp/text-property-search-tests.el
+++ b/test/lisp/emacs-lisp/text-property-search-tests.el
@@ -1,6 +1,6 @@
 ;;; text-property-search-tests.el --- Testing text-property-search  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Ingebrigtsen <larsi@gnus.org>
 ;; Keywords:
diff --git a/test/lisp/emacs-lisp/thunk-tests.el 
b/test/lisp/emacs-lisp/thunk-tests.el
index 5ae0e2a3d7d..440e66ae30d 100644
--- a/test/lisp/emacs-lisp/thunk-tests.el
+++ b/test/lisp/emacs-lisp/thunk-tests.el
@@ -1,6 +1,6 @@
 ;;; thunk-tests.el --- Tests for thunk.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Petton <nicolas@petton.fr>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/emacs-lisp/timer-tests.el 
b/test/lisp/emacs-lisp/timer-tests.el
index 7652b324493..ab1b57eec0d 100644
--- a/test/lisp/emacs-lisp/timer-tests.el
+++ b/test/lisp/emacs-lisp/timer-tests.el
@@ -1,6 +1,6 @@
 ;;; timer-tests.el --- tests for timers -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/unsafep-tests.el 
b/test/lisp/emacs-lisp/unsafep-tests.el
index 368eee796ea..8a41707b6a5 100644
--- a/test/lisp/emacs-lisp/unsafep-tests.el
+++ b/test/lisp/emacs-lisp/unsafep-tests.el
@@ -2,7 +2,7 @@
 
 ;; Author: Jonathan Yavner <jyavner@member.fsf.org>
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/vtable-tests.el 
b/test/lisp/emacs-lisp/vtable-tests.el
index 2da1bbaabb1..08fdf1594a4 100644
--- a/test/lisp/emacs-lisp/vtable-tests.el
+++ b/test/lisp/emacs-lisp/vtable-tests.el
@@ -1,6 +1,6 @@
 ;;; vtable-tests.el --- Tests for vtable.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emacs-lisp/warnings-tests.el 
b/test/lisp/emacs-lisp/warnings-tests.el
index 22520d0e84f..a0ef2ffd332 100644
--- a/test/lisp/emacs-lisp/warnings-tests.el
+++ b/test/lisp/emacs-lisp/warnings-tests.el
@@ -2,7 +2,7 @@
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/emulation/viper-tests.el 
b/test/lisp/emulation/viper-tests.el
index a0b1a823909..96c467e621f 100644
--- a/test/lisp/emulation/viper-tests.el
+++ b/test/lisp/emulation/viper-tests.el
@@ -1,6 +1,6 @@
 ;;; viper-tests.el --- tests for viper.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/env-tests.el b/test/lisp/env-tests.el
index 579f73b1b21..4ccec5f3c41 100644
--- a/test/lisp/env-tests.el
+++ b/test/lisp/env-tests.el
@@ -1,6 +1,6 @@
 ;;; env-tests.el --- Tests for env.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/epg-config-tests.el b/test/lisp/epg-config-tests.el
index 51d2052c27d..09fb18e32f0 100644
--- a/test/lisp/epg-config-tests.el
+++ b/test/lisp/epg-config-tests.el
@@ -1,6 +1,6 @@
 ;;; epg-config-tests.el --- Test suite for epg.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/epg-tests.el b/test/lisp/epg-tests.el
index ed9da90c029..a1748b39f74 100644
--- a/test/lisp/epg-tests.el
+++ b/test/lisp/epg-tests.el
@@ -1,6 +1,6 @@
 ;;; epg-tests.el --- Test suite for epg.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-button-tests.el 
b/test/lisp/erc/erc-button-tests.el
index 34ad06b7eb8..ba6fe9fd8c1 100644
--- a/test/lisp/erc/erc-button-tests.el
+++ b/test/lisp/erc/erc-button-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-button-tests.el --- Tests for erc-button  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 ;;
@@ -21,12 +21,15 @@
 
 ;;; Code:
 
+(require 'ert-x) ; cl-lib
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-tests-common)))
+
 (require 'erc-button)
 
 (ert-deftest erc-button-alist--url ()
-  (setq erc-server-process
-        (start-process "sleep" (current-buffer) "sleep" "1"))
-  (set-process-query-on-exit-flag erc-server-process nil)
+  (erc-tests-common-init-server-proc "sleep" "1")
   (with-current-buffer (erc--open-target "#chan")
     (let ((verify
            (lambda (p url)
@@ -65,9 +68,7 @@
   (apply #'erc-button-add-button rest))
 
 (defun erc-button-tests--erc-button-alist--function-as-form (func)
-  (setq erc-server-process
-        (start-process "sleep" (current-buffer) "sleep" "1"))
-  (set-process-query-on-exit-flag erc-server-process nil)
+  (erc-tests-common-init-server-proc "sleep" "1")
 
   (with-current-buffer (erc--open-target "#chan")
     (let* ((erc-button-tests--form nil)
@@ -102,9 +103,7 @@
      (apply #'erc-button-add-button r))))
 
 (defun erc-button-tests--erc-button-alist--nil-form (form)
-  (setq erc-server-process
-        (start-process "sleep" (current-buffer) "sleep" "1"))
-  (set-process-query-on-exit-flag erc-server-process nil)
+  (erc-tests-common-init-server-proc "sleep" "1")
 
   (with-current-buffer (erc--open-target "#chan")
     (let* ((erc-button-tests--form nil)
@@ -228,11 +227,9 @@
           (inhibit-message noninteractive)
           erc-modules
           erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
-      (erc-mode)
-      (setq erc-server-process
-            (start-process "sleep" (current-buffer) "sleep" "1"))
-      (set-process-query-on-exit-flag erc-server-process nil)
-      (erc--initialize-markers (point) nil)
+      (erc-tests-common-prep-for-insertion)
+      (erc-tests-common-init-server-proc "sleep" "1")
+
       (erc-button-mode +1)
       (should (equal (erc-button--display-error-notice-with-keys
                       "If \\[erc-bol] fails, "
diff --git a/test/lisp/erc/erc-dcc-tests.el b/test/lisp/erc/erc-dcc-tests.el
index a750c96c80f..a2fb0392727 100644
--- a/test/lisp/erc/erc-dcc-tests.el
+++ b/test/lisp/erc/erc-dcc-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-dcc-tests.el --- Tests for erc-dcc  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 ;;
diff --git a/test/lisp/erc/erc-fill-tests.el b/test/lisp/erc/erc-fill-tests.el
index bfdf8cd7320..0f19b481f37 100644
--- a/test/lisp/erc/erc-fill-tests.el
+++ b/test/lisp/erc/erc-fill-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-fill-tests.el --- Tests for erc-fill  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 ;;
@@ -24,6 +24,10 @@
 
 ;;; Code:
 (require 'ert-x)
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-tests-common)))
+
 (require 'erc-fill)
 
 (defvar erc-fill-tests--buffers nil)
@@ -35,7 +39,8 @@
 
 (defun erc-fill-tests--insert-privmsg (speaker &rest msg-parts)
   (declare (indent 1))
-  (let* ((msg (erc-format-privmessage speaker
+  (let* ((erc--msg-prop-overrides `((erc--msg . msg)))
+         (msg (erc-format-privmessage speaker
                                       (apply #'concat msg-parts) nil t))
          (parsed (make-erc-response :unparsed (format ":%s PRIVMSG #chan :%s"
                                                       speaker msg)
@@ -57,9 +62,7 @@
         erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
     (cl-letf (((symbol-function 'erc-server-connect)
                (lambda (&rest _)
-                 (setq erc-server-process
-                       (start-process "sleep" (current-buffer) "sleep" "1"))
-                 (set-process-query-on-exit-flag erc-server-process nil))))
+                 (erc-tests-common-init-server-proc "sleep" "1"))))
       (with-current-buffer
           (car (push (erc-open "localhost" 6667 "tester" "Tester" 'connect
                                nil nil nil nil nil "tester" 'foonet)
@@ -105,10 +108,9 @@
             (when set-transient-map-timer
               (timer-event-handler set-transient-map-timer))
             (set-window-buffer (selected-window) original-window-buffer)
-            (when noninteractive
-              (while-let ((buf (pop erc-fill-tests--buffers)))
-                (kill-buffer buf))
-              (kill-buffer))))))))
+            (when (or noninteractive (getenv "ERC_TESTS_GRAPHICAL"))
+              (erc-tests-common-kill-buffers erc-fill-tests--buffers)
+              (setq erc-fill-tests--buffers nil))))))))
 
 (defun erc-fill-tests--wrap-check-prefixes (&rest prefixes)
   ;; Check that prefix props are applied over correct intervals.
@@ -133,72 +135,21 @@
       (should (equal (get-text-property (1- (pos-eol)) 'wrap-prefix)
                      '(space :width erc-fill--wrap-value))))))
 
-;; Use this variable to generate new snapshots after carefully
-;; reviewing the output of *each* snapshot (not just first and last).
-;; Obviously, only run one test at a time.
-(defvar erc-fill-tests--save-p (getenv "ERC_TESTS_FILL_SAVE"))
-
 ;; On graphical displays, echo .graphic >> .git/info/exclude
-(defvar erc-fill-tests--graphic-dir "fill/snapshots/.graphic")
+(defvar erc-fill-tests--graphic-dir "fill/snapshots/.graphic/")
 
 (defun erc-fill-tests--compare (name)
-  (let* ((dir (expand-file-name (if (display-graphic-p)
-                                    erc-fill-tests--graphic-dir
-                                  "fill/snapshots/")
-                                (ert-resource-directory)))
-         (expect-file (file-name-with-extension (expand-file-name name dir)
-                                                "eld"))
-         (erc--own-property-names
-          (seq-difference `(font-lock-face ,@erc--own-property-names)
-                          '(field display wrap-prefix line-prefix)
-                          #'eq))
-         (print-circle t)
-         (print-escape-newlines t)
-         (print-escape-nonascii t)
-         (got (erc--remove-text-properties
-               (buffer-substring (point-min) erc-insert-marker)))
-         (repr (string-replace "erc-fill--wrap-value"
-                               (number-to-string erc-fill--wrap-value)
-                               (prin1-to-string got))))
-    (with-current-buffer (generate-new-buffer name)
-      (push (current-buffer) erc-fill-tests--buffers)
-      (with-silent-modifications
-        (insert (setq got (read repr))))
-      (erc-mode))
-    (if erc-fill-tests--save-p
-        (let (inhibit-message)
-          (with-temp-file expect-file
-            (insert repr))
-          ;; Limit writing snapshots to one test at a time.
-          (setq erc-fill-tests--save-p nil)
-          (message "erc-fill-tests--compare: wrote %S" expect-file))
-      (if (file-exists-p expect-file)
-          ;; Ensure string-valued properties, like timestamps, aren't
-          ;; recursive (signals `max-lisp-eval-depth' exceeded).
-          (named-let assert-equal
-              ((latest (read repr))
-               (expect (read (with-temp-buffer
-                               (insert-file-contents-literally expect-file)
-                               (buffer-string)))))
-            (pcase latest
-              ((or "" 'nil) t)
-              ((pred stringp)
-               (should (equal-including-properties latest expect))
-               (let ((latest-intervals (object-intervals latest))
-                     (expect-intervals (object-intervals expect)))
-                 (while-let ((l-iv (pop latest-intervals))
-                             (x-iv (pop expect-intervals))
-                             (l-tab (map-into (nth 2 l-iv) 'hash-table))
-                             (x-tab (map-into (nth 2 x-iv) 'hash-table)))
-                   (pcase-dolist (`(,l-k . ,l-v) (map-pairs l-tab))
-                     (assert-equal l-v (gethash l-k x-tab))
-                     (remhash l-k x-tab))
-                   (should (zerop (hash-table-count x-tab))))))
-              ((pred sequencep)
-               (assert-equal (seq-first latest) (seq-first expect))
-               (assert-equal (seq-rest latest) (seq-rest expect)))
-              (_ (should (equal latest expect)))))
-        (message "Snapshot file missing: %S" expect-file)))))
+  (let ((dir (expand-file-name (if (display-graphic-p)
+                                   erc-fill-tests--graphic-dir
+                                 "fill/snapshots/" )
+                               (ert-resource-directory)))
+        (transform-fn (lambda (got)
+                        (string-replace "erc-fill--wrap-value"
+                                        (number-to-string erc-fill--wrap-value)
+                                        got)))
+        (buffer-setup-fn (lambda ()
+                           (push (current-buffer) erc-fill-tests--buffers))))
+    (erc-tests-common-snapshot-compare name dir transform-fn buffer-setup-fn)))
 
 ;; To inspect variable pitch, set `erc-mode-hook' to
 ;;
@@ -207,7 +158,8 @@
 ;; or similar.
 
 (ert-deftest erc-fill-wrap--monospace ()
-  :tags '(:unstable)
+  :tags `(:unstable
+          ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
   (unless (>= emacs-major-version 29)
     (ert-skip "Emacs version too low, missing `buffer-text-pixel-size'"))
 
@@ -253,7 +205,8 @@
       (erc-fill--wrap-rejigger-region (point-min) erc-insert-marker nil nil))))
 
 (ert-deftest erc-fill-wrap--merge ()
-  :tags '(:unstable)
+  :tags `(:unstable
+          ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
   (unless (>= emacs-major-version 29)
     (ert-skip "Emacs version too low, missing `buffer-text-pixel-size'"))
 
@@ -338,23 +291,27 @@
      (erc-fill-tests--compare compare-file))))
 
 (ert-deftest erc-fill-wrap--merge-action ()
-  :tags '(:unstable)
+  :tags `(:unstable
+          ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
   (erc-fill-wrap-tests--merge-action "merge-wrap-01"))
 
 (ert-deftest erc-fill-wrap--merge-action/indicator-pre ()
-  :tags '(:unstable)
+  :tags `(:unstable
+          ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
   (let ((erc-fill-wrap-merge-indicator '(pre ?> shadow)))
     (erc-fill-wrap-tests--merge-action "merge-wrap-indicator-pre-01")))
 
 ;; One crucial thing this test asserts is that the indicator is
 ;; omitted when the previous line ends in a stamp.
 (ert-deftest erc-fill-wrap--merge-action/indicator-post ()
-  :tags '(:unstable)
+  :tags `(:unstable
+          ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
   (let ((erc-fill-wrap-merge-indicator '(post ?~ shadow)))
     (erc-fill-wrap-tests--merge-action "merge-wrap-indicator-post-01")))
 
 (ert-deftest erc-fill-line-spacing ()
-  :tags '(:unstable)
+  :tags `(:unstable
+          ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
   (unless (>= emacs-major-version 29)
     (ert-skip "Emacs version too low, missing `buffer-text-pixel-size'"))
 
@@ -368,7 +325,8 @@
        (erc-fill-tests--compare "spacing-01-mono")))))
 
 (ert-deftest erc-fill-wrap-visual-keys--body ()
-  :tags '(:unstable)
+  :tags `(:unstable
+          ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
   (erc-fill-tests--wrap-populate
 
    (lambda ()
@@ -410,7 +368,8 @@
        (should-not (looking-at (rx "<alice> ")))))))
 
 (ert-deftest erc-fill-wrap-visual-keys--prompt ()
-  :tags '(:unstable)
+  :tags `(:unstable
+          ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
   (erc-fill-tests--wrap-populate
 
    (lambda ()
@@ -453,7 +412,8 @@
        (execute-kbd-macro "\C-a")))))
 
 (ert-deftest erc-fill--left-hand-stamps ()
-  :tags '(:unstable)
+  :tags `(:unstable
+          ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
   (unless (>= emacs-major-version 29)
     (ert-skip "Emacs version too low, missing `buffer-text-pixel-size'"))
 
diff --git a/test/lisp/erc/erc-goodies-tests.el 
b/test/lisp/erc/erc-goodies-tests.el
index cdf861e2018..170e28bda96 100644
--- a/test/lisp/erc/erc-goodies-tests.el
+++ b/test/lisp/erc/erc-goodies-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-goodies-tests.el --- Tests for erc-goodies  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 ;;
@@ -20,6 +20,10 @@
 ;;; Commentary:
 ;;; Code:
 (require 'ert-x)
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-tests-common)))
+
 (require 'erc-goodies)
 
 (defun erc-goodies-tests--assert-face (beg end-str present &optional absent)
@@ -247,15 +251,16 @@
 
 (defun erc-goodies-tests--assert-kp-indicator-on ()
   (should erc--keep-place-indicator-overlay)
-  (should (local-variable-p 'window-configuration-change-hook))
-  (should window-configuration-change-hook)
+  (should (memq 'erc--keep-place-indicator-on-window-buffer-change
+                window-buffer-change-functions))
   (should (memq 'erc-keep-place erc-insert-pre-hook))
   (should (eq erc-keep-place-mode
               (not (local-variable-p 'erc-insert-pre-hook)))))
 
 (defun erc-goodies-tests--assert-kp-indicator-off ()
   (should-not (local-variable-p 'erc-insert-pre-hook))
-  (should-not (local-variable-p 'window-configuration-change-hook))
+  (should-not (memq 'erc--keep-place-indicator-on-window-buffer-change
+                    window-buffer-change-functions))
   (should-not erc--keep-place-indicator-overlay))
 
 (defun erc-goodies-tests--kp-indicator-populate ()
@@ -268,12 +273,9 @@
   (goto-char erc-input-marker))
 
 (defun erc-goodies-tests--keep-place-indicator (test)
-  (with-current-buffer (get-buffer-create "*erc-keep-place-indicator-mode*")
-    (erc-mode)
-    (erc--initialize-markers (point) nil)
-    (setq erc-server-process
-          (start-process "sleep" (current-buffer) "sleep" "1"))
-    (set-process-query-on-exit-flag erc-server-process nil)
+  (erc-keep-place-mode -1)
+  (with-current-buffer (erc-tests-common-make-server-buf
+                        "*erc-keep-place-indicator-mode*")
     (let (erc-connect-pre-hook
           erc-modules)
 
@@ -290,7 +292,7 @@
       (should-not (member 'erc-keep-place
                           (default-value 'erc-insert-pre-hook)))
       (should-not (local-variable-p 'erc-insert-pre-hook))
-      (kill-buffer))))
+      (erc-tests-common-kill-buffers))))
 
 (ert-deftest erc-keep-place-indicator-mode--no-global ()
   (erc-goodies-tests--keep-place-indicator
@@ -420,4 +422,21 @@
        (goto-char (overlay-start erc--keep-place-indicator-overlay))
        (should (looking-at (rx "*** This buffer is for text")))))))
 
+(ert-deftest erc--get-inserted-msg-beg/readonly ()
+  (erc-tests-common-assert-get-inserted-msg-readonly-with
+   #'erc-tests-common-assert-get-inserted-msg/basic
+   (lambda (arg) (should (= 3 (erc--get-inserted-msg-beg arg))))))
+
+(ert-deftest erc--get-inserted-msg-end/readonly ()
+  (erc-tests-common-assert-get-inserted-msg-readonly-with
+   #'erc-tests-common-assert-get-inserted-msg/basic
+   (lambda (arg) (should (= 11 (erc--get-inserted-msg-end arg))))))
+
+(ert-deftest erc--get-inserted-msg-bounds/readonly ()
+  (erc-tests-common-assert-get-inserted-msg-readonly-with
+   #'erc-tests-common-assert-get-inserted-msg/basic
+   (lambda (arg)
+     (should (equal '(3 . 11) (erc--get-inserted-msg-bounds arg))))))
+
+
 ;;; erc-goodies-tests.el ends here
diff --git a/test/lisp/erc/erc-join-tests.el b/test/lisp/erc/erc-join-tests.el
index e293c9976a1..830f0711dde 100644
--- a/test/lisp/erc/erc-join-tests.el
+++ b/test/lisp/erc/erc-join-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-join-tests.el --- Tests for erc-join.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 ;;
diff --git a/test/lisp/erc/erc-match-tests.el b/test/lisp/erc/erc-match-tests.el
index 748ccd02ddf..34610fc0438 100644
--- a/test/lisp/erc/erc-match-tests.el
+++ b/test/lisp/erc/erc-match-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-match-tests.el --- Tests for erc-match.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-networks-tests.el 
b/test/lisp/erc/erc-networks-tests.el
index d0f1dddf6b3..53cff8f489c 100644
--- a/test/lisp/erc/erc-networks-tests.el
+++ b/test/lisp/erc/erc-networks-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-networks-tests.el --- Tests for erc-networks.  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 ;;
@@ -20,25 +20,21 @@
 ;;; Code:
 
 (require 'ert-x) ; cl-lib
-(require 'erc)
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-tests-common)))
 
 (defun erc-networks-tests--create-dead-proc (&optional buf)
   (let ((p (start-process "true" (or buf (current-buffer)) "true")))
     (while (process-live-p p) (sit-for 0.1))
     p))
 
-(defun erc-networks-tests--create-live-proc (&optional buf)
-  (let ((proc (start-process "sleep" (or buf (current-buffer)) "sleep" "1")))
-    (set-process-query-on-exit-flag proc nil)
-    proc))
+(defun erc-networks-tests--create-live-proc ()
+  (erc-tests-common-init-server-proc "sleep" "1"))
 
 ;; When we drop 27, call `get-buffer-create with INHIBIT-BUFFER-HOOKS.
 (defun erc-networks-tests--clean-bufs ()
-  (let (erc-kill-channel-hook
-        erc-kill-server-hook
-        erc-kill-buffer-hook)
-    (dolist (buf (erc-buffer-list))
-      (kill-buffer buf))))
+  (erc-tests-common-kill-buffers))
 
 (defun erc-networks-tests--bufnames (prefix)
   (let* ((case-fold-search)
@@ -1442,10 +1438,12 @@
   (let* (erc-kill-server-hook
          erc-insert-modify-hook
          (old-buf (get-buffer-create "FooNet"))
-         (old-proc (erc-networks-tests--create-live-proc old-buf))) ; live
+         ;;
+         old-proc) ; live
 
     (with-current-buffer old-buf
       (erc-mode)
+      (setq old-proc (erc-networks-tests--create-live-proc))
       (erc--initialize-markers (point) nil)
       (insert "*** Old buf")
       (setq erc-network 'FooNet
@@ -1763,4 +1761,50 @@
       (should (equal (erc-ports-list (nth 4 srv))
                      '(6697 9999))))))
 
+(ert-deftest erc-networks--examine-targets ()
+  (with-current-buffer (erc-tests-common-make-server-buf "foonet")
+    (erc--open-target "#chan")
+    (erc--open-target "#spam"))
+
+  (with-current-buffer (erc-tests-common-make-server-buf "barnet")
+    (with-current-buffer (erc--open-target "*query")
+      (setq erc-networks--id nil))
+    (with-current-buffer (erc--open-target "#chan")
+      (let ((calls ())
+            (snap (lambda (parameter)
+                    (list parameter
+                          (erc-target)
+                          (erc-networks--id-symbol erc-networks--id)))))
+
+        ;; Search for "#chan" dupes among targets of all servers.
+        (should (equal
+                 (erc-networks--examine-targets erc-networks--id erc--target
+                   (lambda () (push (funcall snap 'ON-DUPE) calls))
+                   (lambda () (push (funcall snap 'ON-COLL) calls)))
+                 (list (get-buffer "#chan@foonet")
+                       (get-buffer "#chan@barnet"))))
+
+        (should (equal (pop calls) '(ON-DUPE "#chan" barnet)))
+        (should (equal (pop calls) '(ON-COLL "#chan" foonet)))
+        (should-not calls)
+        (should-not (get-buffer "#chan"))
+        (should (get-buffer "#chan@barnet"))
+        (should (get-buffer "#chan@foonet"))
+
+        ;; Search for "*query" dupes among targets of all servers.
+        (should (equal (erc-networks--examine-targets erc-networks--id
+                           (buffer-local-value 'erc--target
+                                               (get-buffer "*query"))
+                         (lambda () (push (funcall snap 'ON-DUPE) calls))
+                         (lambda () (push (funcall snap 'ON-COLL) calls)))
+                       (list (get-buffer "*query"))))
+
+        (should (equal (pop calls) '(ON-DUPE "*query" barnet)))
+        (should-not calls)))
+
+    (goto-char (point-min))
+    (should (search-forward "Missing network session" nil t)))
+
+  (erc-tests-common-kill-buffers))
+
 ;;; erc-networks-tests.el ends here
diff --git a/test/lisp/erc/erc-nicks-tests.el b/test/lisp/erc/erc-nicks-tests.el
index 35264a23caa..08080d249d5 100644
--- a/test/lisp/erc/erc-nicks-tests.el
+++ b/test/lisp/erc/erc-nicks-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-nicks-tests.el --- Tests for erc-nicks  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -409,7 +409,7 @@
              (push-button)
              (should (search-forward-regexp
                       (rx "Foreground: #" (group (+ xdigit)) eol)))
-             (forward-button 1)
+             (forward-button 2) ; skip Inherit:...
              (push-button))
 
            (ert-info ("First entry's sample is rendered correctly")
diff --git a/test/lisp/erc/erc-sasl-tests.el b/test/lisp/erc/erc-sasl-tests.el
index 767a8f56f54..afe55f522dd 100644
--- a/test/lisp/erc/erc-sasl-tests.el
+++ b/test/lisp/erc/erc-sasl-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-sasl-tests.el --- Tests for erc-sasl.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 ;;
 ;; This file is part of GNU Emacs.
 ;;
diff --git a/test/lisp/erc/erc-scenarios-auth-source.el 
b/test/lisp/erc/erc-scenarios-auth-source.el
index 7eaf90e1e41..f0a7a4cbaca 100644
--- a/test/lisp/erc/erc-scenarios-auth-source.el
+++ b/test/lisp/erc/erc-scenarios-auth-source.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-auth-source.el --- auth-source scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-association-nick.el 
b/test/lisp/erc/erc-scenarios-base-association-nick.el
index 5f90f0d2bcd..57e8abda73c 100644
--- a/test/lisp/erc/erc-scenarios-base-association-nick.el
+++ b/test/lisp/erc/erc-scenarios-base-association-nick.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-association-nick.el --- base assoc scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-association-query.el 
b/test/lisp/erc/erc-scenarios-base-association-query.el
index e9472617918..3ee71a70e96 100644
--- a/test/lisp/erc/erc-scenarios-base-association-query.el
+++ b/test/lisp/erc/erc-scenarios-base-association-query.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-association-query.el --- assoc query scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-association-samenet.el 
b/test/lisp/erc/erc-scenarios-base-association-samenet.el
index c64a3f6725b..07d9102f5f0 100644
--- a/test/lisp/erc/erc-scenarios-base-association-samenet.el
+++ b/test/lisp/erc/erc-scenarios-base-association-samenet.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-association-samenet.el --- assoc samenet scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-association.el 
b/test/lisp/erc/erc-scenarios-base-association.el
index 10abe14c43b..deac0e0cac7 100644
--- a/test/lisp/erc/erc-scenarios-base-association.el
+++ b/test/lisp/erc/erc-scenarios-base-association.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-association.el --- base assoc scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-attach.el 
b/test/lisp/erc/erc-scenarios-base-attach.el
index ccf5d1f9582..dcd16ed6bca 100644
--- a/test/lisp/erc/erc-scenarios-base-attach.el
+++ b/test/lisp/erc/erc-scenarios-base-attach.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-attach.el --- Reattach scenarios -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -47,11 +47,11 @@
 ;;   Author:     Mario Lang <mlang@delysid.org>
 ;;   AuthorDate: Mon Nov 26 18:33:19 2001 +0000
 ;;
-;;   * new function erc-BBDB-NICK to handle nickname anotation ...
+;;   * new function erc-BBDB-NICK to handle nickname annotation ...
 ;;   * Applied antifuchs/mhp patches, the latest on erc-help, unmodified
 ;;   * New variable: erc-reuse-buffers default to t.
 ;;   * Modified erc-generate-new-buffer-name to use it. it checks if
-;;     server and port are the same, then one can assume thats the same
+;;     server and port are the same, then one can assume that's the same
 ;;     channel/query target again.
 
 ;;; Code:
diff --git a/test/lisp/erc/erc-scenarios-base-auto-recon.el 
b/test/lisp/erc/erc-scenarios-base-auto-recon.el
index 40e2c23408b..808b1d8c4d4 100644
--- a/test/lisp/erc/erc-scenarios-base-auto-recon.el
+++ b/test/lisp/erc/erc-scenarios-base-auto-recon.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-auto-recon.el --- auto-recon scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-buffer-display.el 
b/test/lisp/erc/erc-scenarios-base-buffer-display.el
index 889f274b8b1..5c3c526f86d 100644
--- a/test/lisp/erc/erc-scenarios-base-buffer-display.el
+++ b/test/lisp/erc/erc-scenarios-base-buffer-display.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-buffer-display.el --- Buffer display scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-chan-modes.el 
b/test/lisp/erc/erc-scenarios-base-chan-modes.el
index 9c63d8aff8e..3183cd27370 100644
--- a/test/lisp/erc/erc-scenarios-base-chan-modes.el
+++ b/test/lisp/erc/erc-scenarios-base-chan-modes.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-chan-modes.el --- Channel mode scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -81,4 +81,62 @@
       (should-not erc-channel-user-limit)
       (funcall expect 10 "<Chad> after"))))
 
+;; This asserts proper recognition of nonstandard prefixes advertised
+;; via the "PREFIX=" ISUPPORT parameter.  Note that without the IRCv3
+;; `multi-prefix' extension, we can't easily sync a user's channel
+;; membership status on receipt of a 352/353 by parsing the "flags"
+;; parameter because even though servers remember multiple prefixes,
+;; they only ever return the one with the highest rank.  For example,
+;; if on receipt of a 352, we were to "update" someone we believe to
+;; be @+ by changing them to a to @, we'd be guilty of willful
+;; munging.  And if they later lose that @, we'd then see them as null
+;; when in fact they're still +.  However, we *could* use a single
+;; degenerate prefix to "validate" an existing record to ensure
+;; correctness of our processing logic, but it's unclear how such a
+;; discrepancy ought to be handled beyond asking the user to file a
+;; bug.
+(ert-deftest erc-scenarios-base-chan-modes--speaker-status ()
+  :tags '(:expensive-test)
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/modes")
+       (erc-server-flood-penalty 0.1)
+       (dumb-server (erc-d-run "localhost" t 'speaker-status))
+       (erc-show-speaker-membership-status t)
+       (erc-autojoin-channels-alist '(("." "#chan")))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to foonet")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port (process-contact dumb-server :service)
+                                :nick "tester"
+                                :user "tester")
+        (funcall expect 5 "Here on foonet, we provide services")))
+
+    (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+
+      (ert-info ("Prefixes printed correctly in 353")
+        (funcall expect 10 "chan: +alice @fsbot -bob !foop"))
+
+      (ert-info ("Speakers honor option `erc-show-speaker-membership-status'")
+        (funcall expect 10 "<-bob> alice: Of that which hath")
+        (funcall expect 10 "<+alice> Hie you, make haste")
+        (funcall expect 10 "<!foop> hi"))
+
+      (ert-info ("Status conferred and rescinded")
+        (funcall expect 10 "*** foop (user@netadmin.example.net) has changed ")
+        (funcall expect 10 "mode for #chan to +v bob")
+        (funcall expect 10 "<+bob> alice: Fair as a text B")
+        (funcall expect 10 "<+alice> bob: Even as Apemantus")
+        (funcall expect 10 "mode for #chan to -v bob")
+        (funcall expect 10 "<-bob> alice: That's the way")
+        (funcall expect 10 "<+alice> Give it the beasts"))
+
+      ;; If it had instead overwritten it, our two states would be
+      ;; out of sync.  (See comment above.)
+      (ert-info ("/WHO output confirms server shadowed V status")
+        (erc-scenarios-common-say "/who #chan")
+        (funcall expect 10 '(: "bob" (+ " ") "H-"))
+        (funcall expect 10 "<-bob> alice: Remains in danger")
+        (erc-cmd-QUIT "")))))
+
 ;;; erc-scenarios-base-chan-modes.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el 
b/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el
index 9275aba2875..d1124269e0a 100644
--- a/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el
+++ b/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-compat-rename-bouncer.el --- Compat-rename scenarios 
-*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-local-module-modes.el 
b/test/lisp/erc/erc-scenarios-base-local-module-modes.el
index 7b91e28dc83..a3612070f7e 100644
--- a/test/lisp/erc/erc-scenarios-base-local-module-modes.el
+++ b/test/lisp/erc/erc-scenarios-base-local-module-modes.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-local-module-modes.el --- More local-mod ERC tests -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-local-modules.el 
b/test/lisp/erc/erc-scenarios-base-local-modules.el
index d6dbd87c8cc..9604c6ea17c 100644
--- a/test/lisp/erc/erc-scenarios-base-local-modules.el
+++ b/test/lisp/erc/erc-scenarios-base-local-modules.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-local-modules.el --- Local-module tests for ERC -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-misc-regressions.el 
b/test/lisp/erc/erc-scenarios-base-misc-regressions.el
index 85b2c03b6a4..df2aa8e82ec 100644
--- a/test/lisp/erc/erc-scenarios-base-misc-regressions.el
+++ b/test/lisp/erc/erc-scenarios-base-misc-regressions.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-misc-regressions.el --- misc regressions scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el 
b/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el
index 876f2e3cade..4e5c535b40a 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-netid-bouncer-id.el --- net-id bouncer ID scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el 
b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el
index d3d07493e9e..e5453c40e56 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-netid-bouncer-recon-base.el --- net-id base scenarios 
-*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el 
b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el
index b76633f3e3e..09ddcef5fa3 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-netid-bouncer-recon-both.el --- net-id both scenarios 
-*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 ;;
 ;; This file is part of GNU Emacs.
 ;;
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el 
b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el
index 66d3c25f7da..253ab4f72c9 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-netid-bouncer-recon-id.el --- recon ID scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer.el 
b/test/lisp/erc/erc-scenarios-base-netid-bouncer.el
index a658a17601b..1a3946db45e 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-bouncer.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-netid-bouncer.el --- net-id bouncer scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-netid-samenet.el 
b/test/lisp/erc/erc-scenarios-base-netid-samenet.el
index 997dab93735..fee7d78f0e2 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-samenet.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-samenet.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-netid-samenet.el --- One-network net-ID scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-reconnect.el 
b/test/lisp/erc/erc-scenarios-base-reconnect.el
index 7bd16d1ed14..6f968b9fcbc 100644
--- a/test/lisp/erc/erc-scenarios-base-reconnect.el
+++ b/test/lisp/erc/erc-scenarios-base-reconnect.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-reconnect.el --- Base-reconnect scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -171,7 +171,7 @@
           (funcall expect 2 "Canceled")
           (funcall expect 3 "Opening connection")
           (funcall expect 2 "Password incorrect")
-          (funcall expect 2 "Connection failed!")
+          (funcall expect 10 "Connection failed!")
           (funcall expect 2 "Re-establishing connection"))
         (ert-info ("Explicitly cancel timer")
           (erc-cmd-RECONNECT "cancel")
diff --git a/test/lisp/erc/erc-scenarios-base-renick.el 
b/test/lisp/erc/erc-scenarios-base-renick.el
index 5a87e5871f7..ca22728b152 100644
--- a/test/lisp/erc/erc-scenarios-base-renick.el
+++ b/test/lisp/erc/erc-scenarios-base-renick.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-renick.el --- Re-nicking scenarios -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -267,7 +267,7 @@
 
     (ert-info ("Sync convo for rando@foonet")
       (with-current-buffer "rando@foonet"
-        (funcall expect 1 "u are dumb")
+        (funcall expect 10 "u are dumb")
         (erc-scenarios-common-say "not so")))
 
     (ert-info ("Sync convo for rando@barnet")
diff --git a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el 
b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
index af483bb1a52..f07b7024bf3 100644
--- a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
+++ b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-reuse-buffers.el --- base-reuse-buffers scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-send-message.el 
b/test/lisp/erc/erc-scenarios-base-send-message.el
index bf9e0f5ae3a..729c94f5ab7 100644
--- a/test/lisp/erc/erc-scenarios-base-send-message.el
+++ b/test/lisp/erc/erc-scenarios-base-send-message.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-send-message.el --- `send-message' scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-split-line.el 
b/test/lisp/erc/erc-scenarios-base-split-line.el
index f6d888c1f28..dee5950f8ef 100644
--- a/test/lisp/erc/erc-scenarios-base-split-line.el
+++ b/test/lisp/erc/erc-scenarios-base-split-line.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-split-line.el --- ERC line splitting -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-statusmsg.el 
b/test/lisp/erc/erc-scenarios-base-statusmsg.el
new file mode 100644
index 00000000000..480ba7fa8d0
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-statusmsg.el
@@ -0,0 +1,103 @@
+;;; erc-scenarios-base-statusmsg.el --- statusmsg tests -*- lexical-binding: t 
-*-
+
+;; Copyright (C) 2023-2024 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/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-base-statusmsg ()
+
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/display-message")
+       (dumb-server (erc-d-run "localhost" t 'statusmsg))
+       (erc-autojoin-channels-alist '((foonet "#mine")))
+       (erc-modules (cons 'fill-wrap erc-modules))
+       (port (process-contact dumb-server :service))
+       (erc-show-speaker-membership-status nil)
+       (erc-server-flood-penalty 0.1)
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :user "tester"
+                                :full-name "tester")
+        (funcall expect 5 "This server is in debug mode")))
+
+    (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#mine"))
+
+      (ert-info ("Receive status messages unprefixed")
+        (funcall expect 5 "+dummy")
+        (funcall expect 5 "(dummy+) hello")
+        (should (eq 'statusmsg (erc--get-inserted-msg-prop 'erc--msg)))
+        (should (equal "dummy" (erc--get-inserted-msg-prop 'erc--spkr)))
+        (should (eq (get-text-property (1- (point)) 'font-lock-face)
+                    'erc-default-face))
+        (funcall expect 5 "(dummy+) there")
+        (should (equal "" (get-text-property (pos-bol) 'display)))
+
+        ;; CTCP ACTION
+        (funcall expect 5 "* (dummy+) sad")
+        (should (eq 'ctcp-action-statusmsg
+                    (erc--get-inserted-msg-prop 'erc--msg)))
+        (should (eq (get-text-property (1- (point)) 'font-lock-face)
+                    'erc-action-face))
+        (funcall expect 5 "* (dummy+) glad")
+        (should (equal "" (get-text-property (pos-bol) 'display))))
+
+      (ert-info ("Send status messages")
+        ;; We don't have `echo-message' yet, so ERC doesn't currently
+        ;; insert commands like "/msg +#mine foo".
+        (let ((erc-default-recipients '("+#mine")))
+          (erc-send-message "howdy"))
+        (funcall expect 5 "(@tester+) howdy")
+        (should (eq 'statusmsg-input (erc--get-inserted-msg-prop 'erc--msg)))
+        (should (equal "tester" (erc--get-inserted-msg-prop 'erc--spkr)))
+        (should (eq (get-text-property (1- (point)) 'font-lock-face)
+                    'erc-input-face))
+        (let ((erc-default-recipients '("+#mine")))
+          (erc-send-message "tenderfoot"))
+        (funcall expect 5 "(@tester+) tenderfoot")
+        (should (equal "" (get-text-property (pos-bol) 'display)))
+
+        ;; Simulate some "echoed" CTCP ACTION messages since we don't
+        ;; actually support that yet.
+        (funcall expect 5 "* (@tester+) mad")
+        (should (eq 'ctcp-action-statusmsg-input
+                    (erc--get-inserted-msg-prop 'erc--msg)))
+        (should (equal (get-text-property (1- (point)) 'font-lock-face)
+                       '(erc-input-face erc-action-face)))
+        (funcall expect 5 "* (@tester+) chad")
+        (should (equal "" (get-text-property (pos-bol) 'display))))
+
+      (ert-info ("Receive status messages prefixed")
+        (setq erc-show-speaker-membership-status t)
+        (erc-scenarios-common-say "/me ready") ; sync
+        (funcall expect 5 "* @tester ready")
+        (funcall expect 5 "(+dummy+) okie")
+
+        ;; CTCP ACTION
+        (funcall expect 5 "* (+dummy+) dokie")
+        (funcall expect 5 "* +dummy out")))))
+
+;;; erc-scenarios-base-statusmsg.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-unstable.el 
b/test/lisp/erc/erc-scenarios-base-unstable.el
index 2ccf8880b95..a88d8e17077 100644
--- a/test/lisp/erc/erc-scenarios-base-unstable.el
+++ b/test/lisp/erc/erc-scenarios-base-unstable.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-unstable.el --- base unstable scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el 
b/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el
index fc8be982f65..cf7af1ae9a7 100644
--- a/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el
+++ b/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-upstream-recon-soju.el --- Bouncer recon scenario -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el 
b/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el
index 461dac27b21..f3905974a11 100644
--- a/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el
+++ b/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-base-upstream-recon-znc.el --- Bouncer recon scenario -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -42,4 +42,50 @@
    'znc-foonet
    'znc-barnet))
 
+;; Here, the upstream connection is already severed when first
+;; connecting.  The bouncer therefore sends query messages from an
+;; administrative bot before the first numerics burst, which results
+;; in a target buffer not being associated with an `erc-networks--id'.
+;; The problem only manifests later, when the buffer-association
+;; machinery checks the names of all target buffers and assumes a
+;; non-nil `erc-networks--id'.
+(ert-deftest erc-scenarios-upstream-recon--znc/severed ()
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/upstream-reconnect")
+       (erc-d-t-cleanup-sleep-secs 1)
+       (erc-server-flood-penalty 0.1)
+       (dumb-server (erc-d-run "localhost" t 'znc-severed))
+       (port (process-contact dumb-server :service))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to foonet")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :user "tester@vanilla/foonet"
+                                :password "changeme"
+                                :full-name "tester")
+        (erc-scenarios-common-assert-initial-buf-name nil port)
+        (erc-d-t-wait-for 6 (eq (erc-network) 'foonet))))
+
+    (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "*status"))
+      (funcall expect 10 "Connection Refused.  Reconnecting...")
+      (funcall expect 10 "Connected!"))
+
+    (ert-info ("Join #chan")
+      (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+        (funcall expect 10 "<alice> tester, welcome!")
+        (funcall expect 10 "<bob> alice: And see a fearful sight")
+        (funcall expect 10 "<eve> hola")
+        (funcall expect 10 "<Evel> hell o")
+        ;;
+        (funcall expect 10 "<alice> bob: Or to drown my clothes")))
+
+    (ert-info ("Buffer not renamed with net id")
+      (should (get-buffer "*status")))
+
+    (ert-info ("No error")
+      (with-current-buffer (messages-buffer)
+        (funcall expect -0.1 "error in process filter")))))
+
 ;;; erc-scenarios-base-upstream-recon-znc.el ends here
diff --git a/test/lisp/erc/erc-scenarios-display-message.el 
b/test/lisp/erc/erc-scenarios-display-message.el
index c7e0c2fc17a..8e9c355576e 100644
--- a/test/lisp/erc/erc-scenarios-display-message.el
+++ b/test/lisp/erc/erc-scenarios-display-message.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-display-message.el --- erc-display-message -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -50,12 +50,12 @@
       (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "dummy"))
         (funcall expect 10 "<dummy> hi")
         (funcall expect 10 "*** dummy (~u@rdjcgiwfuwqmc.irc) has quit")
-        (should (eq 'QUIT (get-text-property (match-beginning 0) 'erc-msg)))))
+        (should (eq 'QUIT (get-text-property (match-beginning 0) 'erc--msg)))))
 
     (ert-info ("Dummy's QUIT notice in #chan contains metadata props")
       (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
         (funcall expect 10 "*** dummy (~u@rdjcgiwfuwqmc.irc) has quit")
-        (should (eq 'QUIT (get-text-property (match-beginning 0) 'erc-msg)))))
+        (should (eq 'QUIT (get-text-property (match-beginning 0) 'erc--msg)))))
 
     (with-current-buffer "foonet"
       (erc-cmd-QUIT ""))))
diff --git a/test/lisp/erc/erc-scenarios-internal.el 
b/test/lisp/erc/erc-scenarios-internal.el
index 18eb94e24b0..6911bcc9aac 100644
--- a/test/lisp/erc/erc-scenarios-internal.el
+++ b/test/lisp/erc/erc-scenarios-internal.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-internal.el --- Proxy file for erc-d tests -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -24,8 +24,37 @@
   (when (and (getenv "EMACS_TEST_DIRECTORY")
              (getenv "EMACS_TEST_JUNIT_REPORT"))
     (setq ert-load-file-name (or (macroexp-file-name) buffer-file-name)))
-  (let ((load-path (cons (expand-file-name "erc-d" (ert-resource-directory))
-                         load-path)))
-    (load "erc-d-tests" nil 'silent)))
+  (let ((load-path `(,(expand-file-name "erc-d" (ert-resource-directory))
+                     ,(ert-resource-directory)
+                     ,@load-path)))
+    ;; Run all tests in ./resources/erc-d/erc-d-tests.el.
+    (load "erc-d-tests" nil 'silent)
+    (require 'erc-tests-common)))
+
+;; Run all tests tagged `:erc--graphical' in an "interactive"
+;; subprocess.  Time out after 90 seconds.
+(ert-deftest erc-scenarios-internal--run-graphical-all ()
+  :tags '(:expensive-test :unstable)
+  (unless (and (getenv "ERC_TESTS_GRAPHICAL_ALL")
+               (not (getenv "ERC_TESTS_GRAPHICAL"))
+               (not (getenv "CI")))
+    (ert-skip "Environmental conditions unmet"))
+
+  (let* ((default-directory (expand-file-name "../" (ert-resource-directory)))
+         (libs (directory-files default-directory 'full (rx ".el" eot)))
+         (process-environment (cons "ERC_TESTS_GRAPHICAL=1"
+                                    process-environment))
+         (program '(progn (ert (quote (tag :erc--graphical)))
+                          (with-current-buffer ert--output-buffer-name
+                            (kill-emacs (ert--stats-failed-unexpected
+                                         ert--results-stats)))))
+         (proc (erc-tests-common-create-subprocess program
+                                                   '( "-L" "." "-l" "ert")
+                                                   libs)))
+
+    (erc-d-t-wait-for 90 "interactive tests to complete"
+      (not (process-live-p proc)))
+
+    (should (zerop (process-exit-status proc)))))
 
 ;;; erc-scenarios-internal.el ends here
diff --git a/test/lisp/erc/erc-scenarios-join-auth-source.el 
b/test/lisp/erc/erc-scenarios-join-auth-source.el
index 6ed5bc2db37..b04700e6311 100644
--- a/test/lisp/erc/erc-scenarios-join-auth-source.el
+++ b/test/lisp/erc/erc-scenarios-join-auth-source.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-join-auth-source.el --- join-auth-source scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-join-display-context.el 
b/test/lisp/erc/erc-scenarios-join-display-context.el
index 32b782d2af1..84297de7acd 100644
--- a/test/lisp/erc/erc-scenarios-join-display-context.el
+++ b/test/lisp/erc/erc-scenarios-join-display-context.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-join-display-context.el --- buffer-display autojoin ctx -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el 
b/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el
index 812ac1c3b56..3f1f864179b 100644
--- a/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el
+++ b/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-join-netid-newcmd-id.el --- join netid newcmd scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-join-netid-newcmd.el 
b/test/lisp/erc/erc-scenarios-join-netid-newcmd.el
index c8e9d66906e..955ea465f79 100644
--- a/test/lisp/erc/erc-scenarios-join-netid-newcmd.el
+++ b/test/lisp/erc/erc-scenarios-join-netid-newcmd.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-join-netid-newcmd.el --- join netid newcmd scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-join-netid-recon-id.el 
b/test/lisp/erc/erc-scenarios-join-netid-recon-id.el
index 0e0fc9132b8..9910cd95b22 100644
--- a/test/lisp/erc/erc-scenarios-join-netid-recon-id.el
+++ b/test/lisp/erc/erc-scenarios-join-netid-recon-id.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-join-netid-recon-id.el --- join-netid-recon scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-join-netid-recon.el 
b/test/lisp/erc/erc-scenarios-join-netid-recon.el
index 0f76617faa5..3943c139465 100644
--- a/test/lisp/erc/erc-scenarios-join-netid-recon.el
+++ b/test/lisp/erc/erc-scenarios-join-netid-recon.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-join-netid-recon.el --- join-netid-recon scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-keep-place-indicator.el 
b/test/lisp/erc/erc-scenarios-keep-place-indicator.el
new file mode 100644
index 00000000000..ccd6f81b7d2
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-keep-place-indicator.el
@@ -0,0 +1,141 @@
+;;; erc-scenarios-keep-place-indicator.el --- erc-keep-place-indicator-mode 
-*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 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/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-scenarios-common)))
+
+(require 'erc-goodies)
+
+;; This test shows that the indicator does not update when at least
+;; one window remains.  When the last window showing a buffer switches
+;; away, the indicator is updated if it's earlier in the buffer.
+(ert-deftest erc-scenarios-keep-place-indicator--follow ()
+  :tags `(:expensive-test
+          ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
+  (when (version< emacs-version "29") (ert-skip "Times out"))
+  ;; XXX verify that this continues to be the case ^.
+
+  (should-not erc-scrolltobottom-all)
+  (should-not erc-scrolltobottom-mode)
+  (should-not erc-keep-place-mode)
+
+  (erc-scenarios-common-with-noninteractive-in-term
+      ((erc-scenarios-common-dialog "keep-place")
+       (dumb-server (erc-d-run "localhost" t 'follow))
+       (port (process-contact dumb-server :service))
+       (erc-modules `( keep-place-indicator scrolltobottom fill-wrap
+                       ,@erc-modules))
+       (erc-keep-place-indicator-follow t)
+       (erc-scrolltobottom-all t)
+       (erc-server-flood-penalty 0.1)
+       (erc-autojoin-channels-alist '((foonet "#chan" "#spam")))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :full-name "tester"
+                                :nick "tester"
+                                :user "tester")
+        (funcall expect 10 "debug mode")))
+
+    (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+      (set-window-buffer nil (current-buffer))
+      (delete-other-windows)
+      (split-window-below)
+      (funcall expect 10 "<bob> tester, welcome!")
+      (recenter 0)
+      (other-window 1)
+      (funcall expect 10 "<alice> tester, welcome!")
+      (recenter 0)
+      (should (= 2 (length (window-list))))
+
+      (ert-info ("Last window to switch away has point earlier in buffer")
+        ;; Lower window, with point later in buffer, switches away first.
+        (switch-to-buffer (erc-d-t-wait-for 10 (get-buffer "#spam"))) ; lower
+        (other-window 1)
+        (switch-to-buffer "#spam") ; upper
+        (erc-scenarios-common-say "one")
+        (funcall expect 10 "Ay, the heads")
+
+        ;; Overlay has moved to upper window start.
+        (switch-to-buffer "#chan")
+        (redisplay) ; force overlay to update
+        (save-excursion
+          (goto-char (window-point))
+          (should (looking-back (rx "<bob> tester, welcome!")))
+          (should (= (pos-bol) (window-start)))
+          (erc-d-t-wait-for 20
+              (= (overlay-start erc--keep-place-indicator-overlay) (pos-bol))))
+        ;; Lower window is still centered at start.
+        (other-window 1)
+        (switch-to-buffer "#chan")
+        (save-excursion
+          (goto-char (window-point))
+          (should (looking-back (rx "<alice> tester, welcome!")))
+          (should (= (pos-bol) (window-start)))))
+
+      (ert-info ("Last window to switch away has point later in buffer")
+        ;; Lower window advances.
+        (funcall expect 10 "<bob> alice: Since you can cog")
+        (recenter 0)
+        (redisplay) ; force ^ to appear on first line
+
+        (other-window 1) ; upper still at indicator, switches first
+        (switch-to-buffer "#spam")
+        (other-window 1)
+        (switch-to-buffer "#spam") ; lower follows, speaks to sync
+        (erc-scenarios-common-say "two")
+        (funcall expect 10 "<bob> Cause they take")
+        (goto-char (point-max))
+
+        ;; Upper switches back first, finds indicator gone.
+        (other-window 1)
+        (switch-to-buffer "#chan")
+        (save-excursion
+          (goto-char (window-point))
+          (should (looking-back (rx "<bob> tester, welcome!")))
+          (should (= (pos-bol) (window-start)))
+          (should (> (overlay-start erc--keep-place-indicator-overlay)
+                     (pos-eol))))
+
+        ;; Lower window follows, window-start preserved.
+        (other-window 1)
+        (switch-to-buffer "#chan")
+        (save-excursion
+          (goto-char (window-point))
+          (should (looking-back (rx "you can cog")))
+          (should (= (pos-bol) (window-start)))
+          (should (= (overlay-start erc--keep-place-indicator-overlay)
+                     (pos-bol)))))
+
+      (ert-info ("description")
+        (erc-send-input-line "#spam" "three")
+        (save-excursion (erc-d-t-search-for 10 "Ready"))
+        (switch-to-buffer "#spam")
+        (should (< (point) erc-input-marker))))
+
+    (erc-keep-place-mode -1)
+    (erc-scrolltobottom-mode -1)))
+
+;;; erc-scenarios-keep-place-indicator.el ends here
diff --git a/test/lisp/erc/erc-scenarios-log.el 
b/test/lisp/erc/erc-scenarios-log.el
index cd28ea54b2e..3c738822f96 100644
--- a/test/lisp/erc/erc-scenarios-log.el
+++ b/test/lisp/erc/erc-scenarios-log.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-log.el --- erc-log scenarios -*- lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -206,4 +206,59 @@
     (erc-truncate-mode -1)
     (when noninteractive (delete-directory tempdir :recursive))))
 
+(defvar erc-insert-timestamp-function)
+(declare-function erc-insert-timestamp-left "erc-stamp" (string))
+
+(ert-deftest erc-scenarios-log--save-buffer-in-logs/truncate-on-save ()
+  :tags '(:expensive-test)
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/assoc/bouncer-history")
+       (dumb-server (erc-d-run "localhost" t 'foonet))
+       (tempdir (make-temp-file "erc-tests-log." t nil nil))
+       (erc-log-channels-directory tempdir)
+       (erc-modules (cons 'log erc-modules))
+       (port (process-contact dumb-server :service))
+       (erc-truncate-buffer-on-save t)
+       (logchan (expand-file-name (format "#chan!tester@127.0.0.1:%d.txt" port)
+                                  tempdir))
+       (erc-server-flood-penalty 0.1)
+       (erc-insert-timestamp-function #'erc-insert-timestamp-left)
+       (expect (erc-d-t-make-expecter)))
+
+    (unless noninteractive
+      (add-hook 'kill-emacs-hook
+                (lambda () (delete-directory tempdir :recursive))))
+
+    (ert-info ("Connect to foonet")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "foonet:changeme"
+                                :full-name "tester")
+        (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+    (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+      (funcall expect 10 "<someone> [07:04:10] hi everyone")
+      (should-not (file-exists-p logchan))
+      ;; Simulate an M-x erc-save-buffer-in-logs RET
+      (cl-letf (((symbol-function 'called-interactively-p) #'always))
+        (call-interactively #'erc-save-buffer-in-logs))
+      (should (file-exists-p logchan))
+      (funcall expect 10 "<alice> bob: As't please your lordship")
+      (erc-save-buffer-in-logs)
+      ;; Not truncated when called by lisp code.
+      (should (> (buffer-size) 400)))
+
+    (ert-info ("No double entries")
+      (with-temp-buffer
+        (insert-file-contents logchan)
+        (funcall expect 0.1 "hi everyone")
+        (funcall expect -0.1 "hi everyone")
+        (funcall expect 0.1 "Playback Complete")
+        (funcall expect -0.1 "Playback Complete")
+        (funcall expect 10 "<alice> bob: As't")))
+
+    (erc-log-mode -1)
+    (when noninteractive (delete-directory tempdir :recursive))))
+
 ;;; erc-scenarios-log.el ends here
diff --git a/test/lisp/erc/erc-scenarios-match.el 
b/test/lisp/erc/erc-scenarios-match.el
index 17f7649566e..22e34a8efe8 100644
--- a/test/lisp/erc/erc-scenarios-match.el
+++ b/test/lisp/erc/erc-scenarios-match.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-match.el --- Misc `erc-match' scenarios -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -191,7 +191,7 @@
            (should (= (next-single-property-change msg-end 'invisible) end)))))
 
      (lambda ()
-       (let ((end (erc--get-inserted-msg-bounds 'end)))
+       (let ((end (erc--get-inserted-msg-end (point))))
          ;; This message has a time stamp like all the others.
          (should (eq (field-at-pos (1- end)) 'erc-timestamp))
 
@@ -304,9 +304,9 @@
                (should (= mend (field-end right-stamp)))
                (should (eq (field-at-pos (1- mend)) 'erc-timestamp))))
 
-           ;; The `erc-ts' property is present in prop stack.
-           (should (get-text-property (pos-bol) 'erc-ts))
-           (should-not (next-single-property-change (1+ (pos-bol)) 'erc-ts))
+           ;; The `erc--ts' property is present in prop stack.
+           (should (get-text-property (pos-bol) 'erc--ts))
+           (should-not (next-single-property-change (1+ (pos-bol)) 'erc--ts))
 
            ;; Line ending has the `invisible' property `match-fools'.
            (should (eq (get-text-property mbeg 'invisible) 'match-fools))
@@ -413,7 +413,7 @@
         (should-not (equal "" (get-text-property (pos-bol) 'display)))
 
         ;; No remaining meta-data positions, no more timestamps.
-        (should-not (next-single-property-change (1+ (pos-bol)) 'erc-ts))
+        (should-not (next-single-property-change (1+ (pos-bol)) 'erc--ts))
         ;; No remaining invisible messages.
         (should-not (text-property-not-all (pos-bol) erc-insert-marker
                                            'invisible nil))
@@ -456,10 +456,10 @@
              (should (eq (field-at-pos (field-end mbeg)) 'erc-timestamp))
              (should (eq (field-at-pos (1- mend)) 'erc-timestamp)))
 
-           ;; The `erc-ts' property is present in the message's
+           ;; The `erc--ts' property is present in the message's
            ;; width 1 prop collection at its first char.
-           (should (get-text-property (pos-bol) 'erc-ts))
-           (should-not (next-single-property-change (1+ (pos-bol)) 'erc-ts))
+           (should (get-text-property (pos-bol) 'erc--ts))
+           (should-not (next-single-property-change (1+ (pos-bol)) 'erc--ts))
 
            ;; Line ending has the `invisible' property `match-fools'.
            (should (= (char-after mend) ?\n))
diff --git a/test/lisp/erc/erc-scenarios-misc-commands.el 
b/test/lisp/erc/erc-scenarios-misc-commands.el
index 2a36d52b835..d6ed53b5358 100644
--- a/test/lisp/erc/erc-scenarios-misc-commands.el
+++ b/test/lisp/erc/erc-scenarios-misc-commands.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-misc-commands.el --- Misc commands for ERC -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -91,4 +91,36 @@
         (funcall expect -0.1 "Incorrect arguments")
         (funcall expect 10 "See also: HELP EXAMPLES")))))
 
+;; Note that as of ERC 5.6, there is no actual slash-command function
+;; named `erc-cmd-vhost'.  At the moment, this test merely exists to
+;; assert that the `erc-server-396' response handler updates the rolls
+;; correctly.
+(ert-deftest erc-scenarios-misc-commands--VHOST ()
+  :tags '(:expensive-test)
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "commands")
+       (erc-server-flood-penalty 0.1)
+       (dumb-server (erc-d-run "localhost" t 'vhost))
+       ;; As of ERC 5.6, we must join a channel before ERC adds itself
+       ;; to `erc-server-users'.  Without such an entry, there's
+       ;; nothing to update when the 396 arrives.
+       (erc-autojoin-channels-alist '((foonet "#chan")))
+       (port (process-contact dumb-server :service))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to server")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "changeme"
+                                :full-name "tester")
+        (funcall expect 10 "debug mode")))
+
+    (ert-info ("Send VHOST")
+      (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+        (erc-scenarios-common-say "/VHOST tester changeme")
+        (funcall expect 10 "visible host")
+        (should (string= (erc-server-user-host (erc-get-server-user "tester"))
+                         "some.host.test.cc"))))))
+
 ;;; erc-scenarios-misc-commands.el ends here
diff --git a/test/lisp/erc/erc-scenarios-misc.el 
b/test/lisp/erc/erc-scenarios-misc.el
index 2efcd7ec7fb..2afa1ce67a4 100644
--- a/test/lisp/erc/erc-scenarios-misc.el
+++ b/test/lisp/erc/erc-scenarios-misc.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-misc.el --- Misc scenarios for ERC -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -126,7 +126,7 @@
     (erc-d-t-wait-for 10 (get-buffer "foonet"))
 
     (ert-info ("Channel buffer #foo playback received")
-      (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#foo"))
+      (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#foo"))
         (funcall expect 10 "Excellent workman")))
 
     (ert-info ("Global notices routed to server buffer")
diff --git a/test/lisp/erc/erc-scenarios-prompt-format.el 
b/test/lisp/erc/erc-scenarios-prompt-format.el
index 7eccb859dbc..613ad87ccf5 100644
--- a/test/lisp/erc/erc-scenarios-prompt-format.el
+++ b/test/lisp/erc/erc-scenarios-prompt-format.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-prompt-format.el --- erc-prompt-format-mode -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-sasl.el 
b/test/lisp/erc/erc-scenarios-sasl.el
index ab652d72dd2..e070c675446 100644
--- a/test/lisp/erc/erc-scenarios-sasl.el
+++ b/test/lisp/erc/erc-scenarios-sasl.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-sasl.el --- SASL tests for ERC -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -149,23 +149,26 @@
        (erc-modules (cons 'sasl erc-modules))
        (erc-sasl-password "wrong")
        (erc-sasl-mechanism 'plain)
-       (expect (erc-d-t-make-expecter))
-       (buf nil))
+       (erc--warnings-buffer-name  "*ERC test warnings*")
+       (warnings-buffer (get-buffer-create erc--warnings-buffer-name))
+       (inhibit-message noninteractive)
+       (expect (erc-d-t-make-expecter)))
 
-    (ert-info ("Connect")
-      (setq buf (erc :server "127.0.0.1"
-                     :port port
-                     :nick "tester"
-                     :user "tester"
-                     :full-name "tester"))
-      (let ((err (should-error
-                  (with-current-buffer buf
-                    (funcall expect 20 "Connection failed!")))))
-        (should (string-search "please review" (cadr err)))
-        (with-current-buffer buf
-          (funcall expect 10 "Opening connection")
-          (funcall expect 20 "SASL authentication failed")
-          (should-not (erc-server-process-alive)))))))
+    (with-current-buffer (erc :server "127.0.0.1"
+                              :port port
+                              :nick "tester"
+                              :user "tester"
+                              :full-name "tester")
+      (funcall expect 10 "Opening connection")
+      (funcall expect 20 "SASL authentication failed")
+      (funcall expect 20 "Connection failed!")
+      (should-not (erc-server-process-alive)))
+
+    (with-current-buffer warnings-buffer
+      (funcall expect 10 "please review SASL settings")))
+
+  (when noninteractive
+    (should-not (get-buffer "*ERC test warnings*"))))
 
 (defun erc-scenarios--common--sasl (mech)
   (erc-scenarios-common-with-cleanup
diff --git a/test/lisp/erc/erc-scenarios-scrolltobottom-relaxed.el 
b/test/lisp/erc/erc-scenarios-scrolltobottom-relaxed.el
index 68ea0b1b070..c7260500b7d 100644
--- a/test/lisp/erc/erc-scenarios-scrolltobottom-relaxed.el
+++ b/test/lisp/erc/erc-scenarios-scrolltobottom-relaxed.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-scrolltobottom-relaxed.el --- erc-scrolltobottom-all relaxed 
-*- lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -30,7 +30,8 @@
 (require 'erc-goodies)
 
 (ert-deftest erc-scenarios-scrolltobottom--relaxed ()
-  :tags '(:expensive-test)
+  :tags `(:expensive-test
+          ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
   (when (version< emacs-version "29") (ert-skip "Times out"))
 
   (should-not erc-scrolltobottom-all)
diff --git a/test/lisp/erc/erc-scenarios-scrolltobottom.el 
b/test/lisp/erc/erc-scenarios-scrolltobottom.el
index 206687ccab5..d35d3654cd5 100644
--- a/test/lisp/erc/erc-scenarios-scrolltobottom.el
+++ b/test/lisp/erc/erc-scenarios-scrolltobottom.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-scrolltobottom.el --- erc-scrolltobottom-mode -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -30,7 +30,8 @@
 ;; now to stay in sync with `erc-scenarios-scrolltobottom--relaxed'.
 
 (ert-deftest erc-scenarios-scrolltobottom--normal ()
-  :tags '(:expensive-test)
+  :tags `(:expensive-test ,@(and (getenv "ERC_TESTS_GRAPHICAL")
+                                 '(:erc--graphical)))
   (when (version< emacs-version "29") (ert-skip "Times out"))
 
   (should-not erc-scrolltobottom-all)
@@ -45,7 +46,8 @@
              (not (erc-scenarios-common--at-win-end-p w))))))))
 
 (ert-deftest erc-scenarios-scrolltobottom--all ()
-  :tags '(:expensive-test)
+  :tags `(:expensive-test ,@(and (getenv "ERC_TESTS_GRAPHICAL")
+                                 '(:erc--graphical)))
   (when (version< emacs-version "29") (ert-skip "Times out"))
 
   (should-not erc-scrolltobottom-all)
diff --git a/test/lisp/erc/erc-scenarios-services-misc.el 
b/test/lisp/erc/erc-scenarios-services-misc.el
index 1113849578f..ab4a97c5724 100644
--- a/test/lisp/erc/erc-scenarios-services-misc.el
+++ b/test/lisp/erc/erc-scenarios-services-misc.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-services-misc.el --- Services-misc scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/erc-scenarios-stamp.el 
b/test/lisp/erc/erc-scenarios-stamp.el
index 49307dd228a..3a10f709548 100644
--- a/test/lisp/erc/erc-scenarios-stamp.el
+++ b/test/lisp/erc/erc-scenarios-stamp.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-stamp.el --- Misc `erc-stamp' scenarios -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -29,7 +29,7 @@
 (defvar erc-scenarios-stamp--user-marker nil)
 
 (defun erc-scenarios-stamp--on-post-modify ()
-  (when-let (((erc--check-msg-prop 'erc-cmd 4)))
+  (when-let (((erc--check-msg-prop 'erc--cmd 4)))
     (set-marker erc-scenarios-stamp--user-marker (point-max))
     (ert-info ("User marker correctly placed at `erc-insert-marker'")
       (should (= ?\n (char-before erc-scenarios-stamp--user-marker)))
@@ -68,11 +68,11 @@
         (ert-info ("Stamps appear in left margin and are invisible")
           (should (eq 'erc-timestamp (field-at-pos (pos-bol))))
           (should (= (pos-bol) (field-beginning (pos-bol))))
-          (should (eq 'msg (get-text-property (pos-bol) 'erc-msg)))
-          (should (eq 'NOTICE (get-text-property (pos-bol) 'erc-cmd)))
+          (should (eq 'query-notice (get-text-property (pos-bol) 'erc--msg)))
+          (should (eq 'NOTICE (get-text-property (pos-bol) 'erc--cmd)))
           (should (= ?- (char-after (field-end (pos-bol)))))
           (should (equal (get-text-property (1+ (field-end (pos-bol)))
-                                            'erc-speaker)
+                                            'erc--speaker)
                          "irc.foonet.org"))
           (should (pcase (get-text-property (pos-bol) 'display)
                     (`((margin left-margin) ,s)
@@ -104,14 +104,14 @@
           (funcall expect 5 "Opening connection")
           (goto-char (1- (match-beginning 0)))
           (should (eq 'erc-timestamp (field-at-pos (point))))
-          (should (eq 'unknown (erc--get-inserted-msg-prop 'erc-msg)))
+          (should (eq 'unknown (erc--get-inserted-msg-prop 'erc--msg)))
           ;; Force redraw of date stamp.
           (setq erc-timestamp-last-inserted-left nil)
 
           (funcall expect 5 "This server is in debug mode")
           (while (and (zerop (forward-line -1))
                       (not (eq 'erc-timestamp (field-at-pos (point))))))
-          (should (erc--get-inserted-msg-prop 'erc-cmd)))))))
+          (should (erc--get-inserted-msg-prop 'erc--cmd)))))))
 
 ;; This user-owned hook member places a marker on the first message in
 ;; a buffer.  Inserting a date stamp in front of it shouldn't move the
@@ -125,18 +125,18 @@
 
   ;; Sometime after the first message ("Opening connection.."), assert
   ;; that the marker we just placed hasn't moved.
-  (when (erc--check-msg-prop 'erc-cmd 2)
+  (when (erc--check-msg-prop 'erc--cmd 2)
     (save-restriction
       (widen)
       (ert-info ("Date stamp preserves opening user marker")
         (goto-char erc-scenarios-stamp--user-marker)
         (should-not (eq 'erc-timestamp (field-at-pos (point))))
         (should (looking-at "Opening"))
-        (should (eq 'unknown (get-text-property (point) 'erc-msg))))))
+        (should (eq 'unknown (get-text-property (point) 'erc--msg))))))
 
   ;; On 003 ("*** This server was created on"), clear state to force a
   ;; new date stamp on the next message.
-  (when (erc--check-msg-prop 'erc-cmd 3)
+  (when (erc--check-msg-prop 'erc--cmd 3)
     (setq erc-timestamp-last-inserted-left nil)
     (set-marker erc-scenarios-stamp--user-marker erc-insert-marker)))
 
@@ -174,7 +174,7 @@
           (goto-char erc-scenarios-stamp--user-marker)
           (should-not (eq 'erc-timestamp (field-at-pos (point))))
           (should (looking-at (rx "*** irc.foonet.org oragono")))
-          (should (eq 's004 (get-text-property (point) 'erc-msg))))
+          (should (eq 's004 (get-text-property (point) 'erc--msg))))
 
         (funcall expect 5 "This server is in debug mode")))))
 
diff --git a/test/lisp/erc/erc-scenarios-status-sidebar.el 
b/test/lisp/erc/erc-scenarios-status-sidebar.el
index 3a047bf3983..2523ff9ee46 100644
--- a/test/lisp/erc/erc-scenarios-status-sidebar.el
+++ b/test/lisp/erc/erc-scenarios-status-sidebar.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-status-sidebar.el --- erc-sidebar/speedbar tests -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -64,8 +64,7 @@
         (let ((obuf (window-buffer))) ; *scratch*
           (set-window-buffer (selected-window) "#foo")
           (erc-d-t-wait-for 5
-              (when noninteractive
-                (erc-status-sidebar-refresh))
+              (erc-status-sidebar-refresh)
             (with-current-buffer "*ERC Status*"
               (and (marker-position erc-status-sidebar--active-marker)
                    (goto-char erc-status-sidebar--active-marker)
@@ -100,7 +99,8 @@
 (defvar speedbar-buffer)
 
 (ert-deftest erc-scenarios-status-sidebar--nickbar ()
-  :tags '(:unstable :expensive-test)
+  :tags `(:expensive-test :unstable ,@(and (getenv "ERC_TESTS_GRAPHICAL")
+                                           '(:erc--graphical)))
   (when noninteractive (ert-skip "Interactive only"))
 
   (erc-scenarios-common-with-cleanup
diff --git a/test/lisp/erc/erc-services-tests.el 
b/test/lisp/erc/erc-services-tests.el
index 6cbba02a37e..9bafba98dc6 100644
--- a/test/lisp/erc/erc-services-tests.el
+++ b/test/lisp/erc/erc-services-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-services-tests.el --- Tests for erc-services.  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 ;;
diff --git a/test/lisp/erc/erc-stamp-tests.el b/test/lisp/erc/erc-stamp-tests.el
index cc61d599387..70ca224ac74 100644
--- a/test/lisp/erc/erc-stamp-tests.el
+++ b/test/lisp/erc/erc-stamp-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-stamp-tests.el --- Tests for erc-stamp.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 ;;
@@ -21,6 +21,10 @@
 
 ;;; Code:
 (require 'ert-x)
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-tests-common)))
+
 (require 'erc-stamp)
 (require 'erc-goodies) ; for `erc-make-read-only'
 
@@ -42,11 +46,9 @@
 
     (with-current-buffer (get-buffer-create "*erc-stamp-tests--insert-right*")
       (erc-mode)
-      (erc-munge-invisibility-spec)
+      (erc-stamp--manage-local-options-state)
       (erc--initialize-markers (point) nil)
-      (setq erc-server-process (start-process "p" (current-buffer)
-                                              "sleep" "1"))
-      (set-process-query-on-exit-flag erc-server-process nil)
+      (erc-tests-common-init-server-proc "sleep" "1")
 
       (funcall test)
 
@@ -223,17 +225,17 @@
         (erc-timestamp-intangible t) ; default changed to nil in 2014
         (erc-hide-timestamps t)
         (erc-insert-timestamp-function 'erc-insert-timestamp-left)
-        (erc-server-process (start-process "true" (current-buffer) "true"))
         (erc-insert-modify-hook '(erc-make-read-only erc-add-timestamp))
         msg
         erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
     (should (not cursor-sensor-inhibit))
-    (set-process-query-on-exit-flag erc-server-process nil)
+
     (erc-mode)
+    (erc-tests-common-init-server-proc "true")
     (with-current-buffer (get-buffer-create "*erc-timestamp-intangible*")
       (erc-mode)
       (erc--initialize-markers (point) nil)
-      (erc-munge-invisibility-spec)
+      (erc-stamp--manage-local-options-state)
       (erc-display-message nil 'notice (current-buffer) "Welcome")
       ;;
       ;; Pretend `fill' is active and that these lines are
@@ -279,7 +281,7 @@
 
   (should-not erc-echo-timestamps)
   (should-not erc-stamp--last-stamp)
-  (insert (propertize "a" 'erc-ts 433483200 'erc-msg 'msg) "bc")
+  (insert (propertize "a" 'erc--ts 433483200 'erc--msg 'msg) "bc")
   (goto-char (point-min))
   (let ((inhibit-message t)
         (erc-echo-timestamp-format "%Y-%m-%d %H:%M:%S %Z")
@@ -307,4 +309,44 @@
       (should (equal (call-interactively #'erc-echo-timestamp)
                      "1983-09-26 21:00:00 -07")))))
 
+(defun erc-stamp-tests--assert-get-inserted-msg/stamp (test-fn)
+  (let ((erc-insert-modify-hook erc-insert-modify-hook)
+        (erc-insert-timestamp-function 'erc-insert-timestamp-right)
+        (erc-timestamp-use-align-to 0)
+        (erc-timestamp-format "[00:00]"))
+    (cl-pushnew 'erc-add-timestamp erc-insert-modify-hook)
+    (erc-tests-common-get-inserted-msg-setup))
+  (goto-char 19)
+  (should (looking-back (rx "<bob> hi [00:00]")))
+  (erc-tests-common-assert-get-inserted-msg 3 19 test-fn))
+
+(ert-deftest erc--get-inserted-msg-beg/stamp ()
+  (erc-stamp-tests--assert-get-inserted-msg/stamp
+   (lambda (arg) (should (= 3 (erc--get-inserted-msg-beg arg))))))
+
+(ert-deftest erc--get-inserted-msg-beg/readonly/stamp ()
+  (erc-tests-common-assert-get-inserted-msg-readonly-with
+   #'erc-stamp-tests--assert-get-inserted-msg/stamp
+   (lambda (arg) (should (= 3 (erc--get-inserted-msg-beg arg))))))
+
+(ert-deftest erc--get-inserted-msg-end/stamp ()
+  (erc-stamp-tests--assert-get-inserted-msg/stamp
+   (lambda (arg) (should (= 19 (erc--get-inserted-msg-end arg))))))
+
+(ert-deftest erc--get-inserted-msg-end/readonly/stamp ()
+  (erc-tests-common-assert-get-inserted-msg-readonly-with
+   #'erc-stamp-tests--assert-get-inserted-msg/stamp
+   (lambda (arg) (should (= 19 (erc--get-inserted-msg-end arg))))))
+
+(ert-deftest erc--get-inserted-msg-bounds/stamp ()
+  (erc-stamp-tests--assert-get-inserted-msg/stamp
+   (lambda (arg)
+     (should (equal '(3 . 19) (erc--get-inserted-msg-bounds arg))))))
+
+(ert-deftest erc--get-inserted-msg-bounds/readonly/stamp ()
+  (erc-tests-common-assert-get-inserted-msg-readonly-with
+   #'erc-stamp-tests--assert-get-inserted-msg/stamp
+   (lambda (arg)
+     (should (equal '(3 . 19) (erc--get-inserted-msg-bounds arg))))))
+
 ;;; erc-stamp-tests.el ends here
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 477aac6c098..1649617f4b8 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-tests.el --- Tests for erc.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Ingebrigtsen <larsi@gnus.org>
 
@@ -22,7 +22,10 @@
 ;;; Code:
 
 (require 'ert-x)
-(require 'erc)
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-tests-common)))
+
 (require 'erc-ring)
 
 (ert-deftest erc--read-time-period ()
@@ -113,7 +116,7 @@
 
 (ert-deftest erc-with-server-buffer ()
   (setq erc-away 1)
-  (erc-tests--set-fake-server-process "sleep" "1")
+  (erc-tests-common-init-server-proc "sleep" "1")
 
   (let (mockingp calls)
     (advice-add 'buffer-local-value :after
@@ -154,17 +157,18 @@
       (should (equal (nth 4 form) '(widget-editable-list-match w v))))
     (should (equal (nth 4 res) ''(face)))))
 
-(defun erc-tests--send-prep ()
-  ;; Caller should probably shadow `erc-insert-modify-hook' or
-  ;; populate user tables for erc-button.
-  (erc-mode)
-  (erc--initialize-markers (point) nil)
-  (should (= (point) erc-input-marker)))
+(ert-deftest erc--doarray ()
+  (let ((array "abcdefg")
+        out)
+    ;; No return form.
+    (should-not (erc--doarray (c array) (push c out)))
+    (should (equal out '(?g ?f ?e ?d ?c ?b ?a)))
 
-(defun erc-tests--set-fake-server-process (&rest args)
-  (setq erc-server-process
-        (apply #'start-process (car args) (current-buffer) args))
-  (set-process-query-on-exit-flag erc-server-process nil))
+    ;; Return form evaluated upon completion.
+    (setq out nil)
+    (should (= 42 (erc--doarray (c array (+ 39 (length out)))
+                    (when (cl-evenp c) (push c out)))))
+    (should (equal out '(?f ?d ?b)))))
 
 (ert-deftest erc-hide-prompt ()
   (let ((erc-hide-prompt erc-hide-prompt)
@@ -172,16 +176,16 @@
         erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
 
     (with-current-buffer (get-buffer-create "ServNet")
-      (erc-tests--send-prep)
+      (erc-tests-common-prep-for-insertion)
       (goto-char erc-insert-marker)
       (should (looking-at-p (regexp-quote erc-prompt)))
-      (erc-tests--set-fake-server-process "sleep" "1")
+      (erc-tests-common-init-server-proc "sleep" "1")
       (set-process-sentinel erc-server-process #'ignore)
       (setq erc-network 'ServNet)
       (set-process-query-on-exit-flag erc-server-process nil))
 
     (with-current-buffer (get-buffer-create "#chan")
-      (erc-tests--send-prep)
+      (erc-tests-common-prep-for-insertion)
       (goto-char erc-insert-marker)
       (should (looking-at-p (regexp-quote erc-prompt)))
       (setq erc-server-process (buffer-local-value 'erc-server-process
@@ -189,7 +193,7 @@
             erc--target (erc--target-from-string "#chan")))
 
     (with-current-buffer (get-buffer-create "bob")
-      (erc-tests--send-prep)
+      (erc-tests-common-prep-for-insertion)
       (goto-char erc-insert-marker)
       (should (looking-at-p (regexp-quote erc-prompt)))
       (setq erc-server-process (buffer-local-value 'erc-server-process
@@ -310,6 +314,7 @@
                                (cl-incf counter))))
          erc-accidental-paste-threshold-seconds
          erc-insert-modify-hook
+         (erc-last-input-time 0)
          (erc-modules (remq 'stamp erc-modules))
          (erc-send-input-line-function #'ignore)
          (erc--input-review-functions erc--input-review-functions)
@@ -317,10 +322,10 @@
 
     (ert-info ("Server buffer")
       (with-current-buffer (get-buffer-create "ServNet")
-        (erc-tests--send-prep)
+        (erc-tests-common-prep-for-insertion)
         (goto-char erc-insert-marker)
         (should (looking-at-p "ServNet 3>"))
-        (erc-tests--set-fake-server-process "sleep" "1")
+        (erc-tests-common-init-server-proc "sleep" "1")
         (set-process-sentinel erc-server-process #'ignore)
         (setq erc-network 'ServNet
               erc-server-current-nick "tester"
@@ -352,7 +357,7 @@
 
     (ert-info ("Channel buffer")
       (with-current-buffer (get-buffer-create "#chan")
-        (erc-tests--send-prep)
+        (erc-tests-common-prep-for-insertion)
         (goto-char erc-insert-marker)
         (should (looking-at-p "#chan 9>"))
         (goto-char erc-input-marker)
@@ -545,7 +550,7 @@
 
 (ert-deftest erc-setup-buffer--custom-action ()
   (erc-mode)
-  (erc-tests--set-fake-server-process "sleep" "1")
+  (erc-tests-common-init-server-proc "sleep" "1")
   (setq erc--server-last-reconnect-count 0)
   (let ((owin (selected-window))
         (obuf (window-buffer))
@@ -631,8 +636,6 @@
     (should (string= "nick" (erc-lurker-maybe-trim "nick-_`")))))
 
 (ert-deftest erc-parse-user ()
-  (should (equal erc--parse-user-regexp erc--parse-user-regexp-legacy))
-
   (should (equal '("" "" "") (erc-parse-user "!@")))
   (should (equal '("" "!" "") (erc-parse-user "!!@")))
   (should (equal '("" "" "@") (erc-parse-user "!@@")))
@@ -645,46 +648,56 @@
   (should (equal '("abc" "123" "fake") (erc-parse-user "abc!123@fake")))
   (should (equal '("abc" "!123" "@xy") (erc-parse-user "abc!!123@@xy")))
 
-  (should (equal '("de" "fg" "xy") (erc-parse-user "abc\nde!fg@xy")))
+  (should (equal '("de" "fg" "xy") (erc-parse-user "abc\nde!fg@xy"))))
 
-  (ert-info ("`erc--parse-user-regexp-pedantic'")
-    (let ((erc--parse-user-regexp erc--parse-user-regexp-pedantic))
-      (should (equal '("" "" "") (erc-parse-user "!@")))
-      (should (equal '("" "!" "") (erc-parse-user "!!@")))
-      (should (equal '("" "@" "") (erc-parse-user "!@@")))
-      (should (equal '("" "!@" "") (erc-parse-user "!!@@")))
+(ert-deftest erc--parse-nuh ()
+  (should (equal '(nil nil nil) (erc--parse-nuh "!@")))
+  (should (equal '(nil nil nil) (erc--parse-nuh "@")))
+  (should (equal '(nil nil nil) (erc--parse-nuh "!")))
+  (should (equal '(nil "!" nil) (erc--parse-nuh "!!@")))
+  (should (equal '(nil "@" nil) (erc--parse-nuh "!@@")))
+  (should (equal '(nil "!@" nil) (erc--parse-nuh "!!@@")))
 
-      (should (equal '("abc" "" "") (erc-parse-user "abc")))
-      (should (equal '("" "123" "fake") (erc-parse-user "!123@fake")))
-      (should (equal '("abc" "" "123") (erc-parse-user "abc!123")))
+  (should (equal '("abc" nil nil) (erc--parse-nuh "abc!")))
+  (should (equal '(nil "abc" nil) (erc--parse-nuh "abc@")))
+  (should (equal '(nil "abc" nil) (erc--parse-nuh "!abc@")))
 
-      (should (equal '("abc" "123" "fake") (erc-parse-user "abc!123@fake")))
-      (should (equal '("abc" "!123@" "xy") (erc-parse-user "abc!!123@@xy")))
+  (should (equal '("abc" "123" "fake") (erc--parse-nuh "abc!123@fake")))
+  (should (equal '("abc" "!123@" "xy") (erc--parse-nuh "abc!!123@@xy")))
 
-      (should (equal '("de" "" "fg@xy") (erc-parse-user "abc\nde!fg@xy"))))))
+  ;; Missing leading components.
+  (should (equal '(nil "abc" "123") (erc--parse-nuh "abc@123")))
+  (should (equal '(nil "123" "fake") (erc--parse-nuh "!123@fake")))
+  (should (equal '(nil nil "gnu.org") (erc--parse-nuh "@gnu.org")))
+
+  ;; Host "wins" over nick and user (sans "@").
+  (should (equal '(nil nil "abc") (erc--parse-nuh "abc")))
+  (should (equal '(nil nil "gnu.org") (erc--parse-nuh "gnu.org")))
+  (should (equal '(nil nil "gnu.org") (erc--parse-nuh "!gnu.org")))
+  (should (equal '("abc" nil "123") (erc--parse-nuh "abc!123")))
+
+  ;; No fallback behavior.
+  (should-not (erc--parse-nuh "abc\nde!fg@xy")))
 
 (ert-deftest erc--parsed-prefix ()
-  (erc-mode)
-  (erc-tests--set-fake-server-process "sleep" "1")
-  (setq erc--isupport-params (make-hash-table))
+  (erc-tests-common-make-server-buf (buffer-name))
 
   ;; Uses fallback values when no PREFIX parameter yet received, thus
-  ;; ensuring caller can use slot accessors immediately intead of
+  ;; ensuring caller can use slot accessors immediately instead of
   ;; checking if null beforehand.
   (should-not erc--parsed-prefix)
   (should (equal (erc--parsed-prefix)
-                 #s(erc--parsed-prefix nil "qaohv" "~&@%+"
+                 #s(erc--parsed-prefix nil "vhoaq" "+%@&~"
                                        ((?q . ?~) (?a . ?&)
                                         (?o . ?@) (?h . ?%) (?v . ?+)))))
   (let ((cached (should erc--parsed-prefix)))
     (should (eq (erc--parsed-prefix) cached)))
 
   ;; Cache broken.  (Notice not setting `erc--parsed-prefix' to nil).
-  (setq erc-server-parameters '(("PREFIX" . "(Yqaohv)!~&@%+")))
+  (setq erc-server-parameters '(("PREFIX" . "(ov)@+")))
 
   (let ((proc erc-server-process)
-        (expected '((?Y . ?!) (?q . ?~) (?a . ?&)
-                    (?o . ?@) (?h . ?%) (?v . ?+)))
+        (expected '((?o . ?@) (?v . ?+)))
         cached)
 
     (with-temp-buffer
@@ -696,9 +709,8 @@
     (should (equal expected (erc--parsed-prefix-alist erc--parsed-prefix)))
     (setq cached erc--parsed-prefix)
     (should (equal cached
-                   #s(erc--parsed-prefix ("(Yqaohv)!~&@%+") "Yqaohv" "!~&@%+"
-                                         ((?Y . ?!) (?q . ?~) (?a . ?&)
-                                          (?o . ?@) (?h . ?%) (?v . ?+)))))
+                   #s(erc--parsed-prefix ("(ov)@+") "vo" "+@"
+                                         ((?o . ?@) (?v . ?+)))))
     ;; Second target buffer reuses cached value.
     (with-temp-buffer
       (erc-mode)
@@ -706,14 +718,96 @@
       (should (eq cached (erc--parsed-prefix))))
 
     ;; New value computed when cache broken.
-    (puthash 'PREFIX (list "(Yqaohv)!~&@%+") erc--isupport-params)
+    (puthash 'PREFIX (list "(qh)~%") erc--isupport-params)
     (with-temp-buffer
       (erc-mode)
       (setq erc-server-process proc)
       (should-not (eq cached (erc--parsed-prefix)))
       (should (equal (erc--parsed-prefix-alist
                       (erc-with-server-buffer erc--parsed-prefix))
-                     expected)))))
+                     '((?q . ?~) (?h . ?%)))))))
+
+(ert-deftest erc--get-prefix-flag ()
+  (erc-tests-common-make-server-buf (buffer-name))
+  (should-not erc--parsed-prefix)
+  (should (= (erc--get-prefix-flag ?v) 1))
+  (should (= (erc--get-prefix-flag ?h) 2))
+  (should (= (erc--get-prefix-flag ?o) 4))
+  (should (= (erc--get-prefix-flag ?a) 8))
+  (should (= (erc--get-prefix-flag ?q) 16))
+
+  (ert-info ("With optional `from-prefix-p'")
+    (should (= (erc--get-prefix-flag ?+ nil 'fpp) 1))
+    (should (= (erc--get-prefix-flag ?% nil 'fpp) 2))
+    (should (= (erc--get-prefix-flag ?@ nil 'fpp) 4))
+    (should (= (erc--get-prefix-flag ?& nil 'fpp) 8))
+    (should (= (erc--get-prefix-flag ?~ nil 'fpp) 16)))
+  (should erc--parsed-prefix))
+
+(ert-deftest erc--init-cusr-fallback-status ()
+  ;; Fallback behavior active because no `erc--parsed-prefix'.
+  (should-not erc--parsed-prefix)
+  (should (= 0 (erc--init-cusr-fallback-status nil nil nil nil nil)))
+  (should (= 1 (erc--init-cusr-fallback-status t nil nil nil nil)))
+  (should (= 4 (erc--init-cusr-fallback-status nil nil t nil nil)))
+  (should-not erc--parsed-prefix) ; not created in non-ERC buffer.
+
+  ;; Uses advertised server parameter.
+  (erc-tests-common-make-server-buf (buffer-name))
+  (setq erc-server-parameters '(("PREFIX" . "(YqaohvV)!~&@%+-")))
+  (should (= 0 (erc--init-cusr-fallback-status nil nil nil nil nil)))
+  (should (= 2 (erc--init-cusr-fallback-status t nil nil nil nil)))
+  (should (= 8 (erc--init-cusr-fallback-status nil nil t nil nil)))
+  (should erc--parsed-prefix))
+
+(ert-deftest erc--compute-cusr-fallback-status ()
+  ;; Useless without an `erc--parsed-prefix'.
+  (should (= 0 (erc--compute-cusr-fallback-status 0 nil nil nil nil nil)))
+  (should (= 0 (erc--compute-cusr-fallback-status 0 'on 'on 'on 'on 'on)))
+
+  (erc-tests-common-make-server-buf (buffer-name))
+  (should (= 0 (erc--compute-cusr-fallback-status 0 nil nil nil nil nil)))
+  (should (= 1 (erc--compute-cusr-fallback-status 0 'on nil nil nil nil)))
+  (should (= 1 (erc--compute-cusr-fallback-status 0 'on 'off 'off 'off 'off)))
+  (should (= 1 (erc--compute-cusr-fallback-status 1 'on 'off 'off 'off 'off)))
+  (should (= 1 (erc--compute-cusr-fallback-status 1 nil nil nil nil nil)))
+  (should (= 1 (erc--compute-cusr-fallback-status 3 nil 'off nil nil nil)))
+  (should (= 1 (erc--compute-cusr-fallback-status 7 nil 'off 'off nil nil)))
+  (should (= 4 (erc--compute-cusr-fallback-status 1 'off nil 'on nil nil))))
+
+(ert-deftest erc--cusr-status-p ()
+  (erc-tests-common-make-server-buf (buffer-name))
+  (should-not erc--parsed-prefix)
+  (let ((cusr (make-erc-channel-user :voice t :op t)))
+    (should-not (erc--cusr-status-p cusr ?q))
+    (should-not (erc--cusr-status-p cusr ?a))
+    (should-not (erc--cusr-status-p cusr ?h))
+    (should (erc--cusr-status-p cusr ?o))
+    (should (erc--cusr-status-p cusr ?v)))
+  (should erc--parsed-prefix))
+
+(ert-deftest erc--cusr-change-status ()
+  (erc-tests-common-make-server-buf (buffer-name))
+  (let ((cusr (make-erc-channel-user)))
+    (should-not (erc--cusr-status-p cusr ?o))
+    (should-not (erc--cusr-status-p cusr ?v))
+    (erc--cusr-change-status cusr ?o t)
+    (erc--cusr-change-status cusr ?v t)
+    (should (erc--cusr-status-p cusr ?o))
+    (should (erc--cusr-status-p cusr ?v))
+
+    (ert-info ("Reset with optional param")
+      (erc--cusr-change-status cusr ?q t 'reset)
+      (should-not (erc--cusr-status-p cusr ?o))
+      (should-not (erc--cusr-status-p cusr ?v))
+      (should (erc--cusr-status-p cusr ?q)))
+
+    (ert-info ("Clear with optional param")
+      (erc--cusr-change-status cusr ?v t)
+      (should (erc--cusr-status-p cusr ?v))
+      (erc--cusr-change-status cusr ?q nil 'reset)
+      (should-not (erc--cusr-status-p cusr ?v))
+      (should-not (erc--cusr-status-p cusr ?q)))))
 
 ;; This exists as a reference to assert legacy behavior in order to
 ;; preserve and incorporate it as a fallback in the 5.6+ replacement.
@@ -738,12 +832,9 @@
       (should (equal (erc-parse-modes "-l") '(nil nil (("l" off nil))))))))
 
 (ert-deftest erc--update-channel-modes ()
-  (erc-mode)
+  (erc-tests-common-make-server-buf)
   (setq erc-channel-users (make-hash-table :test #'equal)
-        erc-server-users (make-hash-table :test #'equal)
-        erc--isupport-params (make-hash-table)
         erc--target (erc--target-from-string "#test"))
-  (erc-tests--set-fake-server-process "sleep" "1")
 
   (let ((orig-handle-fn (symbol-function 'erc--handle-channel-mode))
         calls)
@@ -757,7 +848,9 @@
 
       (ert-info ("Status updated when user known")
         (puthash "bob" (cons (erc-add-server-user
-                              "bob" (make-erc-server-user :nickname "bob"))
+                              "bob" (make-erc-server-user
+                                     :nickname "bob"
+                                     :buffers (list (current-buffer))))
                              (make-erc-channel-user))
                  erc-channel-users)
         ;; Also asserts fallback behavior for traditional prefixes.
@@ -833,7 +926,7 @@
         erc-server-parameters
         '(("CHANMODES" . "eIbq,k,flj,CFLMPQRSTcgimnprstuz")))
 
-  (erc-tests--set-fake-server-process "sleep" "1")
+  (erc-tests-common-init-server-proc "sleep" "1")
 
   (cl-letf (((symbol-function 'erc-update-mode-line) #'ignore))
     (erc--update-channel-modes "+bltk" "fool!*@*" "3" "h2"))
@@ -848,7 +941,7 @@
   ;; truncation ellipsis when run interactively.  Rather than have
   ;; hard-to-read "nondeterministic" comparisons against sets of
   ;; acceptable values, we use separate tests.
-  (when (display-graphic-p) (ert-pass))
+  (when (char-displayable-p ?…) (ert-pass))
 
   ;; Truncation cache populated and used.
   (let ((cache (erc--channel-mode-types-shortargs erc--channel-mode-types))
@@ -874,10 +967,11 @@
   (should (equal (erc--channel-modes 0) "klt  "))) ; 2 spaces
 
 (ert-deftest erc--channel-modes/graphic-p ()
-  :tags '(:unstable)
-  (unless (display-graphic-p) (ert-skip "See non-/graphic-p variant"))
+  :tags `(:unstable ,@(and (getenv "ERC_TESTS_GRAPHICAL")
+                           '(:erc--graphical)))
+  (unless (char-displayable-p ?…) (ert-skip "See non-/graphic-p variant"))
 
-  (erc-tests--set-fake-server-process "sleep" "1")
+  (erc-tests-common-init-server-proc "sleep" "1")
   (setq erc--isupport-params (make-hash-table)
         erc--target (erc--target-from-string "#test")
         erc-server-parameters
@@ -967,6 +1061,7 @@
   (should (equal (erc--parse-isupport-value "\\x20\\x20\\x20") '("   ")))
   (should (equal (erc--parse-isupport-value "\\x5Co/") '("\\o/")))
   (should (equal (erc--parse-isupport-value "\\x7F,\\x19") '("\\x7F" "\\x19")))
+  (should (equal (erc--parse-isupport-value "a\\x3Db") '("a=b")))
   (should (equal (erc--parse-isupport-value "a\\x2Cb,c") '("a,b" "c"))))
 
 (ert-deftest erc--get-isupport-entry ()
@@ -1107,12 +1202,16 @@
       (should (erc--valid-local-channel-p "&local")))))
 
 (ert-deftest erc--restore-initialize-priors ()
+  (unless (>= emacs-major-version 28)
+    (ert-skip "Lisp nesting exceeds `max-lisp-eval-depth'"))
   (should (pcase (macroexpand-1 '(erc--restore-initialize-priors erc-my-mode
                                    foo (ignore 1 2 3)
                                    bar #'spam
                                    baz nil))
             (`(let* ((,p (or erc--server-reconnecting erc--target-priors))
                      (,q (and ,p (alist-get 'erc-my-mode ,p))))
+                (unless (local-variable-if-set-p 'erc-my-mode)
+                  (error "Not a local minor mode var: %s" 'erc-my-mode))
                 (setq foo (if ,q (alist-get 'foo ,p) (ignore 1 2 3))
                       bar (if ,q (alist-get 'bar ,p) #'spam)
                       baz (if ,q (alist-get 'baz ,p) nil)))
@@ -1187,7 +1286,7 @@
 (ert-deftest erc-ring-previous-command ()
   (with-current-buffer (get-buffer-create "*#fake*")
     (erc-mode)
-    (erc-tests--send-prep)
+    (erc-tests-common-prep-for-insertion)
     (setq erc-server-current-nick "tester")
     (setq-local erc-last-input-time 0)
     (should-not (local-variable-if-set-p 'erc-send-completed-hook))
@@ -1296,6 +1395,14 @@
     (should-not erc-debug-irc-protocol)))
 
 (ert-deftest erc--split-line ()
+  (let ((erc-split-line-length 0))
+    (should (equal (erc--split-line "") '("")))
+    (should (equal (erc--split-line " ") '(" ")))
+    (should (equal (erc--split-line "1") '("1")))
+    (should (equal (erc--split-line " 1") '(" 1")))
+    (should (equal (erc--split-line "1 ") '("1 ")))
+    (should (equal (erc--split-line "abc") '("abc"))))
+
   (let ((erc-default-recipients '("#chan"))
         (erc-split-line-length 10))
     (should (equal (erc--split-line "") '("")))
@@ -1368,29 +1475,8 @@
     (should (equal '("" "" "") (split-string "\n\n" p)))
     (should (equal '("" "" "") (split-string "\n\r" p)))))
 
-(defun erc-tests--with-process-input-spy (test)
-  (with-current-buffer (get-buffer-create "FakeNet")
-    (let* ((erc--input-review-functions
-            (remove #'erc-add-to-input-ring erc--input-review-functions))
-           (erc-pre-send-functions
-            (remove #'erc-add-to-input-ring erc-pre-send-functions)) ; for now
-           (inhibit-message noninteractive)
-           (erc-server-current-nick "tester")
-           (erc-last-input-time 0)
-           erc-accidental-paste-threshold-seconds
-           erc-send-modify-hook
-           ;;
-           calls)
-      (cl-letf (((symbol-function 'erc-process-input-line)
-                 (lambda (&rest r) (push r calls)))
-                ((symbol-function 'erc-server-buffer)
-                 (lambda () (current-buffer))))
-        (erc-tests--send-prep)
-        (funcall test (lambda () (pop calls)))))
-    (when noninteractive (kill-buffer))))
-
 (ert-deftest erc--check-prompt-input-functions ()
-  (erc-tests--with-process-input-spy
+  (erc-tests-common-with-process-input-spy
    (lambda (next)
 
      (ert-info ("Errors when point not in prompt area") ; actually just dings
@@ -1402,9 +1488,9 @@
        (ert-info ("Input remains untouched")
          (should (save-excursion (erc-bol) (looking-at "/msg #chan hi")))))
 
-     (ert-info ("Errors when no process running")
+     (ert-info ("Errors when server buffer absent")
        (let ((e (should-error (erc-send-current-line))))
-         (should (equal "ERC: No process running" (cadr e))))
+         (should (equal "Server buffer missing" (cadr e))))
        (ert-info ("Input remains untouched")
          (should (save-excursion (erc-bol) (looking-at "/msg #chan hi")))))
 
@@ -1425,9 +1511,9 @@
 ;; These also indirectly tests `erc-send-input'
 
 (ert-deftest erc-send-current-line ()
-  (erc-tests--with-process-input-spy
+  (erc-tests-common-with-process-input-spy
    (lambda (next)
-     (erc-tests--set-fake-server-process "sleep" "1")
+     (erc-tests-common-init-server-proc "sleep" "1")
      (should (= 0 erc-last-input-time))
 
      (ert-info ("Simple command")
@@ -1506,9 +1592,9 @@
   '("Stripping" "Padding"))
 
 (ert-deftest erc--check-prompt-input-for-multiline-blanks ()
-  (erc-tests--with-process-input-spy
+  (erc-tests-common-with-process-input-spy
    (lambda (next)
-     (erc-tests--set-fake-server-process "sleep" "1")
+     (erc-tests-common-init-server-proc "sleep" "10")
      (should-not erc-send-whitespace-lines)
      (should erc-warn-about-blank-lines)
 
@@ -1587,9 +1673,9 @@
                        rv ))))))
 
 (ert-deftest erc-send-whitespace-lines ()
-  (erc-tests--with-process-input-spy
+  (erc-tests-common-with-process-input-spy
    (lambda (next)
-     (erc-tests--set-fake-server-process "sleep" "1")
+     (erc-tests-common-init-server-proc "sleep" "1")
      (setq-local erc-send-whitespace-lines t)
 
      (ert-info ("Multiline hunk with blank line correctly split")
@@ -1674,17 +1760,64 @@
         (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b")))))
     (should-not erc-ask-about-multiline-input)))
 
+(ert-deftest erc-extract-command-from-line ()
+  ;; FIXME when next modifying `erc-command-regexp's default value,
+  ;; move the single quote in the first group's character alternative
+  ;; to the front, i.e., [A-Za-z'] -> ['A-Za-z], so we can assert
+  ;; equivalence with this more readable `rx' form.
+  (rx bol
+      "/"
+      (group (+ (in "'A-Za-z")))
+      (group (| (: (+ (syntax whitespace)) (* nonl))
+                (* (syntax whitespace))))
+      eol)
+  (erc-mode) ; for `erc-mode-syntax-table'
+
+  ;; Non-command.
+  (should-not (erc-extract-command-from-line "FAKE\n"))
+  ;; Unknown command.
+  (should (equal (erc-extract-command-from-line "/FAKE\n")
+                 '(erc-cmd-default "/FAKE\n")))
+
+  (ert-info ("With `do-not-parse-args'")
+    (should (equal (erc-extract-command-from-line "/MSG\n")
+                   '(erc-cmd-MSG "\n")))
+    (should (equal (erc-extract-command-from-line "/MSG \n")
+                   '(erc-cmd-MSG " \n")))
+    (should (equal (erc-extract-command-from-line "/MSG \n\n")
+                   '(erc-cmd-MSG " \n\n")))
+    (should (equal (erc-extract-command-from-line "/MSG foo\n")
+                   '(erc-cmd-MSG " foo")))
+    (should (equal (erc-extract-command-from-line "/MSG foo\n\n")
+                   '(erc-cmd-MSG " foo")))
+    (should (equal (erc-extract-command-from-line "/MSG foo\n \n")
+                   '(erc-cmd-MSG " foo")))
+    (should (equal (erc-extract-command-from-line "/MSG    foo\n")
+                   '(erc-cmd-MSG "    foo"))))
+
+  (ert-info ("Without `do-not-parse-args'")
+    (should (equal (erc-extract-command-from-line "/HELP\n")
+                   '(erc-cmd-HELP nil)))
+    (should (equal (erc-extract-command-from-line "/HELP \n")
+                   '(erc-cmd-HELP nil)))
+    (should (equal (erc-extract-command-from-line "/HELP foo\n")
+                   '(erc-cmd-HELP ("foo"))))
+    (should (equal (erc-extract-command-from-line "/HELP     foo\n")
+                   '(erc-cmd-HELP ("foo"))))
+    (should (equal (erc-extract-command-from-line "/HELP foo bar\n")
+                   '(erc-cmd-HELP ("foo" "bar"))))))
+
 ;; The point of this test is to ensure output is handled identically
 ;; regardless of whether a command handler is summoned.
 
 (ert-deftest erc-process-input-line ()
-  (let (erc-server-last-sent-time
-        erc-server-flood-queue
-        (orig-erc-cmd-MSG (symbol-function 'erc-cmd-MSG))
-        (erc-default-recipients '("#chan"))
+  (erc-tests-common-make-server-buf)
+  (let ((orig-erc-cmd-MSG (symbol-function 'erc-cmd-MSG))
+        (pop-flood-queue (lambda () (erc-with-server-buffer
+                                      (pop erc-server-flood-queue))))
         calls)
-    (with-temp-buffer
-      (erc-tests--set-fake-server-process "sleep" "1")
+    (setq erc-server-current-nick "tester")
+    (with-current-buffer (erc--open-target "#chan")
       (cl-letf (((symbol-function 'erc-cmd-MSG)
                  (lambda (line)
                    (push line calls)
@@ -1698,98 +1831,63 @@
           (ert-info ("Baseline")
             (erc-process-input-line "/msg #chan hi\n")
             (should (equal (pop calls) " #chan hi"))
-            (should (equal (pop erc-server-flood-queue)
+            (should (equal (funcall pop-flood-queue)
                            '("PRIVMSG #chan :hi\r\n" . utf-8))))
 
           (ert-info ("Quote preserves line intact")
             (erc-process-input-line "/QUOTE FAKE foo bar\n")
-            (should (equal (pop erc-server-flood-queue)
+            (should (equal (funcall pop-flood-queue)
                            '("FAKE foo bar\r\n" . utf-8))))
 
           (ert-info ("Unknown command respected")
             (erc-process-input-line "/FAKE foo bar\n")
-            (should (equal (pop erc-server-flood-queue)
+            (should (equal (funcall pop-flood-queue)
                            '("FAKE foo bar\r\n" . utf-8))))
 
           (ert-info ("Spaces preserved")
             (erc-process-input-line "/msg #chan hi you\n")
             (should (equal (pop calls) " #chan hi you"))
-            (should (equal (pop erc-server-flood-queue)
+            (should (equal (funcall pop-flood-queue)
                            '("PRIVMSG #chan :hi you\r\n" . utf-8))))
 
           (ert-info ("Empty line honored")
             (erc-process-input-line "/msg #chan\n")
             (should (equal (pop calls) " #chan"))
-            (should (equal (pop erc-server-flood-queue)
+            (should (equal (funcall pop-flood-queue)
                            '("PRIVMSG #chan :\r\n" . utf-8)))))
 
         (ert-info ("Implicit cmd via `erc-send-input-line-function'")
 
           (ert-info ("Baseline")
             (erc-process-input-line "hi\n")
-            (should (equal (pop erc-server-flood-queue)
+            (should (equal (funcall pop-flood-queue)
                            '("PRIVMSG #chan :hi\r\n" . utf-8))))
 
           (ert-info ("Spaces preserved")
             (erc-process-input-line "hi you\n")
-            (should (equal (pop erc-server-flood-queue)
+            (should (equal (funcall pop-flood-queue)
                            '("PRIVMSG #chan :hi you\r\n" . utf-8))))
 
           (ert-info ("Empty line transmitted with injected-space kludge")
             (erc-process-input-line "\n")
-            (should (equal (pop erc-server-flood-queue)
+            (should (equal (funcall pop-flood-queue)
                            '("PRIVMSG #chan : \r\n" . utf-8))))
 
-          (should-not calls))))))
+          (should-not calls)))))
+  (erc-tests-common-kill-buffers))
 
-(ert-deftest erc--get-inserted-msg-bounds ()
-  (erc-mode)
-  (erc--initialize-markers (point) nil)
-  (let ((parsed (make-erc-response :unparsed ":bob PRIVMSG #chan :hi"
-                                   :sender "bob"
-                                   :command "PRIVMSG"
-                                   :command-args (list "#chan" "hi")
-                                   :contents "hi"))
-        (erc--msg-prop-overrides '((erc-ts . 0))))
-    (erc-display-message parsed nil (current-buffer)
-                         (erc-format-privmessage "bob" "hi" nil t)))
-  (goto-char 3)
-  (should (looking-at "<bob> hi"))
-  (goto-char 11)
-  (should (looking-back "<bob> hi"))
-
-  (ert-info ("Parameter `only' being `beg'")
-    (dolist (i (number-sequence 3 11))
-      (goto-char i)
-      (ert-info ((format "At %d (%c)" i (char-after i)))
-        (should (= 3 (erc--get-inserted-msg-bounds 'beg)))))
-
-    (ert-info ("Parameter `point'")
-      (dolist (i (number-sequence 3 11))
-        (ert-info ((format "At %d (%c)" i (char-after i)))
-          (should (= 3 (erc--get-inserted-msg-bounds 'beg i)))))))
-
-  (ert-info ("Parameter `only' being `end'")
-    (dolist (i (number-sequence 3 11))
-      (goto-char i)
-      (ert-info ((format "At %d (%c)" i (char-after i)))
-        (should (= 11 (erc--get-inserted-msg-bounds 'end)))))
-
-    (ert-info ("Parameter `point'")
-      (dolist (i (number-sequence 3 11))
-        (ert-info ((format "At %d (%c)" i (char-after i)))
-          (should (= 11 (erc--get-inserted-msg-bounds 'end i)))))))
-
-  (ert-info ("Parameter `only' being nil")
-    (dolist (i (number-sequence 3 11))
-      (goto-char i)
-      (ert-info ((format "At %d (%c)" i (char-after i)))
-        (should (equal '(3 . 11) (erc--get-inserted-msg-bounds nil)))))
-
-    (ert-info ("Parameter `point'")
-      (dolist (i (number-sequence 3 11))
-        (ert-info ((format "At %d (%c)" i (char-after i)))
-          (should (equal '(3 . 11) (erc--get-inserted-msg-bounds nil i))))))))
+(ert-deftest erc--get-inserted-msg-beg/basic ()
+  (erc-tests-common-assert-get-inserted-msg/basic
+   (lambda (arg) (should (= 3 (erc--get-inserted-msg-beg arg))))))
+
+(ert-deftest erc--get-inserted-msg-end/basic ()
+  (erc-tests-common-assert-get-inserted-msg/basic
+   (lambda (arg) (should (= 11 (erc--get-inserted-msg-end arg))))))
+
+(ert-deftest erc--get-inserted-msg-bounds/basic ()
+  (erc-tests-common-assert-get-inserted-msg/basic
+   (lambda (arg)
+     (should (equal '(3 . 11) (erc--get-inserted-msg-bounds arg))))))
 
 (ert-deftest erc--delete-inserted-message ()
   (erc-mode)
@@ -1797,7 +1895,7 @@
   ;; Put unique invisible properties on the line endings.
   (erc-display-message nil 'notice nil "one")
   (put-text-property (1- erc-insert-marker) erc-insert-marker 'invisible 'a)
-  (let ((erc--msg-prop-overrides '((erc-msg . datestamp) (erc-ts . 0))))
+  (let ((erc--msg-prop-overrides '((erc--msg . datestamp) (erc--ts . 0))))
     (erc-display-message nil nil nil
                          (propertize "\n[date]" 'field 'erc-timestamp)))
   (put-text-property (1- erc-insert-marker) erc-insert-marker 'invisible 'b)
@@ -1806,7 +1904,7 @@
   (ert-info ("Date stamp deleted cleanly")
     (goto-char 11)
     (should (looking-at (rx "\n[date]")))
-    (should (eq 'datestamp (get-text-property (point) 'erc-msg)))
+    (should (eq 'datestamp (get-text-property (point) 'erc--msg)))
     (should (eq (point) (field-beginning (1+ (point)))))
 
     (erc--delete-inserted-message (point))
@@ -1867,19 +1965,21 @@
 
 (ert-deftest erc--order-text-properties-from-hash ()
   (let ((table (map-into '((a . 1)
-                           (erc-ts . 0)
-                           (erc-msg . s005)
+                           (erc--ts . 0)
+                           (erc--msg . s005)
                            (b . 2)
-                           (erc-cmd . 5)
+                           (erc--cmd . 5)
+                           (erc--spkr . "X")
                            (c . 3))
                          'hash-table)))
     (with-temp-buffer
       (erc-mode)
       (insert "abc\n")
       (add-text-properties 1 2 (erc--order-text-properties-from-hash table))
-      (should (equal '( erc-msg s005
-                        erc-ts 0
-                        erc-cmd 5
+      (should (equal '( erc--msg s005
+                        erc--spkr "X"
+                        erc--ts 0
+                        erc--cmd 5
                         a 1
                         b 2
                         c 3)
@@ -1903,21 +2003,15 @@
     (let ((v '(42 y)))
       (should-not (erc--check-msg-prop 'b v)))))
 
-(defmacro erc-tests--equal-including-properties (a b)
-  (list (if (< emacs-major-version 29)
-            'ert-equal-including-properties
-          'equal-including-properties)
-        a b))
-
 (ert-deftest erc--merge-prop ()
   (with-current-buffer (get-buffer-create "*erc-test*")
     ;; Baseline.
     (insert "abc\n")
     (erc--merge-prop 1 3 'erc-test 'x)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("abc" 0 2 (erc-test x))))
     (erc--merge-prop 1 3 'erc-test 'y)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("abc" 0 2 (erc-test (y x)))))
 
     ;; Multiple intervals.
@@ -1925,11 +2019,11 @@
     (insert "def\n")
     (erc--merge-prop 1 2 'erc-test 'x)
     (erc--merge-prop 2 3 'erc-test 'y)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4)
              #("def" 0 1 (erc-test x) 1 2 (erc-test y))))
     (erc--merge-prop 1 3 'erc-test 'z)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4)
              #("def" 0 1 (erc-test (z x)) 1 2 (erc-test (z y)))))
 
@@ -1937,10 +2031,10 @@
     (goto-char (point-min))
     (insert "ghi\n")
     (erc--merge-prop 2 3 'erc-test '(y z))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("ghi" 1 2 (erc-test (y z)))))
     (erc--merge-prop 1 3 'erc-test '(w x))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4)
              #("ghi" 0 1 (erc-test (w x)) 1 2 (erc-test (w x y z)))))
 
@@ -1948,11 +2042,11 @@
     (goto-char (point-min))
     (insert "jkl\n")
     (erc--merge-prop 2 3 'erc-test '(y z))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("jkl" 1 2 (erc-test (y z)))))
     (let ((erc--merge-prop-behind-p t))
       (erc--merge-prop 1 3 'erc-test '(w x)))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4)
              #("jkl" 0 1 (erc-test (w x)) 1 2 (erc-test (y z w x)))))
 
@@ -1966,22 +2060,22 @@
     (put-text-property 1 2 'erc-test 'a)
     (put-text-property 2 3 'erc-test 'b)
     (put-text-property 3 4 'erc-test 'c)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("abc"
                                       0 1 (erc-test a)
                                       1 2 (erc-test b)
                                       2 3 (erc-test c))))
 
     (erc--remove-from-prop-value-list 1 4 'erc-test 'b)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("abc"
                                       0 1 (erc-test a)
                                       2 3 (erc-test c))))
     (erc--remove-from-prop-value-list 1 4 'erc-test 'a)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("abc" 2 3 (erc-test c))))
     (erc--remove-from-prop-value-list 1 4 'erc-test 'c)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) "abc"))
 
     ;; List match.
@@ -1990,20 +2084,20 @@
     (put-text-property 1 2 'erc-test '(d x))
     (put-text-property 2 3 'erc-test '(e y))
     (put-text-property 3 4 'erc-test '(f z))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("def"
                                       0 1 (erc-test (d x))
                                       1 2 (erc-test (e y))
                                       2 3 (erc-test (f z)))))
     (erc--remove-from-prop-value-list 1 4 'erc-test 'y)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("def"
                                       0 1 (erc-test (d x))
                                       1 2 (erc-test e)
                                       2 3 (erc-test (f z)))))
     (erc--remove-from-prop-value-list 1 4 'erc-test 'd)
     (erc--remove-from-prop-value-list 1 4 'erc-test 'f)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("def"
                                       0 1 (erc-test x)
                                       1 2 (erc-test e)
@@ -2011,7 +2105,7 @@
     (erc--remove-from-prop-value-list 1 4 'erc-test 'e)
     (erc--remove-from-prop-value-list 1 4 'erc-test 'z)
     (erc--remove-from-prop-value-list 1 4 'erc-test 'x)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) "def"))
 
     ;; List match.
@@ -2020,20 +2114,20 @@
     (put-text-property 1 2 'erc-test '(g x))
     (put-text-property 2 3 'erc-test '(h x))
     (put-text-property 3 4 'erc-test '(i y))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("ghi"
                                       0 1 (erc-test (g x))
                                       1 2 (erc-test (h x))
                                       2 3 (erc-test (i y)))))
     (erc--remove-from-prop-value-list 1 4 'erc-test 'x)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("ghi"
                                       0 1 (erc-test g)
                                       1 2 (erc-test h)
                                       2 3 (erc-test (i y)))))
     (erc--remove-from-prop-value-list 1 2 'erc-test 'g) ; narrowed
     (erc--remove-from-prop-value-list 3 4 'erc-test 'i) ; narrowed
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("ghi"
                                       1 2 (erc-test h)
                                       2 3 (erc-test y))))
@@ -2045,7 +2139,7 @@
     (put-text-property 2 3 'erc-test '(k))
     (put-text-property 3 4 'erc-test '(k))
     (erc--remove-from-prop-value-list 1 4 'erc-test 'k)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("jkl" 0 1 (erc-test (j x)))))
 
     (when noninteractive
@@ -2058,20 +2152,20 @@
     (put-text-property 1 2 'erc-test 'a)
     (put-text-property 2 3 'erc-test 'b)
     (put-text-property 3 4 'erc-test 'c)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("abc"
                                       0 1 (erc-test a)
                                       1 2 (erc-test b)
                                       2 3 (erc-test c))))
 
     (erc--remove-from-prop-value-list 1 4 'erc-test '(a b))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("abc" 2 3 (erc-test c))))
     (erc--remove-from-prop-value-list 1 4 'erc-test 'a)
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("abc" 2 3 (erc-test c))))
     (erc--remove-from-prop-value-list 1 4 'erc-test '(c))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) "abc"))
 
     ;; List match.
@@ -2080,19 +2174,19 @@
     (put-text-property 1 2 'erc-test '(d x y))
     (put-text-property 2 3 'erc-test '(e y))
     (put-text-property 3 4 'erc-test '(f z))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("def"
                                       0 1 (erc-test (d x y))
                                       1 2 (erc-test (e y))
                                       2 3 (erc-test (f z)))))
     (erc--remove-from-prop-value-list 1 4 'erc-test '(d y f))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("def"
                                       0 1 (erc-test x)
                                       1 2 (erc-test e)
                                       2 3 (erc-test z))))
     (erc--remove-from-prop-value-list 1 4 'erc-test '(e z x))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) "def"))
 
     ;; Narrowed beg.
@@ -2101,13 +2195,13 @@
     (put-text-property 1 2 'erc-test '(g x))
     (put-text-property 2 3 'erc-test '(h x))
     (put-text-property 3 4 'erc-test '(i x))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("ghi"
                                       0 1 (erc-test (g x))
                                       1 2 (erc-test (h x))
                                       2 3 (erc-test (i x)))))
     (erc--remove-from-prop-value-list 1 3 'erc-test '(x g i))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("ghi"
                                       1 2 (erc-test h)
                                       2 3 (erc-test (i x)))))
@@ -2119,7 +2213,7 @@
     (put-text-property 2 3 'erc-test '(k))
     (put-text-property 3 4 'erc-test '(l y z))
     (erc--remove-from-prop-value-list 3 4 'erc-test '(k x y z))
-    (should (erc-tests--equal-including-properties
+    (should (erc-tests-common-equal-with-props
              (buffer-substring 1 4) #("jkl"
                                       0 1 (erc-test (j x))
                                       1 2 (erc-test (k))
@@ -2253,10 +2347,11 @@
               erc-pre-send-functions
               (lambda (o) (setf (erc-input-string o) "foo bar baz"
                                 (erc-input-refoldp o) t)))
-        (let ((erc-split-line-length 8))
+        (let* ((split (make-erc--input-split :string "foo" :lines '("foo")))
+               (erc--current-line-input-split split)
+               (erc-split-line-length 8))
           (should
-           (pcase (erc--run-send-hooks (make-erc--input-split
-                                        :string "foo" :lines '("foo")))
+           (pcase (erc--run-send-hooks split)
              ((cl-struct erc--input-split
                          (string "foo") (sendp 't) (insertp 't)
                          (lines '("foo bar " "baz")) (cmdp 'nil))
@@ -2270,7 +2365,8 @@
         calls
         erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
     (cl-letf (((symbol-function 'erc-display-message)
-               (lambda (_ _ _ line) (push line calls)))
+               (lambda (_ _ _ msg &rest args)
+                 (push (apply #'erc-format-message msg args) calls)))
               ((symbol-function 'erc-server-send)
                (lambda (line _) (push line calls)))
               ((symbol-function 'erc-server-buffer)
@@ -2312,7 +2408,7 @@
           (should-not erc-server-last-peers)
           (erc-message "PRIVMSG" ". hi")
           (should-not erc-server-last-peers)
-          (should (eq 'no-target (pop calls)))
+          (should (equal "No target" (pop calls)))
           (erc-message "PRIVMSG" ", hi")
           (should-not erc-server-last-peers)
           (should (string-match "alice :hi" (pop calls)))))
@@ -2345,46 +2441,273 @@
     (kill-buffer "ExampleNet")
     (kill-buffer "#chan")))
 
-(ert-deftest erc-format-privmessage ()
-  ;; Basic PRIVMSG
-  (should (erc-tests--equal-including-properties
-           (erc-format-privmessage (copy-sequence "bob")
-                                   (copy-sequence "oh my")
-                                   nil 'msgp)
-           #("<bob> oh my"
-             0 1 (font-lock-face erc-default-face)
-             1 4 (erc-speaker "bob" font-lock-face erc-nick-default-face)
-             4 11 (font-lock-face erc-default-face))))
-
-  ;; Basic NOTICE
-  (should (erc-tests--equal-including-properties
-           (erc-format-privmessage (copy-sequence "bob")
-                                   (copy-sequence "oh my")
-                                   nil nil)
-           #("-bob- oh my"
-             0 1 (font-lock-face erc-default-face)
-             1 4 (erc-speaker "bob" font-lock-face erc-nick-default-face)
-             4 11 (font-lock-face erc-default-face))))
-
-  ;; Prefixed PRIVMSG
-  (let* ((user (make-erc-server-user :nickname (copy-sequence "Bob")))
+(ert-deftest erc-get-channel-membership-prefix ()
+  (ert-info ("Uses default prefixes when `erc--parsed-prefix' not available")
+    (should-not (erc--parsed-prefix))
+    ;; Baseline.
+    (should-not (erc-get-channel-membership-prefix nil))
+    (should (equal (erc-get-channel-membership-prefix "Bob") ""))
+    (should (equal (erc-get-channel-membership-prefix (make-erc-channel-user))
+                   ""))
+    ;; Defaults.
+    (should
+     (erc-tests-common-equal-with-props
+      (erc-get-channel-membership-prefix (make-erc-channel-user :owner t))
+      #("~" 0 1 (help-echo "owner"))))
+    (should
+     (erc-tests-common-equal-with-props
+      (erc-get-channel-membership-prefix (make-erc-channel-user :admin t))
+      #("&" 0 1 (help-echo "admin"))))
+    (should
+     (erc-tests-common-equal-with-props
+      (erc-get-channel-membership-prefix (make-erc-channel-user :op t))
+      #("@" 0 1 (help-echo "operator"))))
+    (should
+     (erc-tests-common-equal-with-props
+      (erc-get-channel-membership-prefix (make-erc-channel-user :halfop t))
+      #("%" 0 1 (help-echo "half-op"))))
+    (should
+     (erc-tests-common-equal-with-props
+      (erc-get-channel-membership-prefix (make-erc-channel-user :voice t))
+      #("+" 0 1 (help-echo "voice")))))
+
+  (ert-info ("Uses advertised prefixes when `erc--parsed-prefix' is available")
+    (erc-tests-common-make-server-buf (buffer-name))
+    (push '("PREFIX" . "(ov)@+") erc-server-parameters)
+    (should (erc--parsed-prefix))
+
+    (with-current-buffer (erc--open-target "#chan")
+      (erc-update-current-channel-member "Bob" nil t nil nil 'on)
+
+      ;; Baseline.
+      (should-not (erc-get-channel-membership-prefix nil))
+      (should (string-empty-p (erc-get-channel-membership-prefix
+                               (make-erc-channel-user))))
+
+      ;; Defaults.
+      (should (string-empty-p (erc-get-channel-membership-prefix
+                               (make-erc-channel-user :owner t))))
+      (should (string-empty-p (erc-get-channel-membership-prefix
+                               (make-erc-channel-user :admin t))))
+      (should (string-empty-p (erc-get-channel-membership-prefix
+                               (make-erc-channel-user :halfop t))))
+
+      (should (erc-tests-common-equal-with-props
+               (erc-get-channel-membership-prefix "Bob")
+               #("@" 0 1 (help-echo "operator"))))
+      (should (erc-tests-common-equal-with-props
+               (erc-get-channel-membership-prefix
+                (make-erc-channel-user :voice t))
+               #("+" 0 1 (help-echo "voice"))))
+
+      (kill-buffer))))
+
+;; This is an adapter that uses formatting templates from the
+;; `-speaker' catalog to mimic `erc-format-privmessage', for testing
+;; purposes.
+(defun erc-tests--format-privmessage (nick msg privp msgp &optional inputp pfx)
+  (let ((erc-current-message-catalog erc--message-speaker-catalog))
+    (apply #'erc-format-message
+           (erc--determine-speaker-message-format-args nick msg privp msgp
+                                                       inputp nil pfx))))
+
+;; This asserts that `erc--determine-speaker-message-format-args'
+;; behaves identically to `erc-format-privmessage', the function whose
+;; role it basically replaced.
+(ert-deftest erc--determine-speaker-message-format-args ()
+  ;; Basic PRIVMSG.
+  (let ((expect #("<bob> oh my"
+                  0 1 (font-lock-face erc-default-face)
+                  1 4 (erc--speaker "bob" font-lock-face erc-nick-default-face)
+                  4 11 (font-lock-face erc-default-face)))
+        (args (list (concat "bob") (concat "oh my") nil 'msgp)))
+    (should (erc-tests-common-equal-with-props
+             (apply #'erc-format-privmessage args)
+             expect))
+    (should (erc-tests-common-equal-with-props
+             (apply #'erc-tests--format-privmessage args)
+             expect)))
+
+  ;; Basic NOTICE.
+  (let ((expect #("-bob- oh my"
+                  0 1 (font-lock-face erc-default-face)
+                  1 4 (erc--speaker "bob" font-lock-face erc-nick-default-face)
+                  4 11 (font-lock-face erc-default-face)))
+        (args (list (copy-sequence "bob") (copy-sequence "oh my") nil nil)))
+    (should (erc-tests-common-equal-with-props
+             (apply #'erc-format-privmessage args)
+             expect))
+    (should (erc-tests-common-equal-with-props
+             (apply #'erc-tests--format-privmessage args)
+             expect)))
+
+  ;; Status-prefixed PRIVMSG.
+  (let* ((expect
+          #("<@Bob> oh my"
+            0 1 (font-lock-face erc-default-face)
+            1 2 (font-lock-face erc-nick-prefix-face help-echo "operator")
+            2 5 (erc--speaker "Bob" font-lock-face erc-nick-default-face)
+            5 12 (font-lock-face erc-default-face)))
+         (user (make-erc-server-user :nickname (copy-sequence "Bob")))
          (cuser (make-erc-channel-user :op t))
          (erc-channel-users (make-hash-table :test #'equal)))
     (puthash "bob" (cons user cuser) erc-channel-users)
 
-    (should (erc-tests--equal-including-properties
-             (erc-format-privmessage (erc-format-@nick user cuser)
-                                     (copy-sequence "oh my")
-                                     nil 'msgp)
-             #("<@Bob> oh my"
+    (with-suppressed-warnings ((obsolete erc-format-@nick))
+      (should (erc-tests-common-equal-with-props
+               (erc-format-privmessage (erc-format-@nick user cuser)
+                                       (copy-sequence "oh my")
+                                       nil 'msgp)
+               expect)))
+    (let ((nick "Bob")
+          (msg "oh my"))
+      (should (erc-tests-common-equal-with-props
+               (erc-tests--format-privmessage nick msg nil 'msgp nil cuser)
+               expect)) ; overloaded on PREFIX arg
+      (should (erc-tests-common-equal-with-props
+               (erc-tests--format-privmessage nick msg nil 'msgp nil t)
+               expect))
+      ;; The new version makes a copy instead of adding properties to
+      ;; the input.
+      (should-not
+       (text-property-not-all 0 (length nick) 'font-lock-face nil nick))
+      (should-not
+       (text-property-not-all 0 (length msg) 'font-lock-face nil msg)))))
+
+(ert-deftest erc--determine-speaker-message-format-args/queries-as-channel ()
+  (should erc-format-query-as-channel-p)
+
+  (with-current-buffer (get-buffer-create "bob")
+    (erc-mode)
+    (setq erc--target (erc--target-from-string "alice"))
+
+    (insert "PRIVMSG\n"
+            (erc-tests--format-privmessage "bob" "oh my" 'queryp 'msgp))
+    (should (erc-tests-common-equal-with-props
+             #("<bob> oh my"
+               0 1 (font-lock-face erc-default-face)
+               1 4 (erc--speaker "bob" font-lock-face erc-nick-default-face)
+               4 11 (font-lock-face erc-default-face))
+             (buffer-substring (pos-bol) (pos-eol))))
+
+    (insert "\nNOTICE\n"
+            (erc-tests--format-privmessage "bob" "oh my" 'queryp nil))
+    (should (erc-tests-common-equal-with-props
+             #("-bob- oh my"
+               0 1 (font-lock-face erc-default-face)
+               1 4 (erc--speaker "bob" font-lock-face erc-nick-default-face)
+               4 11 (font-lock-face erc-default-face))
+             (buffer-substring (pos-bol) (pos-eol))))
+
+    (insert "\nInput PRIVMSG\n"
+            (erc-tests--format-privmessage "bob" "oh my"
+                                           'queryp 'privmsgp 'inputp))
+    (should (erc-tests-common-equal-with-props
+             #("<bob> oh my"
+               0 1 (font-lock-face erc-default-face)
+               1 4 (erc--speaker "bob" font-lock-face erc-my-nick-face)
+               4 6 (font-lock-face erc-default-face)
+               6 11 (font-lock-face erc-input-face))
+             (buffer-substring (pos-bol) (pos-eol))))
+
+    (insert "\nInput NOTICE\n"
+            (erc-tests--format-privmessage "bob" "oh my" 'queryp nil 'inputp))
+    (should (erc-tests-common-equal-with-props
+             #("-bob- oh my"
                0 1 (font-lock-face erc-default-face)
-               1 2 (font-lock-face erc-nick-prefix-face help-echo "operator")
-               2 5 (erc-speaker "Bob" font-lock-face erc-nick-default-face)
-               5 12 (font-lock-face erc-default-face))))))
+               1 4 (erc--speaker "bob" font-lock-face erc-my-nick-face)
+               4 6 (font-lock-face erc-default-face)
+               6 11 (font-lock-face erc-input-face))
+             (buffer-substring (pos-bol) (pos-eol))))
+
+    (when noninteractive (kill-buffer))))
+
+(ert-deftest erc--determine-speaker-message-format-args/queries ()
+  (should erc-format-query-as-channel-p)
+
+  (with-current-buffer (get-buffer-create "bob")
+    (erc-mode)
+    (setq-local erc-format-query-as-channel-p nil)
+    (setq erc--target (erc--target-from-string "alice"))
+
+    (insert "PRIVMSG\n"
+            (erc-tests--format-privmessage "bob" "oh my" 'queryp 'msgp))
+    (should (erc-tests-common-equal-with-props
+             #("*bob* oh my"
+               0 1 (font-lock-face erc-direct-msg-face)
+               1 4 (erc--speaker "bob" font-lock-face erc-nick-msg-face)
+               4 11 (font-lock-face erc-direct-msg-face))
+             (buffer-substring (pos-bol) (pos-eol))))
+
+    (insert "\nNOTICE\n"
+            (erc-tests--format-privmessage "bob" "oh my" 'queryp nil))
+    (should (erc-tests-common-equal-with-props
+             #("-bob- oh my"
+               0 1 (font-lock-face erc-direct-msg-face)
+               1 4 (erc--speaker "bob" font-lock-face erc-nick-msg-face)
+               4 11 (font-lock-face erc-direct-msg-face))
+             (buffer-substring (pos-bol) (pos-eol))))
+
+    (insert "\nInput PRIVMSG\n"
+            (erc-tests--format-privmessage "bob" "oh my"
+                                           'queryp 'privmsgp 'inputp))
+    (should (erc-tests-common-equal-with-props
+             #("*bob* oh my"
+               0 1 (font-lock-face erc-direct-msg-face)
+               1 4 (erc--speaker "bob" font-lock-face erc-my-nick-face)
+               4 6 (font-lock-face erc-direct-msg-face)
+               6 11 (font-lock-face erc-input-face))
+             (buffer-substring (pos-bol) (pos-eol))))
+
+    (insert "\nInput NOTICE\n"
+            (erc-tests--format-privmessage "bob" "oh my" 'queryp nil 'inputp))
+    (should (erc-tests-common-equal-with-props
+             #("-bob- oh my"
+               0 1 (font-lock-face erc-direct-msg-face)
+               1 4 (erc--speaker "bob" font-lock-face erc-my-nick-face)
+               4 6 (font-lock-face erc-direct-msg-face)
+               6 11 (font-lock-face erc-input-face))
+             (buffer-substring (pos-bol) (pos-eol))))
+
+    (when noninteractive (kill-buffer))))
+
+(defun erc-tests--format-my-nick (message)
+  (concat (erc-format-my-nick)
+          (propertize message 'font-lock-face 'erc-input-face)))
+
+;; This tests that the default behavior of the replacement formatting
+;; function for prompt input, `erc--format-speaker-input-message'
+;; matches that of the original being replaced, `erc-format-my-nick',
+;; though it only handled the speaker portion.
+(ert-deftest erc--format-speaker-input-message ()
+  ;; No status prefix.
+  (let ((erc-server-current-nick "tester")
+        (expect #("<tester> oh my"
+                  0 1 (font-lock-face erc-default-face)
+                  1 7 (font-lock-face erc-my-nick-face erc--speaker "tester")
+                  7 9 (font-lock-face erc-default-face)
+                  9 14 (font-lock-face erc-input-face))))
+    (should (equal (erc-tests--format-my-nick "oh my") expect))
+    (should (equal (erc--format-speaker-input-message "oh my") expect)))
+
+  ;; With channel-operator status prefix.
+  (let* ((erc-server-current-nick "tester")
+         (cmem (cons (make-erc-server-user :nickname "tester")
+                     (make-erc-channel-user :op t)))
+         (erc-channel-users (map-into (list "tester" cmem)
+                                      '(hash-table :test equal)))
+         (expect #("<@tester> oh my"
+                   0 1 (font-lock-face erc-default-face)
+                   1 2 (font-lock-face erc-my-nick-prefix-face)
+                   2 5 (font-lock-face erc-my-nick-face erc--speaker "bob")
+                   5 7 (font-lock-face erc-default-face)
+                   7 12 (font-lock-face erc-input-face))))
+    (should (equal (erc-tests--format-my-nick "oh my") expect))
+    (should (equal (erc--format-speaker-input-message "oh my") expect))))
 
 (ert-deftest erc--route-insertion ()
-  (erc-tests--send-prep)
-  (erc-tests--set-fake-server-process "sleep" "1")
+  (erc-tests-common-prep-for-insertion)
+  (erc-tests-common-init-server-proc "sleep" "1")
   (setq erc-networks--id (erc-networks--id-create 'foonet))
 
   (let* ((erc-modules) ; for `erc--open-target'
@@ -2404,7 +2727,7 @@
 
         (ert-info ("Cons `buffer' routes to live members")
           ;; Copies a let-bound `erc--msg-props' before mutating.
-          (let* ((table (map-into '(erc-msg msg) 'hash-table))
+          (let* ((table (map-into '(erc--msg msg) 'hash-table))
                  (erc--msg-props table))
             (erc--route-insertion "cons" (list server-buffer spam-buffer))
             (should-not (eq table erc--msg-props)))
@@ -2481,7 +2804,7 @@
                    (list :server "irc.libera.chat"
                          :port 6697
                          :nick (user-login-name)
-                         '&interactive-env
+                         '--interactive-env--
                          '((erc-server-connect-function . erc-open-tls-stream)
                            (erc-join-buffer . window))))))
 
@@ -2491,7 +2814,7 @@
                    (list :server "irc.gnu.org"
                          :port 6697
                          :nick (user-login-name)
-                         '&interactive-env
+                         '--interactive-env--
                          '((erc-server-connect-function . erc-open-tls-stream)
                            (erc-join-buffer . window))))))
 
@@ -2502,7 +2825,7 @@
                      (list :server "irc.gnu.org"
                            :port 6697
                            :nick (user-login-name)
-                           '&interactive-env
+                           '--interactive-env--
                            '((erc-server-connect-function
                               . erc-open-tls-stream)
                              (erc--display-context
@@ -2770,30 +3093,6 @@
                          (erc-server-connect-function
                           erc-open-network-stream))))))))
 
-(defun erc-tests--make-server-buf (name)
-  (with-current-buffer (get-buffer-create name)
-    (erc-mode)
-    (setq erc-server-process (start-process "sleep" (current-buffer)
-                                            "sleep" "1")
-          erc-session-server (concat "irc." name ".org")
-          erc-session-port 6667
-          erc-network (intern name))
-    (set-process-query-on-exit-flag erc-server-process nil)
-    (current-buffer)))
-
-(defun erc-tests--make-client-buf (server name)
-  (unless (bufferp server)
-    (setq server (get-buffer server)))
-  (with-current-buffer (get-buffer-create name)
-    (erc-mode)
-    (setq erc--target (erc--target-from-string name))
-    (dolist (v '(erc-server-process
-                 erc-session-server
-                 erc-session-port
-                 erc-network))
-      (set v (buffer-local-value v server)))
-    (current-buffer)))
-
 (ert-deftest erc-handle-irc-url ()
   (let* (calls
          rvbuf
@@ -2807,10 +3106,10 @@
     (cl-letf (((symbol-function 'erc-cmd-JOIN)
                (lambda (&rest r) (push r calls))))
 
-      (with-current-buffer (erc-tests--make-server-buf "foonet")
+      (with-current-buffer (erc-tests-common-make-server-buf "foonet")
         (setq rvbuf (current-buffer)))
-      (erc-tests--make-server-buf "barnet")
-      (erc-tests--make-server-buf "baznet")
+      (erc-tests-common-make-server-buf "barnet")
+      (erc-tests-common-make-server-buf "baznet")
 
       (ert-info ("Unknown network")
         (erc-handle-irc-url "irc.foonet.org" 6667 "#chan" nil nil "irc")
@@ -2834,7 +3133,8 @@
         (should-not calls))
 
       (ert-info ("Known network, existing chan with key")
-        (erc-tests--make-client-buf "foonet" "#chan")
+        (save-excursion
+          (with-current-buffer "foonet" (erc--open-target "#chan")))
         (erc-handle-irc-url "irc.foonet.org" nil "#chan?sec" nil nil "irc")
         (should (equal '("#chan" "sec") (pop calls)))
         (should-not calls))
@@ -2847,7 +3147,7 @@
       (ert-info ("Unknown network, connect, chan")
         (with-current-buffer "foonet"
           (should-not (local-variable-p 'erc-after-connect)))
-        (setq rvbuf (lambda () (erc-tests--make-server-buf "gnu")))
+        (setq rvbuf (lambda () (erc-tests-common-make-server-buf "gnu")))
         (erc-handle-irc-url "irc.gnu.org" nil "#spam" nil nil "irc")
         (should (equal '("irc" :server "irc.gnu.org") (pop calls)))
         (should-not calls)
@@ -2859,10 +3159,58 @@
         (should-not calls))))
 
   (when noninteractive
-    (kill-buffer "foonet")
-    (kill-buffer "barnet")
-    (kill-buffer "baznet")
-    (kill-buffer "#chan")))
+    (erc-tests-common-kill-buffers)))
+
+(ert-deftest erc-channel-user ()
+  ;; Traditional and alternate constructor swapped for compatibility.
+  (should (= 0 (erc-channel-user-status (erc-channel-user--make))))
+  (should-not (erc-channel-user-last-message-time (erc-channel-user--make)))
+
+  (should (= 42 (erc-channel-user-last-message-time
+                 (make-erc-channel-user :last-message-time 42))))
+
+  (should (zerop (erc-channel-user-status (make-erc-channel-user))))
+
+  (let ((u (make-erc-channel-user)))
+
+    (ert-info ("Add voice status to user")
+      (should (= 0 (erc-channel-user-status u)))
+      (should-not (erc-channel-user-voice u))
+      (should (eq t (setf (erc-channel-user-voice u) t)))
+      (should (eq t (erc-channel-user-voice u))))
+
+    (ert-info ("Add op status to user")
+      (should (= 1 (erc-channel-user-status u)))
+      (should-not (erc-channel-user-op u))
+      (should (eq t (setf (erc-channel-user-op u) t)))
+      (should (eq t (erc-channel-user-op u))))
+
+    (ert-info ("Add owner status to user")
+      (should (= 5 (erc-channel-user-status u)))
+      (should-not (erc-channel-user-owner u))
+      (should (eq t (setf (erc-channel-user-owner u) t)))
+      (should (eq t (erc-channel-user-owner u))))
+
+    (ert-info ("Remove owner status from user")
+      (should (= 21 (erc-channel-user-status u)))
+      (should-not (setf (erc-channel-user-owner u) nil))
+      (should-not (erc-channel-user-owner u)))
+
+    (ert-info ("Remove op status from user")
+      (should (= 5 (erc-channel-user-status u)))
+      (should-not (setf (erc-channel-user-op u) nil))
+      (should-not (erc-channel-user-op u)))
+
+    (ert-info ("Remove voice status from user")
+      (should (= 1 (erc-channel-user-status u)))
+      (should-not (setf (erc-channel-user-voice u) nil))
+      (should-not (erc-channel-user-voice u)))
+
+    (ert-info ("Remove voice status from zeroed user")
+      (should (= 0 (erc-channel-user-status u)))
+      (should-not (setf (erc-channel-user-voice u) nil))
+      (should-not (erc-channel-user-voice u))
+      (should (= 0 (erc-channel-user-status u))))))
 
 (defconst erc-tests--modules
   '( autoaway autojoin bufbar button capab-identify
@@ -2902,35 +3250,11 @@
   (should (eq (erc--normalize-module-symbol 'nickserv) 'services)))
 
 (defun erc-tests--assert-printed-in-subprocess (code expected)
-  (let* ((package (if-let* ((found (getenv "ERC_PACKAGE_NAME"))
-                            ((string-prefix-p "erc-" found)))
-                      (intern found)
-                    'erc))
-         ;; This is for integrations testing with managed configs
-         ;; ("starter kits") that use a different package manager.
-         (init (and-let* ((found (getenv "ERC_TESTS_INIT"))
-                          (files (split-string found ",")))
-                 (mapcan (lambda (f) (list "-l" f)) files)))
-         (prog
-          `(progn
-             ,@(and (not init) (featurep 'compat)
-                    `((require 'package)
-                      (let ((package-load-list '((compat t) (,package t))))
-                        (package-initialize))))
-             (require 'erc)
-             (cl-assert (equal erc-version ,erc-version) t)
-             ,code))
-         (proc (apply #'start-process
-                      (symbol-name (ert-test-name (ert-running-test)))
-                      (current-buffer)
-                      (concat invocation-directory invocation-name)
-                      `("-batch" ,@(or init '("-Q"))
-                        "-eval" ,(format "%S" prog)))))
-    (set-process-query-on-exit-flag proc t)
+  (let ((proc (erc-tests-common-create-subprocess code '("-batch") nil)))
     (while (accept-process-output proc 10))
     (goto-char (point-min))
     (unless (equal (read (current-buffer)) expected)
-      (message "Exepcted: %S\nGot: %s" expected (buffer-string))
+      (message "Expected: %S\nGot: %s" expected (buffer-string))
       (ert-fail "Mismatch"))))
 
 ;; Worrying about which library a module comes from is mostly not
@@ -3007,6 +3331,7 @@
   (should (eq (erc--find-group 'autojoin) 'erc-autojoin))
   (should (eq (erc--find-group 'pcomplete 'Completion) 'erc-pcomplete))
   (should (eq (erc--find-group 'capab-identify) 'erc-capab))
+  (should (eq (erc--find-group 'completion) 'erc-pcomplete))
   ;; No group specified.
   (should (eq (erc--find-group 'smiley nil) 'erc))
   (should (eq (erc--find-group 'unmorse nil) 'erc)))
@@ -3274,4 +3599,100 @@ connection."
                       (put 'erc-mname-enable 'definition-name 'mname)
                       (put 'erc-mname-disable 'definition-name 'mname))))))
 
+(ert-deftest erc-tests-common-string-to-propertized-parts ()
+  :tags '(:unstable) ; only run this locally
+  (unless (>= emacs-major-version 28) (ert-skip "Missing `object-intervals'"))
+
+  (should (equal (erc-tests-common-string-to-propertized-parts
+                  #("abc"
+                    0 1 (face default foo 1)
+                    1 3 (face (default italic) bar "2")))
+                 '(concat (propertize "a" 'foo 1 'face 'default)
+                          (propertize "bc" 'bar "2" 'face '(default italic)))))
+  (should (equal #("abc"
+                   0 1 (face default foo 1)
+                   1 3 (face (default italic) bar "2"))
+                 (concat (propertize "a" 'foo 1 'face 'default)
+                         (propertize "bc" 'bar "2" 'face '(default italic))))))
+
+(ert-deftest erc--make-message-variable-name ()
+  (should (erc--make-message-variable-name 'english 'QUIT 'softp))
+  (should (erc--make-message-variable-name 'english 'QUIT nil))
+
+  (let ((obarray (obarray-make)))
+    (should-not (erc--make-message-variable-name 'testcat 'testkey 'softp))
+    (should (erc--make-message-variable-name 'testcat 'testkey nil))
+    (should (intern-soft "erc-message-testcat-testkey" obarray))
+    (should-not (erc--make-message-variable-name 'testcat 'testkey 'softp))
+    (set (intern "erc-message-testcat-testkey" obarray) "hello world")
+    (should (equal (symbol-value
+                    (erc--make-message-variable-name 'testcat 'testkey nil))
+                   "hello world")))
+
+  ;; Hyphenated (internal catalog).
+  (let ((obarray (obarray-make)))
+    (should-not (erc--make-message-variable-name '-testcat 'testkey 'softp))
+    (should (erc--make-message-variable-name '-testcat 'testkey nil))
+    (should (intern-soft "erc--message-testcat-testkey" obarray))
+    (should-not (erc--make-message-variable-name '-testcat 'testkey 'softp))
+    (set (intern "erc--message-testcat-testkey" obarray) "hello world")
+    (should (equal (symbol-value
+                    (erc--make-message-variable-name '-testcat 'testkey nil))
+                   "hello world"))))
+
+(ert-deftest erc-retrieve-catalog-entry ()
+  (should (eq 'english erc-current-message-catalog))
+  (should (equal (erc-retrieve-catalog-entry 's221) "User modes for %n: %m"))
+
+  ;; Local binding.
+  (with-temp-buffer
+    (should (equal (erc-retrieve-catalog-entry 's221) "User modes for %n: %m"))
+    (setq erc-current-message-catalog 'test)
+    ;; No catalog named `test'.
+    (should (equal (erc-retrieve-catalog-entry 's221) "User modes for %n: %m"))
+
+    (let ((obarray (obarray-make)))
+      (set (intern "erc-message-test-s221") "test 221 val")
+      (should (equal (erc-retrieve-catalog-entry 's221) "test 221 val"))
+      (set (intern "erc-message-english-s221") "eng 221 val")
+
+      (let ((erc-current-message-catalog 'english))
+        (should (equal (erc-retrieve-catalog-entry 's221) "eng 221 val")))
+
+      (with-temp-buffer
+        (should (equal (erc-retrieve-catalog-entry 's221) "eng 221 val"))
+        (let ((erc-current-message-catalog 'test))
+          (should (equal (erc-retrieve-catalog-entry 's221) "test 221 val"))))
+
+      (should (equal (erc-retrieve-catalog-entry 's221) "test 221 val")))
+
+    (should (equal (erc-retrieve-catalog-entry 's221) "User modes for %n: %m"))
+    (should (equal erc-current-message-catalog 'test)))
+
+  ;; Default top-level value.
+  (set-default-toplevel-value 'erc-current-message-catalog 'test-top)
+  (should (equal (erc-retrieve-catalog-entry 's221) "User modes for %n: %m"))
+  (set (intern "erc-message-test-top-s221") "test-top 221 val")
+  (should (equal (erc-retrieve-catalog-entry 's221) "test-top 221 val"))
+
+  (setq erc-current-message-catalog 'test-local)
+  (should (equal (erc-retrieve-catalog-entry 's221) "test-top 221 val"))
+
+  (makunbound (intern "erc-message-test-top-s221"))
+  (unintern "erc-message-test-top-s221" obarray)
+
+  ;; Inheritance.
+  (let ((obarray (obarray-make)))
+    (set (intern "erc-message-test1-abc") "val test1 abc")
+    (set (intern "erc-message-test2-abc") "val test2 abc")
+    (set (intern "erc-message-test2-def") "val test2 def")
+    (put (intern "test0") 'erc--base-format-catalog (intern "test1"))
+    (put (intern "test1") 'erc--base-format-catalog (intern "test2"))
+    (should (equal (erc-retrieve-catalog-entry 'abc (intern "test0"))
+                   "val test1 abc"))
+    (should (equal (erc-retrieve-catalog-entry 'def (intern "test0"))
+                   "val test2 def"))
+    ;; Terminates.
+    (should-not (erc-retrieve-catalog-entry 'ghi (intern "test0")))))
+
 ;;; erc-tests.el ends here
diff --git a/test/lisp/erc/erc-track-tests.el b/test/lisp/erc/erc-track-tests.el
index ab8d708b721..3288c42a42e 100644
--- a/test/lisp/erc/erc-track-tests.el
+++ b/test/lisp/erc/erc-track-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-track-tests.el --- Tests for erc-track.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <mlang@delysid.org>
 ;; Author: Vivek Dasmohapatra <vivek@etla.org>
@@ -104,6 +104,42 @@
                                       '("#emacs" "#vi"))
             '("#e" "#v"))) ))
 
+(ert-deftest erc-track--shortened-names ()
+  (let (erc-track--shortened-names
+        erc-track--shortened-names-current-hash
+        results)
+
+    (with-memoization (erc-track--shortened-names-get
+                       '("apple" "banana" "cherries"))
+      '("a" "b" "c"))
+    (should (integerp (car erc-track--shortened-names)))
+    (should (equal (cdr erc-track--shortened-names) '("a" "b" "c")))
+    (push erc-track--shortened-names results)
+
+    ;; Redundant call doesn't run.
+    (with-memoization (erc-track--shortened-names-get
+                       '("apple" "banana" "cherries"))
+      (should-not 'run)
+      '("a" "b" "c"))
+    (should (equal erc-track--shortened-names (car results)))
+
+    ;; Change in environment or context forces run.
+    (with-temp-buffer
+      (with-memoization (erc-track--shortened-names-get
+                         '("apple" "banana" "cherries"))
+        '("x" "y" "z")))
+    (should (and (integerp (car erc-track--shortened-names))
+                 (/= (car erc-track--shortened-names) (caar results))))
+    (should (equal (cdr erc-track--shortened-names) '("x" "y" "z")))
+    (push erc-track--shortened-names results)
+
+    (with-memoization (erc-track--shortened-names-get
+                       '("apple" "banana" "cherries"))
+      '("1" "2" "3"))
+    (should (and (integerp (car erc-track--shortened-names))
+                 (/= (car erc-track--shortened-names) (caar results))))
+    (should (equal (cdr erc-track--shortened-names) '("1" "2" "3")))))
+
 (ert-deftest erc-track--erc-faces-in ()
   "`erc-faces-in' should pick up both 'face and 'font-lock-face properties."
   (let ((str0 (copy-sequence "is bold"))
@@ -120,4 +156,134 @@
     (should (erc-faces-in str0))
     (should (erc-faces-in str1)) ))
 
+;; This simulates an alternating bold/non-bold [#c] in the mode-line,
+;; i.e., an `erc-modified-channels-alist' that vacillates between
+;;
+;;   ((#<buffer #chan> 42 . erc-default-face))
+;;
+;; and
+;;
+;;   ((#<buffer #chan> 42 erc-nick-default-face erc-default-face))
+;;
+;; This is a fairly typical scenario where consecutive messages
+;; feature speaker and addressee button highlighting and otherwise
+;; plain message bodies.  This mapping of phony to real faces
+;; describes the picture in 5.6:
+;;
+;;   `1': (erc-button erc-default-face)                 ; URL
+;;   `2': (erc-nick-default-face erc-default-face)      ; mention
+;;   `3': erc-default-face                              ; body
+;;   `_': (erc-nick-default-face erc-nick-default-face) ; speaker
+;;
+;; The `_' represents a commonly occurring face (a <speaker>) that's
+;; not present in either option's default (standard) value.  It's a
+;; no-op from the POV of `erc-track-select-mode-line-face'.
+
+(ert-deftest erc-track-select-mode-line-face ()
+
+  ;; Observed (see key above).
+  (let ((erc-track-faces-priority-list '(1 2 3))
+        (erc-track-faces-normal-list   '(1 2 3)))
+
+    (should (equal 2 (erc-track-select-mode-line-face 3 '(2 _ 3))))
+    (should (equal 2 (erc-track-select-mode-line-face 2 '(2 _ 3))))
+    (should (equal 3 (erc-track-select-mode-line-face 2 '(_ 3))))
+    (should (equal 2 (erc-track-select-mode-line-face 3 '(2 3))))
+    (should (equal 3 (erc-track-select-mode-line-face 2 '(3))))
+
+    (should (equal 1 (erc-track-select-mode-line-face 1 '(2 1 3))))
+    (should (equal 1 (erc-track-select-mode-line-face 1 '(1 3))))
+    (should (equal 1 (erc-track-select-mode-line-face 1 '(1 3 2))))
+    (should (equal 1 (erc-track-select-mode-line-face 1 '(3 1)))))
+
+  ;; When the current face outranks all new faces and doesn't appear
+  ;; among them, it's eligible to be replaced with a fellow "normal"
+  ;; from those new faces.  But if it does appear among them, it's
+  ;; never replaced.
+  (let ((erc-track-faces-priority-list '(a b))
+        (erc-track-faces-normal-list   '(a b)))
+
+    (should (equal 'a (erc-track-select-mode-line-face 'a '(b a))))
+    (should (equal 'a (erc-track-select-mode-line-face 'a '(a b))))
+    (should (equal 'a (erc-track-select-mode-line-face 'b '(b a))))
+    (should (equal 'a (erc-track-select-mode-line-face 'b '(a b))))
+
+    (should (equal 'a (erc-track-select-mode-line-face 'b '(a))))
+    (should (equal 'b (erc-track-select-mode-line-face 'a '(b)))))
+
+  ;; The ordering of the "normal" list doesn't matter.
+  (let ((erc-track-faces-priority-list '(a b))
+        (erc-track-faces-normal-list   '(b a)))
+
+    (should (equal 'a (erc-track-select-mode-line-face 'a '(b a))))
+    (should (equal 'a (erc-track-select-mode-line-face 'a '(a b))))
+    (should (equal 'a (erc-track-select-mode-line-face 'b '(b a))))
+    (should (equal 'a (erc-track-select-mode-line-face 'b '(a b))))))
+
+(defun erc-track-tests--select-mode-line-face (ranked normals cases)
+  (setq normals (map-into (mapcar (lambda (f) (cons f t)) normals)
+                          '(hash-table :test equal)))
+  (pcase-dolist (`(,want ,cur-face ,new-faces) cases)
+
+    (ert-info ((format "Observed: {cur: %S, new: %S, want: %S}"
+                       cur-face new-faces want))
+      (setq new-faces (cons (map-into
+                             (mapcar (lambda (f) (cons f t)) new-faces)
+                             '(hash-table :test equal))
+                            (reverse new-faces)))
+      (should (equal want (funcall #'erc-track--select-mode-line-face
+                                   cur-face new-faces ranked normals))))))
+
+;; The main difference between these variants is that with the above,
+;; when given alternating lines like
+;;
+;;  CUR      NEW                          CHOICE
+;;   text     (mention $speaker text)  =>   mention
+;;   mention  ($speaker text)          =>   text
+;;
+;; we see the effect of alternating faces in the indicator.  But when
+;; given consecutive lines with a similar composition, like
+;;
+;;   text     (mention $speaker text)  =>   mention
+;;   text     (mention $speaker text)  =>   mention
+;;
+;; we lose the effect.  With the variant below, we get
+;;
+;;   text     (mention $speaker text)  =>   mention
+;;   text     (mention $speaker text)  =>   text
+;;
+
+(ert-deftest erc-track--select-mode-line-face ()
+  (should-not erc-track-ignore-normal-contenders-p)
+
+  ;; These are the same test cases from the previous test.  The syntax
+  ;; is (expected cur-face new-faces).
+  (erc-track-tests--select-mode-line-face
+   '(1 2 3) '(1 2 3)
+   '((2 3 (2 _ 3))
+     (3 2 (2 _ 3))
+     (3 2 (_ 3))
+     (2 3 (2 3))
+     (3 2 (3))
+     (2 1 (2 1 3))
+     (3 1 (1 3))
+     (2 1 (1 3 2))
+     (3 1 (3 1))))
+
+  (erc-track-tests--select-mode-line-face
+   '(a b) '(a b)
+   '((b a (b a))
+     (b a (a b))
+     (a b (b a))
+     (a b (a b))
+     (a b (a))
+     (b a (b))))
+
+  (erc-track-tests--select-mode-line-face
+   '(a b) '(b a)
+   '((b a (b a))
+     (b a (a b))
+     (a b (b a))
+     (a b (a b)))))
+
 ;;; erc-track-tests.el ends here
diff --git a/test/lisp/erc/resources/base/display-message/statusmsg.eld 
b/test/lisp/erc/resources/base/display-message/statusmsg.eld
new file mode 100644
index 00000000000..7c42117080c
--- /dev/null
+++ b/test/lisp/erc/resources/base/display-message/statusmsg.eld
@@ -0,0 +1,47 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER tester 0 * :tester")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.02 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running 
version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Thu, 07 Dec 2023 
08:04:35 UTC")
+ (0.00 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios 
CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii 
CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# 
CHATHISTORY=1000 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by 
this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 
MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ 
TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100
 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=1000 :are supported by 
this server")
+ (0.00 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 
server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0.02 ":irc.foonet.org 265 tester 4 5 :Current local users 4, max 5")
+ (0.00 ":irc.foonet.org 266 tester 4 5 :Current global users 4, max 5")
+ (0.00 ":irc.foonet.org 422 tester :MOTD File is missing")
+ (0.00 ":irc.foonet.org 221 tester +i")
+ (0.00 ":irc.foonet.org NOTICE tester :This server is in debug mode and is 
logging all user I/O. If you do not wish for everything you send to be readable 
by the server owner(s), please disconnect."))
+
+((mode-tester 10 "MODE tester +i"))
+
+((join-mine 10 "JOIN #mine")
+ (0.01 ":irc.foonet.org 221 tester +i")
+ (0.00 ":tester!~u@2jv6nwu4af69s.irc JOIN #mine")
+ (0.02 ":irc.foonet.org 353 tester = #mine :@tester +dummy")
+ (0.01 ":irc.foonet.org 366 tester #mine :End of NAMES list"))
+
+((mode-mine 10 "MODE #mine")
+ (0.00 ":irc.foonet.org 324 tester #mine +Cnt")
+ (0.02 ":irc.foonet.org 329 tester #mine 1702026418")
+ (0.04 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :hello")
+ (0.03 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :there")
+ (0.05 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :\1ACTION sad\1")
+ (0.03 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :\1ACTION glad\1"))
+
+((privmsg-statusmsg 10 "PRIVMSG +#mine :howdy"))
+((privmsg-statusmsg-action 10 "PRIVMSG +#mine :tenderfoot")
+ ;; These are simulated "echoed messages"
+ (0.05 ":tester!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :\1ACTION mad\1")
+ (0.05 ":tester!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :\1ACTION chad\1"))
+
+((privmsg-prefixed 10 "PRIVMSG #mine :\1ACTION ready\1")
+ (0.04 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :okie")
+ (0.05 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :\1ACTION dokie\1")
+ (0.04 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG #mine :\1ACTION out\1"))
diff --git a/test/lisp/erc/resources/base/local-modules/first.eld 
b/test/lisp/erc/resources/base/local-modules/first.eld
index f9181a80fb7..4e923270e24 100644
--- a/test/lisp/erc/resources/base/local-modules/first.eld
+++ b/test/lisp/erc/resources/base/local-modules/first.eld
@@ -1,7 +1,7 @@
 ;; -*- mode: lisp-data; -*-
 ((cap 10 "CAP REQ :sasl"))
-((nick 1 "NICK tester"))
-((user 1 "USER tester 0 * :tester"))
+((nick 10 "NICK tester"))
+((user 10 "USER tester 0 * :tester"))
 
 ((authenticate 5 "AUTHENTICATE PLAIN")
  (0.0 ":irc.foonet.org CAP * ACK sasl")
@@ -11,7 +11,7 @@
  (0.0 ":irc.foonet.org 900 * * tester :You are now logged in as tester")
  (0.01 ":irc.foonet.org 903 * :Authentication successful"))
 
-((cap 3.2 "CAP END")
+((cap 10 "CAP END")
  (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
  (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running 
version ergo-v2.8.0")
  (0.2 ":irc.foonet.org 003 tester :This server was created Sun, 20 Nov 2022 
23:10:36 UTC")
diff --git a/test/lisp/erc/resources/base/modes/speaker-status.eld 
b/test/lisp/erc/resources/base/modes/speaker-status.eld
new file mode 100644
index 00000000000..4a7d508e35c
--- /dev/null
+++ b/test/lisp/erc/resources/base/modes/speaker-status.eld
@@ -0,0 +1,69 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER tester 0 * :unknown")
+ (0.00 ":irc.example.net NOTICE * :*** Looking up your hostname...")
+ (0.00 ":irc.example.net NOTICE tester :*** Could not resolve your hostname: 
Domain not found; using your IP address (10.0.2.100) instead.")
+ (0.09 ":irc.example.net 001 tester :Welcome to the foonet IRC Network 
tester!tester@10.0.2.100")
+ (0.01 ":irc.example.net 002 tester :Your host is irc.example.net, running 
version InspIRCd-3")
+ (0.01 ":irc.example.net 003 tester :This server was created 07:50:59 Jan 22 
2024")
+ (0.03 ":irc.example.net 004 tester irc.example.net InspIRCd-3 BIRcgikorsw 
ACHIKMORTVXabcefghijklmnopqrstvyz :HIVXabefghjkloqvy")
+ (0.00 ":irc.example.net 005 tester ACCEPT=30 AWAYLEN=200 BOT=B CALLERID=g 
CASEMAPPING=ascii CHANLIMIT=#:20 CHANMODES=IXbeg,k,Hfjl,ACKMORTcimnprstz 
CHANNELLEN=64 CHANTYPES=# ELIST=CMNTU ESILENCE=CcdiNnPpTtx EXCEPTS=e :are 
supported by this server")
+ (0.01 ":irc.example.net 005 tester EXTBAN=,ACORTUacjrwz HOSTLEN=64 INVEX=I 
KEYLEN=32 KICKLEN=255 LINELEN=512 MAXLIST=I:100,X:100,b:100,e:100,g:100 
MAXTARGETS=20 MODES=20 MONITOR=30 NAMELEN=128 NAMESX NETWORK=foonet :are 
supported by this server")
+ (0.01 ":irc.example.net 005 tester NICKLEN=30 PREFIX=(yqaohvV)!~&@%+- 
SAFELIST SILENCE=32 STATUSMSG=!~&@%+- TOPICLEN=307 UHNAMES USERIP USERLEN=10 
USERMODES=,,s,BIRcgikorw WHOX :are supported by this server")
+ (0.01 ":irc.example.net 251 tester :There are 2 users and 2 invisible on 2 
servers")
+ (0.00 ":irc.example.net 252 tester 1 :operator(s) online")
+ (0.00 ":irc.example.net 253 tester 1 :unknown connections")
+ (0.00 ":irc.example.net 254 tester 2 :channels formed")
+ (0.00 ":irc.example.net 255 tester :I have 4 clients and 1 servers")
+ (0.00 ":irc.example.net 265 tester :Current local users: 4  Max: 5")
+ (0.00 ":irc.example.net 266 tester :Current global users: 4  Max: 5")
+ (0.00 ":irc.example.net 375 tester :irc.example.net message of the day")
+ (0.00 ":irc.example.net 372 tester :      
https://github.com/inspircd/inspircd-docker/issues";)
+ (0.00 ":irc.example.net 372 tester : ")
+ (0.00 ":irc.example.net 372 tester :      Have fun with the image!")
+ (0.00 ":irc.example.net 376 tester :End of message of the day.")
+ (0.00 ":irc.example.net 501 tester x :is not a recognised user mode.")
+ (0.00 ":NickServ!NickServ@services.int NOTICE tester :Welcome to foonet, 
tester! Here on foonet, we provide services to enable the registration of 
nicknames and channels! For details, type \2/msg NickServ help\2 and \2/msg 
ChanServ help\2."))
+
+((mode 10 "MODE tester +i")
+ (0.01 ":tester!tester@10.0.2.100 MODE tester :+i"))
+
+((join 10 "JOIN #chan")
+ (0.02 ":tester!tester@10.0.2.100 JOIN :#chan")
+ (0.02 ":irc.example.net 353 tester = #chan :+alice @fsbot -bob !foop tester")
+ (0.03 ":irc.example.net 366 tester #chan :End of /NAMES list.")
+ (0.00 ":bob!bob@localhost PRIVMSG #chan :tester, welcome!")
+ (0.01 ":alice!alice@localhost PRIVMSG #chan :tester, welcome!"))
+
+((mode-chan 10 "MODE #chan")
+ (0.00 ":irc.example.net 324 tester #chan :+nt")
+ (0.01 ":irc.example.net 329 tester #chan :1705909863")
+ (0.03 ":bob!bob@localhost PRIVMSG #chan :alice: Of that which hath so 
faithfully been paid.")
+ (0.03 ":alice!alice@localhost PRIVMSG #chan :Hie you, make haste, for it 
grows very late.")
+ (0.03 ":foop!user@netadmin.example.net PRIVMSG #chan :hi")
+ ;; (0.07 ":alice!alice@localhost PRIVMSG #chan :bob: And make a clear way to 
the gods.")
+ ;; (0.04 ":bob!bob@localhost PRIVMSG #chan :Why, that they have; and bid them 
so be gone.")
+ ;; (0.08 ":bob!bob@localhost PRIVMSG #chan :alice: Now stay your strife: what 
shall be is dispatch'd.")
+ (0.06 ":foop!user@netadmin.example.net MODE #chan +v :bob")
+ (0.05 ":bob!bob@localhost PRIVMSG #chan :alice: Fair as a text B in a 
copy-book.")
+ (0.07 ":alice!alice@localhost PRIVMSG #chan :bob: Even as Apemantus does now; 
hate a lord with my heart.")
+ (0.03 ":bob!bob@localhost PRIVMSG #chan :Then here is a supplication for you. 
And when you come to him, at the first approach you must kneel; then kiss his 
foot; then deliver up your pigeons; and then look for your reward. I'll be at 
hand, sir; see you do it bravely.")
+ (0.05 ":foop!user@netadmin.example.net MODE #chan -v :bob")
+ (0.04 ":bob!bob@localhost PRIVMSG #chan :alice: That's the way: for women are 
light at midnight.")
+ (0.04 ":alice!alice@localhost PRIVMSG #chan :Give it the beasts, to be rid of 
the men.")
+ ;; (0.02 ":alice!alice@localhost PRIVMSG #chan :bob: Here comes young Master 
Ganymede, my new mistress's brother.")
+ )
+
+((who-chan 10 "who #chan")
+ (0.03 ":irc.example.net 352 tester #chan alice localhost irc.example.net 
alice H+ :0 Irc bot based on irc3 http://irc3.readthedocs.io";)
+ (0.03 ":irc.example.net 352 tester #chan fsbot localhost irc.example.net 
fsbot H@ :0 fsbot")
+ (0.01 ":irc.example.net 352 tester #chan bob localhost irc.example.net bob H- 
:0 Irc bot based on irc3 http://irc3.readthedocs.io";)
+ (0.01 ":irc.example.net 352 tester #chan user netadmin.example.net 
irc.example.net foop H*! :0 unknown")
+ (0.01 ":irc.example.net 352 tester #chan tester 10.0.2.100 irc.example.net 
tester H :0 unknown")
+ (0.01 ":irc.example.net 315 tester #chan :End of /WHO list.")
+ ;; (0.09 ":bob!bob@localhost PRIVMSG #chan :alice: Shall nothing wrong him. 
Thus it is, general.")
+ ;; (0.04 ":alice!alice@localhost PRIVMSG #chan :bob: His father and I were 
soldiers together; to whom I have been often bound for no less than my life. 
Here comes the Briton: let him be so entertained amongst you as suits, with 
gentlemen of your knowing, to a stranger of his quality.")
+ (0.04 ":bob!bob@localhost PRIVMSG #chan :alice: Remains in danger of her 
former tooth."))
+
+((quit 10 "QUIT :\2ERC\2")
+ (0.03 "ERROR :Closing link: (tester@10.0.2.100) [Quit: \2ERC\2 5.x (IRC 
client for GNU Emacs)]"))
diff --git a/test/lisp/erc/resources/base/upstream-reconnect/znc-severed.eld 
b/test/lisp/erc/resources/base/upstream-reconnect/znc-severed.eld
new file mode 100644
index 00000000000..32d05cc8a3a
--- /dev/null
+++ b/test/lisp/erc/resources/base/upstream-reconnect/znc-severed.eld
@@ -0,0 +1,87 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :changeme"))
+((nick 10 "NICK tester"))
+((user 10 "USER tester@vanilla/foonet 0 * :tester")
+ (0.00 ":irc.znc.in 001 tester :Welcome to ZNC")
+ (0.03 ":*status!znc@znc.in PRIVMSG tester :Connection Refused.  
Reconnecting...")
+ (0.01 ":*status!znc@znc.in PRIVMSG tester :Connection Refused.  
Reconnecting...")
+ (0.00 ":*status!znc@znc.in PRIVMSG tester :Connection Refused.  
Reconnecting...")
+ (0.01 ":*status!znc@znc.in PRIVMSG tester :Connected!")
+ (0.02 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.01 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running 
version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Wed, 31 Jan 2024 
10:58:16 UTC")
+ (0.01 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios 
CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii 
CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# 
CHATHISTORY=1000 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by 
this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 
MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ 
TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100
 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=1000 :are supported by 
this server")
+ (0.00 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 
server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.00 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.00 ":irc.foonet.org 422 tester :MOTD File is missing")
+ (0.00 ":irc.foonet.org 221 tester +Zi")
+ (0.00 ":irc.foonet.org NOTICE tester :This server is in debug mode and is 
logging all user I/O. If you do not wish for everything you send to be readable 
by the server owner(s), please disconnect."))
+
+((mode 10 "MODE tester +i")
+ (0.01 ":irc.foonet.org 352 tester * ~u pfa3tpa5ig5ty.irc irc.foonet.org 
tester H :0 ZNC - https://znc.in";)
+ (0.01 ":irc.foonet.org 315 tester tester :End of WHO list")
+
+ (0.02 ":tester!~u@pfa3tpa5ig5ty.irc JOIN #chan")
+ (0.03 ":irc.foonet.org 353 tester = #chan :bob tester @alice eve"))
+
+((mode 10 "MODE #chan")
+ (0.00 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.00 ":bob!~u@euegh6mj3y8r2.irc PRIVMSG #chan :tester, welcome!")
+ (0.01 ":alice!~u@euegh6mj3y8r2.irc PRIVMSG #chan :tester, welcome!")
+ (0.01 ":bob!~u@euegh6mj3y8r2.irc PRIVMSG #chan :alice: And see how he will 
take it at your hands.")
+ (0.02 ":irc.foonet.org 221 tester +Zi")
+ (0.01 ":alice!~u@euegh6mj3y8r2.irc PRIVMSG #chan :bob: Fear not, my lord, 
your servant shall do so.")
+ (0.02 ":bob!~u@euegh6mj3y8r2.irc PRIVMSG #chan :alice: If I thrive well, I'll 
visit thee again.")
+ (0.01 ":irc.foonet.org 324 tester #chan +Cnt")
+ (0.03 ":irc.foonet.org 329 tester #chan 1706698713")
+ (0.05 ":alice!~u@euegh6mj3y8r2.irc PRIVMSG #chan :bob: Let it be forbid, sir; 
so should I be a great deal of his act.")
+ (0.04 ":bob!~u@euegh6mj3y8r2.irc PRIVMSG #chan :alice: And see a fearful 
sight of blood and death.")
+ (0.00 ":eve!~u@euegh6mj3y8r2.irc PRIVMSG #chan :hola")
+ (0.01 ":eve!~u@euegh6mj3y8r2.irc NICK :Evel")
+ (0.01 ":Evel!~u@euegh6mj3y8r2.irc PRIVMSG #chan :hell o")
+ (0.02 ":alice!~u@euegh6mj3y8r2.irc PRIVMSG #chan :bob: His highness comes 
post from Marseilles, of as able body as when he numbered thirty: he will be 
here to-morrow, or I am deceived by him that in such intelligence hath seldom 
failed.")
+ (0.03 ":bob!~u@euegh6mj3y8r2.irc PRIVMSG #chan :alice: See, by good hap, 
yonder's my lord; I have sweat to see his honour.")
+ (0.02 ":alice!~u@euegh6mj3y8r2.irc PRIVMSG #chan :bob: With the rich worth of 
your virginity.")
+
+ (0.02 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC. 
Reconnecting...")
+ (0.05 ":*status!znc@znc.in PRIVMSG tester :Connection Refused.  
Reconnecting...")
+ (0.03 ":*status!znc@znc.in PRIVMSG tester :Connected!")
+ (0.01 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.04 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running 
version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Wed, 31 Jan 2024 
10:58:16 UTC")
+ (0.01 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios 
CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.03 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii 
CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# 
CHATHISTORY=1000 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by 
this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 
MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ 
TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100
 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=1000 :are supported by 
this server")
+ (0.00 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 
server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0.00 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0.00 ":irc.foonet.org 422 tester :MOTD File is missing")
+ (0.02 ":irc.foonet.org 221 tester +i")
+ (0.01 ":irc.foonet.org NOTICE tester :This server is in debug mode and is 
logging all user I/O. If you do not wish for everything you send to be readable 
by the server owner(s), please disconnect.")
+ (0.02 ":irc.foonet.org 352 tester * ~u hrn2ea3rpeyck.irc irc.foonet.org 
tester H :0 ZNC - https://znc.in";)
+ (0.01 ":irc.foonet.org 315 tester tester :End of WHO list")
+ (0.02 ":tester!~u@hrn2ea3rpeyck.irc JOIN #chan"))
+
+((mode 10 "MODE #chan")
+ (0.00 ":irc.foonet.org 353 tester = #chan :tester @alice bob")
+ (0.01 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.00 ":alice!~u@euegh6mj3y8r2.irc PRIVMSG #chan :tester, welcome!")
+ (0.01 ":bob!~u@euegh6mj3y8r2.irc PRIVMSG #chan :tester, welcome!")
+ (0.02 ":alice!~u@euegh6mj3y8r2.irc PRIVMSG #chan :bob: Nay, I assure you, a 
peace concluded.")
+ (0.03 ":irc.foonet.org 324 tester #chan +Cnt")
+ (0.01 ":irc.foonet.org 329 tester #chan 1706698713")
+ (0.05 ":bob!~u@euegh6mj3y8r2.irc PRIVMSG #chan :alice: But, in defence, by 
mercy, 'tis most just.")
+ (0.04 ":alice!~u@euegh6mj3y8r2.irc PRIVMSG #chan :bob: Or to drown my 
clothes, and say I was stripped."))
diff --git a/test/lisp/erc/resources/commands/vhost.eld 
b/test/lisp/erc/resources/commands/vhost.eld
new file mode 100644
index 00000000000..42013198fbc
--- /dev/null
+++ b/test/lisp/erc/resources/commands/vhost.eld
@@ -0,0 +1,40 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :changeme"))
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version 
oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 
05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 
BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii 
CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# 
ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this 
server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 
NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ 
TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100
 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this 
server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 
server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is 
logging all user I/O. If you do not wish for everything you send to be readable 
by the server owner(s), please disconnect."))
+
+((join 10 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode-chan 10 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!"))
+
+((vhost 10 "VHOST tester changeme")
+ (0 ":irc.foonet.org NOTICE tester :Setting your VHost: some.host.test.cc")
+ (0 ":irc.foonet.org 396 tester some.host.test.cc :is now your displayed host")
+ (0 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did 
violence on herself.")
+ (0 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest 
of Arden."))
diff --git a/test/lisp/erc/resources/erc-d/erc-d-i.el 
b/test/lisp/erc/resources/erc-d/erc-d-i.el
index 05302e4f0be..219ab6d63f0 100644
--- a/test/lisp/erc/resources/erc-d/erc-d-i.el
+++ b/test/lisp/erc/resources/erc-d/erc-d-i.el
@@ -1,6 +1,6 @@
 ;;; erc-d-i.el --- IRC helpers for ERC test server -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/resources/erc-d/erc-d-t.el 
b/test/lisp/erc/resources/erc-d/erc-d-t.el
index 7126165fd91..2dc8398198f 100644
--- a/test/lisp/erc/resources/erc-d/erc-d-t.el
+++ b/test/lisp/erc/resources/erc-d/erc-d-t.el
@@ -1,6 +1,6 @@
 ;;; erc-d-t.el --- ERT helpers for ERC test server -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/resources/erc-d/erc-d-tests.el 
b/test/lisp/erc/resources/erc-d/erc-d-tests.el
index 0ae70087fd1..78f87399afb 100644
--- a/test/lisp/erc/resources/erc-d/erc-d-tests.el
+++ b/test/lisp/erc/resources/erc-d/erc-d-tests.el
@@ -1,6 +1,6 @@
 ;;; erc-d-tests.el --- tests for erc-d -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/resources/erc-d/erc-d-u.el 
b/test/lisp/erc/resources/erc-d/erc-d-u.el
index c7d6859e3e1..11202f41112 100644
--- a/test/lisp/erc/resources/erc-d/erc-d-u.el
+++ b/test/lisp/erc/resources/erc-d/erc-d-u.el
@@ -1,6 +1,6 @@
 ;;; erc-d-u.el --- Helpers for ERC test server -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/resources/erc-d/erc-d.el 
b/test/lisp/erc/resources/erc-d/erc-d.el
index a87904e5830..89701442ff6 100644
--- a/test/lisp/erc/resources/erc-d/erc-d.el
+++ b/test/lisp/erc/resources/erc-d/erc-d.el
@@ -1,6 +1,6 @@
 ;;; erc-d.el --- A dumb test server for ERC -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/resources/erc-d/resources/basic.eld 
b/test/lisp/erc/resources/erc-d/resources/basic.eld
index a020eec3fff..80e46d9a279 100644
--- a/test/lisp/erc/resources/erc-d/resources/basic.eld
+++ b/test/lisp/erc/resources/erc-d/resources/basic.eld
@@ -8,8 +8,7 @@
  (0 ":irc.example.org 002 tester :Your host is irc.example.org")
  (0 ":irc.example.org 003 tester :This server was created just now")
  (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv 
Iabehkloqv")
- (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+"
-    " :are supported by this server")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+ :are supported by this server")
  (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 
server(s)")
  ;; Just to mix thing's up (force handler to schedule timer)
  (0.1 ":irc.example.org 252 tester 0 :IRC Operators online")
@@ -24,7 +23,7 @@
  (0 ":irc.example.org 221 tester +Zi")
  (0 ":irc.example.org 306 tester :You have been marked as being away")
  (0 ":tester!~tester@localhost JOIN #chan")
- (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com 
@%+bob!~bob@example.org")
+ (0 ":irc.example.org 353 alice = #chan :+alice @bob")
  (0 ":irc.example.org 366 alice #chan :End of NAMES list"))
 
 ;; Some comment (to prevent regression)
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld 
b/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld
index e8feb2e6fd8..47be0722115 100644
--- a/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld
@@ -22,7 +22,7 @@
  (0. ":irc.barnet.org 221 tester +Zi")
  (0. ":irc.barnet.org 306 tester :You have been marked as being away")
  (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
- (0 ":irc.barnet.org 353 joe = #chan :+joe!~joe@example.com 
@%+mike!~mike@example.org")
+ (0 ":irc.barnet.org 353 joe = #chan :+joe @mike")
  (0 ":irc.barnet.org 366 joe #chan :End of NAMES list"))
 
 ((mode 3 "MODE #chan")
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld 
b/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld
index 2db750e49da..5d5f8ed18a8 100644
--- a/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld
@@ -21,7 +21,7 @@
  (0. ":irc.foonet.org 221 tester +Zi")
  (0. ":irc.foonet.org 306 tester :You have been marked as being away")
  (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
- (0 ":irc.foonet.org 353 alice = #chan :+alice!~alice@example.com 
@%+bob!~bob@example.org")
+ (0 ":irc.foonet.org 353 alice = #chan :+alice @bob")
  (0 ":irc.foonet.org 366 alice #chan :End of NAMES list"))
 
 ((mode 3 "MODE #chan")
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic.eld 
b/test/lisp/erc/resources/erc-d/resources/dynamic.eld
index 459b6e52bfe..64d8c091ad7 100644
--- a/test/lisp/erc/resources/erc-d/resources/dynamic.eld
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic.eld
@@ -7,8 +7,7 @@
  (0.0 ":" dom " 002 " nick " :Your host is " dom)
  (0.0 ":" dom " 003 " nick " :This server was created just now")
  (0.0 ":" dom " 004 " nick " " dom " BERios CEIRabehiklmnoqstv Iabehkloqv")
- (0.0 ":" dom " 005 " nick " MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+"
-      " :are supported by this server")
+ (0.0 ":" dom " 005 " nick " MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+ :are supported by this server")
  (0.0 ":" dom " 251 " nick " :There are 3 users and 0 invisible on 1 
server(s)")
  (0.0 ":" dom " 252 " nick " 0 :IRC Operators online")
  (0.0 ":" dom " 253 " nick " 0 :unregistered connections")
@@ -23,7 +22,7 @@
 
  (0.0 ":" dom " 306 " nick " :You have been marked as being away")
  (0.0 ":" nick "!~" nick "@localhost JOIN #chan")
- (0.0 ":" dom " 353 alice = #chan :+alice!~alice@example.com 
@%+bob!~bob@example.org")
+ (0.0 ":" dom " 353 alice = #chan :+alice @bob")
  (0.0 ":" dom " 366 alice #chan :End of NAMES list"))
 
 ((mode 2.2 "MODE #chan")
diff --git a/test/lisp/erc/resources/erc-d/resources/eof.eld 
b/test/lisp/erc/resources/erc-d/resources/eof.eld
index 5da84b2e74f..db39b3d4af1 100644
--- a/test/lisp/erc/resources/erc-d/resources/eof.eld
+++ b/test/lisp/erc/resources/erc-d/resources/eof.eld
@@ -8,8 +8,7 @@
  (0 ":irc.example.org 002 tester :Your host is irc.example.org")
  (0 ":irc.example.org 003 tester :This server was created just now")
  (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv 
Iabehkloqv")
- (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+"
-    " :are supported by this server")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+ :are supported by this server")
  (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 
server(s)")
  ;; Just to mix thing's up (force handler to schedule timer)
  (0.1 ":irc.example.org 252 tester 0 :IRC Operators online")
@@ -24,7 +23,7 @@
  (0 ":irc.example.org 221 tester +Zi")
  (0 ":irc.example.org 306 tester :You have been marked as being away")
  (0 ":tester!~tester@localhost JOIN #chan")
- (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com 
@%+bob!~bob@example.org")
+ (0 ":irc.example.org 353 alice = #chan :+alice @bob")
  (0 ":irc.example.org 366 alice #chan :End of NAMES list"))
 
 ((mode-chan 1.2 "MODE #chan")
diff --git a/test/lisp/erc/resources/erc-d/resources/fuzzy.eld 
b/test/lisp/erc/resources/erc-d/resources/fuzzy.eld
index 0504b6a6682..cf64004da0d 100644
--- a/test/lisp/erc/resources/erc-d/resources/fuzzy.eld
+++ b/test/lisp/erc/resources/erc-d/resources/fuzzy.eld
@@ -23,12 +23,12 @@
 
 ((~join-foo 3.2 "JOIN #foo")
  (0 "@time=" now " :tester!~tester@localhost JOIN #foo")
- (0 "@time=" now " :irc.example.org 353 alice = #foo 
:+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 "@time=" now " :irc.example.org 353 alice = #foo :+alice @bob")
  (0 "@time=" now " :irc.example.org 366 alice #foo :End of NAMES list"))
 
 ((~join-bar 1.2 "JOIN #bar")
  (0 "@time=" now " :tester!~tester@localhost JOIN #bar")
- (0 "@time=" now " :irc.example.org 353 alice = #bar 
:+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 "@time=" now " :irc.example.org 353 alice = #bar :+alice @bob")
  (0 "@time=" now " :irc.example.org 366 alice #bar :End of NAMES list"))
 
 ((~mode-foo 3.2 "MODE #foo")
diff --git a/test/lisp/erc/resources/erc-d/resources/incremental.eld 
b/test/lisp/erc/resources/erc-d/resources/incremental.eld
index a1b48495ec3..7d192a53066 100644
--- a/test/lisp/erc/resources/erc-d/resources/incremental.eld
+++ b/test/lisp/erc/resources/erc-d/resources/incremental.eld
@@ -7,8 +7,7 @@
  (0.0 ":irc.foo.net 002 tester :Your host is irc.foo.net")
  (0.0 ":irc.foo.net 003 tester :This server was created just now")
  (0.0 ":irc.foo.net 004 tester irc.foo.net BERios CEIRabehiklmnoqstv 
Iabehkloqv")
- (0.0 ":irc.foo.net 005 tester MODES NETWORK=FooNet NICKLEN=32 
PREFIX=(qaohv)~&@%+"
-              " :are supported by this server")
+ (0.0 ":irc.foo.net 005 tester MODES NETWORK=FooNet NICKLEN=32 
PREFIX=(qaohv)~&@%+ :are supported by this server")
  (0.0 ":irc.foo.net 251 tester :There are 3 users and 0 invisible on 1 
server(s)")
  (0.0 ":irc.foo.net 252 tester 0 :IRC Operators online")
  (0.0 ":irc.foo.net 253 tester 0 :unregistered connections")
@@ -24,7 +23,7 @@
 
 ((join 3 "JOIN #foo")
  (0 ":tester!~tester@localhost JOIN #foo")
- (0 ":irc.foo.net 353 alice = #foo :+alice!~alice@example.com 
@%+bob!~bob@example.org")
+ (0 ":irc.foo.net 353 alice = #foo :+alice @bob")
  (0 ":irc.foo.net 366 alice #foo :End of NAMES list"))
 
 ((mode 3 "MODE #foo")
diff --git a/test/lisp/erc/resources/erc-d/resources/linger.eld 
b/test/lisp/erc/resources/erc-d/resources/linger.eld
index e456370a800..d68da730581 100644
--- a/test/lisp/erc/resources/erc-d/resources/linger.eld
+++ b/test/lisp/erc/resources/erc-d/resources/linger.eld
@@ -8,8 +8,7 @@
  (0 ":irc.example.org 002 tester :Your host is irc.example.org")
  (0 ":irc.example.org 003 tester :This server was created just now")
  (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv 
Iabehkloqv")
- (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+"
-    " :are supported by this server")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+ :are supported by this server")
  (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 
server(s)")
  ;; Just to mix thing's up (force handler to schedule timer)
  (0.1 ":irc.example.org 252 tester 0 :IRC Operators online")
@@ -24,7 +23,7 @@
  (0 ":irc.example.org 221 tester +Zi")
  (0 ":irc.example.org 306 tester :You have been marked as being away")
  (0 ":tester!~tester@localhost JOIN #chan")
- (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com 
@%+bob!~bob@example.org")
+ (0 ":irc.example.org 353 alice = #chan :+alice @bob")
  (0 ":irc.example.org 366 alice #chan :End of NAMES list"))
 
 ((mode-chan 2 "MODE #chan")
diff --git a/test/lisp/erc/resources/erc-d/resources/no-block.eld 
b/test/lisp/erc/resources/erc-d/resources/no-block.eld
index 2811923d8ac..af2f4a83ff6 100644
--- a/test/lisp/erc/resources/erc-d/resources/no-block.eld
+++ b/test/lisp/erc/resources/erc-d/resources/no-block.eld
@@ -7,8 +7,7 @@
  (0.0 ":irc.org 002 tester :Your host is irc.org")
  (0.0 ":irc.org 003 tester :This server was created just now")
  (0.0 ":irc.org 004 tester irc.org BERios CEIRabehiklmnoqstv Iabehkloqv")
- (0.0 ":irc.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+"
-              " :are supported by this server")
+ (0.0 ":irc.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+ :are supported by this server")
  (0.0 ":irc.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
  (0.0 ":irc.org 252 tester 0 :IRC Operators online")
  (0.0 ":irc.org 253 tester 0 :unregistered connections")
@@ -24,13 +23,13 @@
 
 ((join-foo 1.2 "JOIN #foo")
  (0 ":tester!~tester@localhost JOIN #foo")
- (0 ":irc.example.org 353 alice = #foo :+alice!~alice@example.com 
@%+bob!~bob@example.org")
+ (0 ":irc.example.org 353 alice = #foo :+alice @bob")
  (0 ":irc.example.org 366 alice #foo :End of NAMES list"))
 
 ;; This would time out if the mode-foo's outgoing blocked (remove minus signs 
to see)
 ((~join-bar 1.5 "JOIN #bar")
  (0 ":tester!~tester@localhost JOIN #bar")
- (0 ":irc.example.org 353 alice = #bar :+alice!~alice@example.com 
@%+bob!~bob@example.org")
+ (0 ":irc.example.org 353 alice = #bar :+alice @bob")
  (0 ":irc.example.org 366 alice #bar :End of NAMES list"))
 
 ((mode-foo 1.2 "MODE #foo")
diff --git a/test/lisp/erc/resources/erc-d/resources/no-match.eld 
b/test/lisp/erc/resources/erc-d/resources/no-match.eld
index d147be1e084..d12854de551 100644
--- a/test/lisp/erc/resources/erc-d/resources/no-match.eld
+++ b/test/lisp/erc/resources/erc-d/resources/no-match.eld
@@ -8,8 +8,7 @@
  (0 ":irc.example.org 002 tester :Your host is irc.example.org")
  (0 ":irc.example.org 003 tester :This server was created just now")
  (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv 
Iabehkloqv")
- (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+"
-    " :are supported by this server")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+ :are supported by this server")
  (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 
server(s)")
  (0 ":irc.example.org 252 tester 0 :IRC Operators online")
  (0 ":irc.example.org 253 tester 0 :unregistered connections")
@@ -25,7 +24,7 @@
 
 ((join 1.2 "JOIN #chan")
  (0 ":tester!~tester@localhost JOIN #chan")
- (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com 
@%+bob!~bob@example.org")
+ (0 ":irc.example.org 353 alice = #chan :+alice @bob")
  (0 ":irc.example.org 366 alice #chan :End of NAMES list"))
 
 ((mode-chan 0.2 "MODE #chan")
diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el 
b/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el
index 541c222dc21..38ab9f3136a 100644
--- a/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el
+++ b/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el
@@ -1,6 +1,6 @@
 ;;; proxy-subprocess.el --- Example setup file for erc-d  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/erc/resources/erc-d/resources/unexpected.eld 
b/test/lisp/erc/resources/erc-d/resources/unexpected.eld
index ac0a8fecfa6..c03b1dbcfdb 100644
--- a/test/lisp/erc/resources/erc-d/resources/unexpected.eld
+++ b/test/lisp/erc/resources/erc-d/resources/unexpected.eld
@@ -7,8 +7,7 @@
  (0.0 ":irc.example.org 002 tester :Your host is irc.example.org")
  (0.0 ":irc.example.org 003 tester :This server was created just now")
  (0.0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv 
Iabehkloqv")
- (0.0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+"
-      " :are supported by this server")
+ (0.0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 
PREFIX=(qaohv)~&@%+ :are supported by this server")
  (0.0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 
server(s)")
  (0.0 ":irc.example.org 252 tester 0 :IRC Operators online")
  (0.0 ":irc.example.org 253 tester 0 :unregistered connections")
@@ -23,6 +22,6 @@
 
  (0.0 ":irc.example.org 306 tester :You have been marked as being away")
  (0.0 ":tester!~tester@localhost JOIN #chan")
- (0.0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com 
@%+bob!~bob@example.org")
+ (0.0 ":irc.example.org 353 alice = #chan :+alice @bob")
  (0.0 ":irc.example.org 366 alice #chan :End of NAMES list")
  (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))
diff --git a/test/lisp/erc/resources/erc-scenarios-common.el 
b/test/lisp/erc/resources/erc-scenarios-common.el
index 311d8a82d72..042b3a8c05b 100644
--- a/test/lisp/erc/resources/erc-scenarios-common.el
+++ b/test/lisp/erc/resources/erc-scenarios-common.el
@@ -1,6 +1,6 @@
 ;;; erc-scenarios-common.el --- Common helpers for ERC scenarios -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -61,6 +61,25 @@
 ;; always associated with the fake network FooNet, while nicks Joe and
 ;; Mike are always on BarNet.  (Networks are sometimes downcased.)
 ;;
+;; Environment variables:
+;;
+;;  `ERC_TESTS_GRAPHICAL': Internal variable to unskip those few tests
+;;   capable of running consecutively while interactive on a graphical
+;;   display.  This triggers both the tests and the suite to commence
+;;   with teardown activities normally skipped to allow for inspection
+;;   while interactive.  This is also handy when needing to quickly
+;;   run `ert-results-rerun-test-at-point-debugging-errors' on a
+;;   failing test because you don't have to go around hunting for and
+;;   killing associated buffers and processes.
+;;
+;;  `ERC_TESTS_GRAPHICAL_ALL': Currently targets a single "meta" test,
+;;   `erc-scenarios-internal--run-interactive-all', that runs all
+;;   tests tagged `:erc--graphical' in an interactive subprocess.
+;;
+;;  `ERC_TESTS_SUBPROCESS': Used internally to detect nested tests.
+;;
+;;  `ERC_D_DEBUG': Tells `erc-d' to emit debugging info to stderr.
+;;
 ;; XXX This file should *not* contain any test cases.
 
 ;;; Code:
@@ -91,6 +110,7 @@
 
 (defvar erc-scenarios-common-dialog nil)
 (defvar erc-scenarios-common-extra-teardown nil)
+(defvar erc-scenarios-common--graphical-p nil)
 
 (defun erc-scenarios-common--add-silence ()
   (advice-add #'erc-login :around #'erc-d-t-silence-around)
@@ -110,7 +130,11 @@
 
 (eval-and-compile
   (defun erc-scenarios-common--make-bindings (bindings)
-    `((erc-d-u-canned-dialog-dir (expand-file-name
+    `((erc-scenarios-common--graphical-p
+       (and (or erc-scenarios-common--graphical-p
+                (memq :erc--graphical (ert-test-tags (ert-running-test))))
+            (not (and noninteractive (ert-skip "Interactive only")))))
+      (erc-d-u-canned-dialog-dir (expand-file-name
                                   (or erc-scenarios-common-dialog
                                       (cadr (assq 'erc-scenarios-common-dialog
                                                   ',bindings)))
@@ -119,7 +143,7 @@
                          (quit . ,(erc-quit/part-reason-default))
                          (erc-version . ,erc-version)))
       (erc-modules (copy-sequence erc-modules))
-      (inhibit-interaction t)
+      (inhibit-interaction noninteractive)
       (auth-source-do-cache nil)
       (timer-list (copy-sequence timer-list))
       (timer-idle-list (copy-sequence timer-idle-list))
@@ -127,6 +151,7 @@
       (erc-autojoin-channels-alist nil)
       (erc-server-auto-reconnect nil)
       (erc-after-connect nil)
+      (erc-last-input-time 0)
       (erc-d-linger-secs 10)
       ,@bindings)))
 
@@ -139,13 +164,19 @@ disabled by BODY.  Other defaults common to these test 
cases are added
 below and can be overridden, except when wanting the \"real\" default
 value, which must be looked up or captured outside of the calling form.
 
+When running tests tagged as serially runnable while interactive
+and the flag `erc-scenarios-common--graphical-p' is non-nil, run
+teardown tasks normally inhibited when interactive.  That is,
+behave almost as if `noninteractive' were also non-nil, and
+ensure buffers and other resources are destroyed on completion.
+
 Dialog resource directories are located by expanding the variable
 `erc-scenarios-common-dialog' or its value in BINDINGS."
   (declare (indent 1))
 
   (let* ((orig-autojoin-mode (make-symbol "orig-autojoin-mode"))
          (combined `((,orig-autojoin-mode (bound-and-true-p erc-autojoin-mode))
-                    ,@(erc-scenarios-common--make-bindings bindings))))
+                     ,@(erc-scenarios-common--make-bindings bindings))))
 
     `(erc-d-t-with-cleanup (,@combined)
 
@@ -165,8 +196,9 @@ Dialog resource directories are located by expanding the 
variable
                       (not (eq erc-autojoin-mode ,orig-autojoin-mode)))
              (erc-autojoin-mode (if ,orig-autojoin-mode +1 -1)))
 
-           (when noninteractive
-             (erc-scenarios-common--print-trace)
+           (when (or noninteractive erc-scenarios-common--graphical-p)
+             (when noninteractive
+               (erc-scenarios-common--print-trace))
              (erc-d-t-kill-related-buffers)
              (delete-other-windows)))
 
@@ -179,7 +211,8 @@ Dialog resource directories are located by expanding the 
variable
                (erc-d-t-search-for 3 "Starting")))))
 
        (ert-info ("Activate erc-debug-irc-protocol")
-         (unless (and noninteractive (not erc-debug-irc-protocol))
+         (unless (and (or noninteractive erc-scenarios-common--graphical-p)
+                      (not erc-debug-irc-protocol))
            (erc-toggle-debug-irc-protocol)))
 
        ,@body)))
@@ -417,7 +450,9 @@ See Info node `(emacs) Term Mode' for the various commands."
         (erc-scenarios-common-say "/msg NickServ help identify")
         ;; New arriving messages trigger a snap when inserted.
         (erc-d-t-wait-for 10 (erc-scenarios-common--at-win-end-p))
-        (funcall expect 10 "IDENTIFY lets you login")))))
+        (funcall expect 10 "IDENTIFY lets you login"))
+
+      (erc-scrolltobottom-mode -1))))
 
 (cl-defun erc-scenarios-common--base-network-id-bouncer
     ((&key autop foo-id bar-id after
diff --git a/test/lisp/erc/resources/erc-tests-common.el 
b/test/lisp/erc/resources/erc-tests-common.el
new file mode 100644
index 00000000000..99f15b89b03
--- /dev/null
+++ b/test/lisp/erc/resources/erc-tests-common.el
@@ -0,0 +1,301 @@
+;;; erc-tests-common.el --- Common helpers for ERC tests -*- lexical-binding: 
t -*-
+
+;; Copyright (C) 2023-2024 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:
+
+;; This file must *not* contain any `ert-deftest' definitions.  See
+;; top of test/lisp/erc/erc-tests.el for loading example.
+;;
+;; Environment variables:
+;;
+;;  `ERC_PACKAGE_NAME': Name of the installed ERC package currently
+;;   running.  ERC needs this in order to load the same package in
+;;   tests that run in a subprocess.  Necessary even when the package
+;;   name is `erc' and not something like `erc-49860'.
+;;
+;;  `ERC_TESTS_INIT': The name of an alternate init file.  Mainly for
+;;   integrations tests involving starter kits.
+;;
+;;  `ERC_TESTS_SNAPSHOT_SAVE': When set, ERC saves the current test's
+;;   snapshots to disk.
+;;
+
+;;; Code:
+(require 'ert-x)
+(require 'erc)
+
+
+(defmacro erc-tests-common-equal-with-props (a b)
+  "Compare strings A and B for equality including text props.
+Use `ert-equal-including-properties' on older Emacsen."
+  (list (if (< emacs-major-version 29)
+            'ert-equal-including-properties
+          'equal-including-properties)
+        a b))
+
+;; Caller should probably shadow `erc-insert-modify-hook' or populate
+;; user tables for erc-button.
+;; FIXME explain this comment ^ in more detail or delete.
+(defun erc-tests-common-prep-for-insertion ()
+  "Initialize current buffer with essentials for message insertion.
+Assume caller intends to use `erc-display-message'."
+  (erc-mode)
+  (erc--initialize-markers (point) nil)
+  (should (= (point) erc-input-marker)))
+
+(defun erc-tests-common-init-server-proc (&rest args)
+  "Create a process with `start-process' from ARGS.
+Assign the result to `erc-server-process' in the current buffer."
+  (setq erc-server-process
+        (apply #'start-process (car args) (current-buffer) args))
+  (set-process-query-on-exit-flag erc-server-process nil)
+  erc-server-process)
+
+;; After dropping support for Emacs 27, callers can use
+;; `get-buffer-create' with INHIBIT-BUFFER-HOOKS.
+(defun erc-tests-common-kill-buffers (&rest extra-buffers)
+  "Kill all ERC buffers and possibly EXTRA-BUFFERS."
+  (let (erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+    (dolist (buf (erc-buffer-list))
+      (kill-buffer buf))
+    (named-let doit ((buffers extra-buffers))
+      (dolist (buf buffers)
+        (if (consp buf) (doit buf) (kill-buffer buf))))))
+
+(defun erc-tests-common-with-process-input-spy (test-fn)
+  "Mock `erc-process-input-line' and call TEST-FN.
+Shadow `erc--input-review-functions' and `erc-pre-send-functions'
+with `erc-add-to-input-ring' removed.  Shadow other relevant
+variables as nil, and bind `erc-last-input-time' to 0.  Also mock
+`erc-server-buffer' to return the current buffer.  Call TEST-FN
+with a utility function that returns the set of arguments most
+recently passed to the mocked `erc-process-input-line'.  Make
+`inhibit-message' non-nil unless running interactively."
+  (with-current-buffer (get-buffer-create "FakeNet")
+    (let* ((erc--input-review-functions
+            (remove 'erc-add-to-input-ring erc--input-review-functions))
+           (erc-pre-send-functions
+            (remove 'erc-add-to-input-ring erc-pre-send-functions)) ; for now
+           (inhibit-message noninteractive)
+           (erc-server-current-nick "tester")
+           (erc-last-input-time 0)
+           erc-accidental-paste-threshold-seconds
+           erc-send-modify-hook
+           ;;
+           calls)
+      (cl-letf (((symbol-function 'erc-process-input-line)
+                 (lambda (&rest r) (push r calls)))
+                ((symbol-function 'erc-server-buffer)
+                 (lambda () (current-buffer))))
+        (erc-tests-common-prep-for-insertion)
+        (funcall test-fn (lambda () (pop calls)))))
+    (when noninteractive (kill-buffer))))
+
+(defun erc-tests-common-make-server-buf (&optional name)
+  "Return a server buffer named NAME, creating it if necessary.
+Use NAME for the network and the session server as well."
+  (unless name
+    (cl-assert (string-prefix-p " *temp*" (setq name (buffer-name)))))
+  (with-current-buffer (get-buffer-create name)
+    (erc-tests-common-prep-for-insertion)
+    (erc-tests-common-init-server-proc "sleep" "1")
+    (setq erc-session-server (concat "irc." name ".org")
+          erc-server-announced-name (concat "west." name ".org")
+          erc-server-users (make-hash-table :test #'equal)
+          erc-server-parameters nil
+          erc--isupport-params (make-hash-table)
+          erc-session-port 6667
+          erc-network (intern name)
+          erc-networks--id (erc-networks--id-create name))
+    (current-buffer)))
+
+(defun erc-tests-common-string-to-propertized-parts (string)
+  "Return a sequence of `propertize' forms for generating STRING.
+Expect maintainers manipulating template catalogs to use this
+with `pp-eval-last-sexp' or similar to convert back and forth
+between literal strings."
+  `(concat
+    ,@(mapcar
+       (pcase-lambda (`(,beg ,end ,plist))
+         ;; At the time of writing, `propertize' produces a string
+         ;; with the order of the input plist reversed.
+         `(propertize ,(substring-no-properties string beg end)
+                      ,@(let (out)
+                          (while-let ((plist)
+                                      (k (pop plist))
+                                      (v (pop plist)))
+                            (push (if (or (consp v) (symbolp v)) `',v v) out)
+                            (push `',k out))
+                          out)))
+       (object-intervals string))))
+
+(defun erc-tests-common-pp-propertized-parts (arg)
+  "Convert literal string before point into a `propertize'd form.
+For simplicity, assume string evaluates to itself."
+  (interactive "P")
+  (let ((sexp (erc-tests-common-string-to-propertized-parts (pp-last-sexp))))
+    (if arg (insert (pp-to-string sexp)) (pp-macroexpand-expression sexp))))
+
+;; The following utilities are meant to help prepare tests for
+;; `erc--get-inserted-msg-bounds' and friends.
+(defun erc-tests-common-get-inserted-msg-setup ()
+  (erc-tests-common-prep-for-insertion)
+  (let ((parsed (make-erc-response :unparsed ":bob PRIVMSG #chan :hi"
+                                   :sender "bob"
+                                   :command "PRIVMSG"
+                                   :command-args (list "#chan" "hi")
+                                   :contents "hi"))
+        (erc--msg-prop-overrides '((erc--ts . 0))))
+    (erc-display-message parsed nil (current-buffer)
+                         (erc-format-privmessage "bob" "hi" nil t)))
+  (goto-char 3)
+  (should (looking-at "<bob> hi")))
+
+;; All these bounds-finding functions take an optional POINT argument.
+;; So run each case with and without it at each pos in the message.
+(defun erc-tests-common-assert-get-inserted-msg (from to assert-fn)
+  (dolist (pt-arg '(nil t))
+    (dolist (i (number-sequence from to))
+      (goto-char i)
+      (ert-info ((format "At %d (%c) %s param" i (char-after i)
+                         (if pt-arg "with" "")))
+        (funcall assert-fn (and pt-arg i))))))
+
+(defun erc-tests-common-assert-get-inserted-msg/basic (test-fn)
+  (erc-tests-common-get-inserted-msg-setup)
+  (goto-char 11)
+  (should (looking-back "<bob> hi"))
+  (erc-tests-common-assert-get-inserted-msg 3 11 test-fn))
+
+;; This is a "mixin" and requires a base assertion function, like
+;; `erc-tests-common-assert-get-inserted-msg/basic', to work.
+(defun erc-tests-common-assert-get-inserted-msg-readonly-with
+    (assert-fn test-fn)
+  (defvar erc-readonly-mode)
+  (defvar erc-readonly-mode-hook)
+  (let ((erc-readonly-mode nil)
+        (erc-readonly-mode-hook nil)
+        (erc-send-post-hook erc-send-post-hook)
+        (erc-insert-post-hook erc-insert-post-hook))
+    (erc-readonly-mode +1)
+    (funcall assert-fn test-fn)))
+
+
+;;;; Buffer snapshots
+
+;; Use this variable to generate new snapshots after carefully
+;; reviewing the output of *each* snapshot (not just first and last).
+;; Obviously, only run one test at a time.
+(defvar erc-tests-common-snapshot-save-p (getenv "ERC_TESTS_SNAPSHOT_SAVE"))
+
+(defun erc-tests-common-snapshot-compare (name dir trans-fn buf-init-fn)
+  "Compare `buffer-string' to snapshot NAME.eld in DIR, if present.
+When non-nil, run TRANS-FN to filter the current buffer string,
+and expect a similar string in return.  Call BUF-INIT-FN, when
+non-nil, in the preview buffer after inserting the filtered
+string."
+  (let* ((expect-file (file-name-with-extension (expand-file-name name dir)
+                                                "eld"))
+         (erc--own-property-names
+          (seq-difference `(font-lock-face ,@erc--own-property-names)
+                          `(field display wrap-prefix line-prefix
+                                  erc--msg erc--cmd erc--spkr erc--ts erc--ctcp
+                                  erc--ephemeral)
+                          #'eq))
+         (print-circle t)
+         (print-escape-newlines t)
+         (print-escape-nonascii t)
+         (got (erc--remove-text-properties
+               (buffer-substring (point-min) erc-insert-marker)))
+         (repr (funcall (or trans-fn #'identity) (prin1-to-string got))))
+    (with-current-buffer (generate-new-buffer name)
+      (with-silent-modifications
+        (insert (setq got (read repr))))
+      (when buf-init-fn (funcall buf-init-fn))
+      (erc-mode))
+    ;; LHS is a string, RHS is a symbol.
+    (if (string= erc-tests-common-snapshot-save-p
+                 (ert-test-name (ert-running-test)))
+        (let (inhibit-message)
+          (with-temp-file expect-file
+            (insert repr))
+          ;; Limit writing snapshots to one test at a time.
+          (message "erc-tests-common-snapshot-compare: wrote %S" expect-file))
+      (if (file-exists-p expect-file)
+          ;; Ensure string-valued properties, like timestamps, aren't
+          ;; recursive (signals `max-lisp-eval-depth' exceeded).
+          (named-let assert-equal
+              ((latest (read repr))
+               (expect (read (with-temp-buffer
+                               (insert-file-contents-literally expect-file)
+                               (buffer-string)))))
+            (pcase latest
+              ((or "" 'nil) t)
+              ((pred stringp)
+               (should (equal-including-properties latest expect))
+               (let ((latest-intervals (object-intervals latest))
+                     (expect-intervals (object-intervals expect)))
+                 (while-let ((l-iv (pop latest-intervals))
+                             (x-iv (pop expect-intervals))
+                             (l-tab (map-into (nth 2 l-iv) 'hash-table))
+                             (x-tab (map-into (nth 2 x-iv) 'hash-table)))
+                   (pcase-dolist (`(,l-k . ,l-v) (map-pairs l-tab))
+                     (assert-equal l-v (gethash l-k x-tab))
+                     (remhash l-k x-tab))
+                   (should (zerop (hash-table-count x-tab))))))
+              ((pred sequencep)
+               (assert-equal (seq-first latest) (seq-first expect))
+               (assert-equal (seq-rest latest) (seq-rest expect)))
+              (_ (should (equal latest expect)))))
+        (message "Snapshot file missing: %S" expect-file)))))
+
+(defun erc-tests-common-create-subprocess (code switches libs)
+  "Return subprocess for running CODE in an inferior Emacs.
+Include SWITCHES, like \"-batch\", as well as libs, after
+interspersing \"-l\" between members."
+  (let* ((package (if-let ((found (getenv "ERC_PACKAGE_NAME"))
+                           ((string-prefix-p "erc-" found)))
+                      (intern found)
+                    'erc))
+         ;; For integrations testing with managed configs that use a
+         ;; different package manager.
+         (init (and-let* ((found (getenv "ERC_TESTS_INIT"))
+                          (files (split-string found ",")))
+                 (mapcan (lambda (f) (list "-l" f)) files)))
+         (prog
+          `(progn
+             ,@(and (not init) (featurep 'compat)
+                    `((require 'package)
+                      (let ((package-load-list '((compat t) (,package t))))
+                        (package-initialize))))
+             (require 'erc)
+             (cl-assert (equal erc-version ,erc-version) t)
+             ,code))
+         (proc (apply #'start-process
+                      (symbol-name (ert-test-name (ert-running-test)))
+                      (current-buffer)
+                      (concat invocation-directory invocation-name)
+                      `(,@(or init '("-Q"))
+                        ,@switches
+                        ,@(mapcan (lambda (f) (list "-l" f)) libs)
+                        "-eval" ,(format "%S" prog)))))
+    (set-process-query-on-exit-flag proc t)
+    proc))
+
+(provide 'erc-tests-common)
diff --git a/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld 
b/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld
index c07eee3517f..3c32719a052 100644
--- a/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld
+++ b/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<alic [...]
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<alic [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld 
b/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld
index cf5cdb4f825..e2064b914c4 100644
--- a/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld
+++ b/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<alic [...]
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<alic [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld 
b/test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld
index ad4e6483f01..feaba85ec90 100644
--- a/test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld
+++ b/test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<bob> [...]
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<bob> [...]
\ No newline at end of file
diff --git 
a/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-post-01.eld 
b/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-post-01.eld
index 893588c028f..ed1488c8595 100644
--- a/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-post-01.eld
+++ b/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-post-01.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<bob> [...]
\ No newline at end of file
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<bob> [...]
\ No newline at end of file
diff --git 
a/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld 
b/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld
index 2b67cbbf90e..a3530a6c44d 100644
--- a/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld
+++ b/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<bob> [...]
\ No newline at end of file
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr  1 
2023]\n<bob> zero.[07:00]\n<bob> [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld 
b/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld
index 84a1e34670c..c94629cf357 100644
--- a/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld
+++ b/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc-msg 
datestamp erc-ts 0 field erc-ti [...]
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg 
datestamp erc--ts 0 field erc- [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld 
b/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld
index 83394f2f639..127c0b29bc9 100644
--- a/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld
+++ b/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc-msg 
datestamp erc-ts 0 field erc-ti [...]
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg 
datestamp erc--ts 0 field erc- [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld 
b/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld
index 1605628b29f..a9f3f1d1904 100644
--- a/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld
+++ b/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc-msg 
datestamp erc-ts 0 field erc-ti [...]
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg 
datestamp erc--ts 0 field erc- [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld 
b/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld
index 84a1e34670c..c94629cf357 100644
--- a/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld
+++ b/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc-msg 
datestamp erc-ts 0 field erc-ti [...]
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg 
datestamp erc--ts 0 field erc- [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld 
b/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld
index 7a7e01de49d..754d7989cea 100644
--- a/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld
+++ b/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n<bob> This 
buffer is for text.\n*** one two th [...]
+#("\n\n\n[Thu Jan  1 1970]\n*** This server is in debug mode and is logging 
all user I/O. If you do not wish for everything you send to be readable by the 
server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a 
tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause 
to complain of? Come me to what was done to her.\n<bob> alice: Either your 
unparagoned mistress is dead, or she's outprized by a trifle.\n<bob> This 
buffer is for text.\n*** one two th [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/stamps-left-01.eld 
b/test/lisp/erc/resources/fill/snapshots/stamps-left-01.eld
index bb248ffb28e..1b22b6c5cfd 100644
--- a/test/lisp/erc/resources/fill/snapshots/stamps-left-01.eld
+++ b/test/lisp/erc/resources/fill/snapshots/stamps-left-01.eld
@@ -1 +1 @@
-#("\n\n[00:00]*** This server is in debug mode and is logging all user I/O. If 
you do not wish for everything you send to be readable by the server owner(s), 
please disconnect.\n[00:00]<alice> bob: come, you are a tedious fool: to the 
purpose. What was done to Elbow's wife, that he hath cause to complain of? Come 
me to what was done to her.\n[00:00]<bob> alice: Either your unparagoned 
mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc-msg notice erc-ts 
0 display #3=(#5=(margin [...]
+#("\n\n[00:00]*** This server is in debug mode and is logging all user I/O. If 
you do not wish for everything you send to be readable by the server owner(s), 
please disconnect.\n[00:00]<alice> bob: come, you are a tedious fool: to the 
purpose. What was done to Elbow's wife, that he hath cause to complain of? Come 
me to what was done to her.\n[00:00]<bob> alice: Either your unparagoned 
mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg notice 
erc--ts 0 display #3=(#5=(marg [...]
\ No newline at end of file
diff --git a/test/lisp/erc/resources/join/network-id/barnet.eld 
b/test/lisp/erc/resources/join/network-id/barnet.eld
index e33dd6be29e..ad6a7c820a9 100644
--- a/test/lisp/erc/resources/join/network-id/barnet.eld
+++ b/test/lisp/erc/resources/join/network-id/barnet.eld
@@ -40,4 +40,4 @@
  (0.05 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: And now, dear maid, be 
you as free to us.")
  (0.00 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: He hath an uncle here 
in Messina will be very much glad of it."))
 
-((linger 3.5 LINGER))
+((linger 30 LINGER))
diff --git a/test/lisp/erc/resources/join/network-id/foonet-again.eld 
b/test/lisp/erc/resources/join/network-id/foonet-again.eld
index b230eff27c7..a8b8a52f87a 100644
--- a/test/lisp/erc/resources/join/network-id/foonet-again.eld
+++ b/test/lisp/erc/resources/join/network-id/foonet-again.eld
@@ -43,4 +43,4 @@
  (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :alice: But we are spirits of 
another sort.")
  (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: It was not given me, 
nor I did not buy it."))
 
-((linger 6 LINGER))
+((linger 30 LINGER))
diff --git a/test/lisp/erc/resources/keep-place/follow.eld 
b/test/lisp/erc/resources/keep-place/follow.eld
new file mode 100644
index 00000000000..db9352d93be
--- /dev/null
+++ b/test/lisp/erc/resources/keep-place/follow.eld
@@ -0,0 +1,78 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER tester 0 * :tester")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.01 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running 
version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Tue, 26 Dec 2023 
08:36:35 UTC")
+ (0.01 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios 
CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii 
CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# 
CHATHISTORY=1000 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by 
this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 
MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ 
TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100
 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=1000 :are supported by 
this server")
+ (0.01 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 
server(s)")
+ (0.01 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0.00 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0.03 ":irc.foonet.org 422 tester :MOTD File is missing")
+ (0.01 ":irc.foonet.org NOTICE tester :This server is in debug mode and is 
logging all user I/O. If you do not wish for everything you send to be readable 
by the server owner(s), please disconnect."))
+
+((mode 10 "MODE tester +i"))
+
+((join 10 "JOIN #chan")
+ (0.01 ":irc.foonet.org 221 tester +i")
+ (0.01 ":tester!~u@p64eqfwvvbxrk.irc JOIN #chan")
+ (0.03 ":irc.foonet.org 353 tester = #chan :@fsbot bob alice tester")
+ (0.01 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.00 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :tester, welcome!")
+ (0.01 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :tester, welcome!"))
+
+((join 10 "JOIN #spam")
+ (0.00 ":tester!~u@p64eqfwvvbxrk.irc JOIN #spam")
+ (0.06 ":irc.foonet.org 353 tester = #spam :@fsbot bob alice tester")
+ (0.01 ":irc.foonet.org 366 tester #spam :End of NAMES list")
+ (0.03 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #spam :tester, welcome!")
+ (0.01 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #spam :tester, welcome!"))
+
+((mode 10 "MODE #chan")
+ (0.00 ":irc.foonet.org 324 tester #chan +Cnt")
+ (0.02 ":irc.foonet.org 329 tester #chan 1703579802")
+ (0.02 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :bob: Madam, my lord is 
gone, for ever gone.")
+ (0.10 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :The kinder we, to give them 
thanks for nothing."))
+
+((mode 10 "MODE #spam")
+ (0.00 ":irc.foonet.org 324 tester #spam +Cnt")
+ (0.02 ":irc.foonet.org 329 tester #spam 1703579805")
+ (0.02 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :Most manifest, and not denied 
by himself.")
+ (0.02 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :alice: To bed, to bed: 
there's knocking at the gate. Come, come, come, come, give me your hand. What's 
done cannot be undone.")
+ (0.02 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :bob: And what I spake, I 
spake it to my face.")
+ (0.08 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :alice: Since you can cog, 
I'll play no more with you.")
+ (0.06 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :bob: The little casket 
bring me hither.")
+ (0.01 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :alice: Not to-night, good 
Iago: I have very poor and unhappy brains for drinking: I could well wish 
courtesy would invent some other custom of entertainment.")
+ (0.02 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :Yes, faith will I, Fridays 
and Saturdays and all."))
+
+((privmsg 10 "PRIVMSG #spam :one")
+ (0.03 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :bob: This is the first 
truth that e'er thine own tongue was guilty of.")
+ (0.02 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :alice: Drown the lamenting 
fool in sea-salt tears.")
+
+ ;; Insert some lines ^ before rendezvous, so #chan can update scrolltobottom.
+ (0.01 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #spam :Ay, the heads of the maids, 
or their maidenheads; take it in what sense thou wilt.")
+
+ (0.05 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :alice: And work confusion on 
his enemies.")
+ (0.06 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :bob: Truly, she must be 
given, or the marriage is not lawful."))
+
+((privmsg 10 "PRIVMSG #spam :two")
+ (0.02 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :To be whipped; and yet a 
better love than my master.")
+ (0.06 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :And duty in his service 
perishing.")
+
+ ;; Second check point.
+ (0.01 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #spam :Cause they take vengeance of 
such kind of men.")
+
+ (0.03 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :alice: No egma, no riddle, no 
l'envoy; no salve in the mail, sir. O! sir, plantain, a plain plantain: no 
l'envoy, no l'envoy: no salve, sir, but a plantain.")
+ (0.03 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :Signior Iachimo will not 
from it. Pray, let us follow 'em."))
+
+((privmsg 10 "PRIVMSG #spam :three")
+ ;; Third check point.
+ (0.01 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #spam :Moved.")
+ (0.01 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :Ready."))
diff --git a/test/lisp/erc/resources/sasl/plain-failed.eld 
b/test/lisp/erc/resources/sasl/plain-failed.eld
index 336700290c5..47d13de18e5 100644
--- a/test/lisp/erc/resources/sasl/plain-failed.eld
+++ b/test/lisp/erc/resources/sasl/plain-failed.eld
@@ -1,16 +1,16 @@
 ;; -*- mode: lisp-data; -*-
 ((cap-req 10 "CAP REQ :sasl"))
-((nick 1 "NICK tester"))
-((user 1 "USER tester 0 * :tester")
+((nick 10 "NICK tester"))
+((user 10 "USER tester 0 * :tester")
  (0.0 ":irc.foonet.org NOTICE * :*** Looking up your hostname...")
  (0.0 ":irc.foonet.org NOTICE * :*** Found your hostname")
  (0.0 ":irc.foonet.org CAP * ACK :cap-notify sasl"))
 
-((authenticate-plain 3.2 "AUTHENTICATE PLAIN")
+((authenticate-plain 10 "AUTHENTICATE PLAIN")
  (0.0 ":irc.foonet.org AUTHENTICATE +"))
 
-((authenticate-gimme 3.2 "AUTHENTICATE AHRlc3RlcgB3cm9uZw==")
+((authenticate-gimme 10 "AUTHENTICATE AHRlc3RlcgB3cm9uZw==")
  (0.0 ":irc.foonet.org 900 * * tester :You are now logged in as tester")
  (0.0 ":irc.foonet.org 904 * :SASL authentication failed: Invalid account 
credentials"))
 
-((cap-end 3.2 "CAP END"))
+((eof 10 EOF))
diff --git a/test/lisp/eshell/em-alias-tests.el 
b/test/lisp/eshell/em-alias-tests.el
index ec1704545a4..b70ca185730 100644
--- a/test/lisp/eshell/em-alias-tests.el
+++ b/test/lisp/eshell/em-alias-tests.el
@@ -1,6 +1,6 @@
 ;;; em-alias-tests.el --- em-alias test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/eshell/em-basic-tests.el 
b/test/lisp/eshell/em-basic-tests.el
index 6ac7226ffa0..ebb91cdeea0 100644
--- a/test/lisp/eshell/em-basic-tests.el
+++ b/test/lisp/eshell/em-basic-tests.el
@@ -1,6 +1,6 @@
 ;;; em-basic-tests.el --- em-basic test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -33,7 +33,7 @@
 
 ;;; Tests:
 
-(ert-deftest em-basic-test/umask-print-numeric ()
+(ert-deftest em-basic-test/umask/print-numeric ()
   "Test printing umask numerically."
   (cl-letf (((symbol-function 'default-file-modes) (lambda () #o775)))
     (eshell-command-result-equal "umask" "002\n"))
@@ -43,7 +43,7 @@
   (cl-letf (((symbol-function 'default-file-modes) (lambda () #o1775)))
     (eshell-command-result-equal "umask" "002\n")))
 
-(ert-deftest em-basic-test/umask-read-symbolic ()
+(ert-deftest em-basic-test/umask/print-symbolic ()
   "Test printing umask symbolically."
   (cl-letf (((symbol-function 'default-file-modes) (lambda () #o775)))
     (eshell-command-result-equal "umask -S"
@@ -56,8 +56,8 @@
     (eshell-command-result-equal "umask -S"
                                  "u=rwx,g=rwx,o=rx\n")))
 
-(ert-deftest em-basic-test/umask-set ()
-  "Test setting umask."
+(ert-deftest em-basic-test/umask/set-numeric ()
+  "Test setting umask numerically."
   (let ((file-modes 0))
     (cl-letf (((symbol-function 'set-default-file-modes)
                (lambda (mode) (setq file-modes mode))))
@@ -68,4 +68,30 @@
       (eshell-test-command-result "umask $(identity #o222)")
       (should (= file-modes #o555)))))
 
+(ert-deftest em-basic-test/umask/set-symbolic ()
+  "Test setting umask symbolically."
+  (let ((file-modes 0))
+    (cl-letf (((symbol-function 'default-file-modes)
+               (lambda() file-modes))
+              ((symbol-function 'set-default-file-modes)
+               (lambda (mode) (setq file-modes mode))))
+      (eshell-test-command-result "umask u=rwx,g=rwx,o=rx")
+      (should (= file-modes #o775))
+      (eshell-test-command-result "umask u=rw,g=rx,o=x")
+      (should (= file-modes #o651))
+      (eshell-test-command-result "umask u+x,o-x")
+      (should (= file-modes #o750))
+      (eshell-test-command-result "umask a+rx")
+      (should (= file-modes #o755)))))
+
+(ert-deftest em-basic-test/umask/set-with-S ()
+  "Test that passing \"-S\" and a umask still sets the umask."
+  (let ((file-modes 0))
+    (cl-letf (((symbol-function 'set-default-file-modes)
+               (lambda (mode) (setq file-modes mode))))
+      (eshell-test-command-result "umask -S 002")
+      (should (= file-modes #o775))
+      (eshell-test-command-result "umask -S 123")
+      (should (= file-modes #o654)))))
+
 ;; em-basic-tests.el ends here
diff --git a/test/lisp/eshell/em-cmpl-tests.el 
b/test/lisp/eshell/em-cmpl-tests.el
index dd3c338ac54..f778816c4e1 100644
--- a/test/lisp/eshell/em-cmpl-tests.el
+++ b/test/lisp/eshell/em-cmpl-tests.el
@@ -1,6 +1,6 @@
 ;;; em-cmpl-tests.el --- em-cmpl test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -175,18 +175,18 @@ ACTUAL and EXPECTED should both be lists of strings."
    (ert-with-temp-directory default-directory
      (write-region nil nil (expand-file-name "file.txt"))
      (write-region nil nil (expand-file-name "file.el"))
+     ;; Complete the first time.  This should insert the common prefix
+     ;; of our completions.
      (should (equal (eshell-insert-and-complete "echo fi")
                     "echo file."))
+     ;; Make sure the completions buffer isn't displayed.
+     (should-not (get-buffer-window "*Completions*"))
      ;; 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")))))))
+     ;; This time, we should display the completions buffer.
+     (should (get-buffer-window "*Completions*")))))
 
 (ert-deftest em-cmpl-test/file-completion/glob ()
   "Test completion of file names using a glob."
diff --git a/test/lisp/eshell/em-dirs-tests.el 
b/test/lisp/eshell/em-dirs-tests.el
index 9864b72ba78..9789e519f4c 100644
--- a/test/lisp/eshell/em-dirs-tests.el
+++ b/test/lisp/eshell/em-dirs-tests.el
@@ -1,6 +1,6 @@
 ;;; em-dirs-tests.el --- em-dirs test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -34,6 +34,9 @@
                                                     default-directory))))
 ;;; Tests:
 
+
+;; Variables
+
 (ert-deftest em-dirs-test/pwd-var ()
   "Test using the $PWD variable."
   (let ((default-directory "/some/path"))
@@ -99,6 +102,25 @@
      (eshell-match-command-output "echo $-[1][/ 1 3]"
                                   "(\"some\" \"here\")\n"))))
 
+
+;; Argument expansion
+
+(ert-deftest em-dirs-test/expand-user-reference/local ()
+  "Test expansion of \"~USER\" references."
+  (eshell-command-result-equal "echo ~" (expand-file-name "~"))
+  (eshell-command-result-equal
+   (format "echo ~%s" user-login-name)
+   (expand-file-name (format "~%s" user-login-name))))
+
+(ert-deftest em-dirs-test/expand-user-reference/quoted ()
+  "Test that a quoted \"~\" isn't expanded."
+  (eshell-command-result-equal "echo \\~" "~")
+  (eshell-command-result-equal "echo \"~\"" "~")
+  (eshell-command-result-equal "echo '~'" "~"))
+
+
+;; `cd'
+
 (ert-deftest em-dirs-test/cd ()
   "Test that changing directories with `cd' works."
   (ert-with-temp-directory tmpdir
diff --git a/test/lisp/eshell/em-extpipe-tests.el 
b/test/lisp/eshell/em-extpipe-tests.el
index 6984ec2de59..610e3d41524 100644
--- a/test/lisp/eshell/em-extpipe-tests.el
+++ b/test/lisp/eshell/em-extpipe-tests.el
@@ -1,6 +1,6 @@
 ;;; em-extpipe-tests.el --- em-extpipe test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Sean Whitton <spwhitton@spwhitton.name>
 
diff --git a/test/lisp/eshell/em-glob-tests.el 
b/test/lisp/eshell/em-glob-tests.el
index 6e07225657c..6d922666ea3 100644
--- a/test/lisp/eshell/em-glob-tests.el
+++ b/test/lisp/eshell/em-glob-tests.el
@@ -1,6 +1,6 @@
 ;;; em-glob-tests.el --- em-glob test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/eshell/em-hist-tests.el 
b/test/lisp/eshell/em-hist-tests.el
index 466d19cc6f7..a4e1e01b124 100644
--- a/test/lisp/eshell/em-hist-tests.el
+++ b/test/lisp/eshell/em-hist-tests.el
@@ -1,6 +1,6 @@
 ;;; em-hist-tests.el --- em-hist test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -35,7 +35,7 @@
 (cl-defun em-hist-test/check-history-file (file-name expected &optional
                                                      (expected-ring t))
   "Check that the contents of FILE-NAME match the EXPECTED history entries.
-Additonally, check that after loading the file, the history ring
+Additionally, check that after loading the file, the history ring
 matches too.  If EXPECTED-RING is a list, compare the ring
 elements against that; if t (the default), check against EXPECTED."
   (when (eq expected-ring t) (setq expected-ring expected))
diff --git a/test/lisp/eshell/em-ls-tests.el b/test/lisp/eshell/em-ls-tests.el
index 862a6dfd9f8..347716a577f 100644
--- a/test/lisp/eshell/em-ls-tests.el
+++ b/test/lisp/eshell/em-ls-tests.el
@@ -1,6 +1,6 @@
 ;;; em-ls-tests.el --- em-ls test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Tino Calancha <tino.calancha@gmail.com>
 
diff --git a/test/lisp/eshell/em-pred-tests.el 
b/test/lisp/eshell/em-pred-tests.el
index adc4ac01eb1..3bffc918b66 100644
--- a/test/lisp/eshell/em-pred-tests.el
+++ b/test/lisp/eshell/em-pred-tests.el
@@ -1,6 +1,6 @@
 ;;; em-pred-tests.el --- em-pred test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/eshell/em-prompt-tests.el 
b/test/lisp/eshell/em-prompt-tests.el
index 46e74e64983..964609e6410 100644
--- a/test/lisp/eshell/em-prompt-tests.el
+++ b/test/lisp/eshell/em-prompt-tests.el
@@ -1,6 +1,6 @@
 ;;; em-prompt-tests.el --- em-prompt test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/eshell/em-script-tests.el 
b/test/lisp/eshell/em-script-tests.el
index 02e4125d827..f77c4568ea8 100644
--- a/test/lisp/eshell/em-script-tests.el
+++ b/test/lisp/eshell/em-script-tests.el
@@ -1,6 +1,6 @@
 ;;; em-script-tests.el --- em-script test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/eshell/em-tramp-tests.el 
b/test/lisp/eshell/em-tramp-tests.el
index a3bda970b63..3be5d3542ca 100644
--- a/test/lisp/eshell/em-tramp-tests.el
+++ b/test/lisp/eshell/em-tramp-tests.el
@@ -1,6 +1,6 @@
 ;;; em-tramp-tests.el --- em-tramp test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -59,35 +59,31 @@
         "cd"
         (list ,(format "/su:root@%s:~/" tramp-default-host))))))
 
-(defun mock-eshell-named-command (&rest args)
-  "Dummy function to test Eshell `sudo' command rewriting."
-  (list default-directory args))
-
 (ert-deftest em-tramp-test/sudo-basic ()
   "Test Eshell `sudo' command with default user."
-  (cl-letf (((symbol-function 'eshell-named-command)
-             #'mock-eshell-named-command))
-    (should (equal
-             (catch 'eshell-external (eshell/sudo "echo" "hi"))
-             `(,(format "/sudo:root@%s:%s" tramp-default-host 
default-directory)
-               ("echo" ("hi")))))
-    (should (equal
-             (catch 'eshell-external (eshell/sudo "echo" "-u" "hi"))
-             `(,(format "/sudo:root@%s:%s" tramp-default-host 
default-directory)
-               ("echo" ("-u" "hi")))))))
+  (let ((sudo-directory (format "/sudo:root@%s:%s"
+                                tramp-default-host default-directory)))
+    (should (equal (catch 'eshell-replace-command
+                     (eshell/sudo "echo" "hi"))
+                   `(let ((default-directory ,sudo-directory))
+                      (eshell-named-command '"echo" '("hi")))))
+    (should (equal (catch 'eshell-replace-command
+                     (eshell/sudo "echo" "-u" "hi"))
+                   `(let ((default-directory ,sudo-directory))
+                      (eshell-named-command '"echo" '("-u" "hi")))))))
 
 (ert-deftest em-tramp-test/sudo-user ()
   "Test Eshell `sudo' command with specified user."
-  (cl-letf (((symbol-function 'eshell-named-command)
-             #'mock-eshell-named-command))
-    (should (equal
-             (catch 'eshell-external (eshell/sudo "-u" "USER" "echo" "hi"))
-             `(,(format "/sudo:USER@%s:%s" tramp-default-host 
default-directory)
-               ("echo" ("hi")))))
-    (should (equal
-             (catch 'eshell-external (eshell/sudo "-u" "USER" "echo" "-u" 
"hi"))
-             `(,(format "/sudo:USER@%s:%s" tramp-default-host 
default-directory)
-               ("echo" ("-u" "hi")))))))
+  (let ((sudo-directory (format "/sudo:USER@%s:%s"
+                                tramp-default-host default-directory)))
+    (should (equal (catch 'eshell-replace-command
+                     (eshell/sudo "-u" "USER" "echo" "hi"))
+                   `(let ((default-directory ,sudo-directory))
+                      (eshell-named-command '"echo" '("hi")))))
+    (should (equal (catch 'eshell-replace-command
+                     (eshell/sudo "-u" "USER" "echo" "-u" "hi"))
+                   `(let ((default-directory ,sudo-directory))
+                      (eshell-named-command '"echo" '("-u" "hi")))))))
 
 (ert-deftest em-tramp-test/sudo-shell ()
   "Test Eshell `sudo' command with -s/--shell option."
@@ -109,34 +105,29 @@
 
 (ert-deftest em-tramp-test/doas-basic ()
   "Test Eshell `doas' command with default user."
-  (cl-letf (((symbol-function 'eshell-named-command)
-             #'mock-eshell-named-command))
-    (should (equal
-             (catch 'eshell-external (eshell/doas "echo" "hi"))
-             `(,(format "/doas:root@%s:%s"
-                        tramp-default-host default-directory)
-               ("echo" ("hi")))))
-    (should (equal
-             (catch 'eshell-external (eshell/doas "echo" "-u" "hi"))
-             `(,(format "/doas:root@%s:%s"
-                        tramp-default-host default-directory)
-               ("echo" ("-u" "hi")))))))
+  (let ((doas-directory (format "/doas:root@%s:%s"
+                                tramp-default-host default-directory)))
+    (should (equal (catch 'eshell-replace-command
+                     (eshell/doas "echo" "hi"))
+                   `(let ((default-directory ,doas-directory))
+                      (eshell-named-command '"echo" '("hi")))))
+    (should (equal (catch 'eshell-replace-command
+                     (eshell/doas "echo" "-u" "hi"))
+                   `(let ((default-directory ,doas-directory))
+                      (eshell-named-command '"echo" '("-u" "hi")))))))
 
 (ert-deftest em-tramp-test/doas-user ()
   "Test Eshell `doas' command with specified user."
-  (cl-letf (((symbol-function 'eshell-named-command)
-             #'mock-eshell-named-command))
-    (should (equal
-             (catch 'eshell-external (eshell/doas "-u" "USER" "echo" "hi"))
-             `(,(format "/doas:USER@%s:%s"
-                        tramp-default-host default-directory)
-               ("echo" ("hi")))))
-    (should (equal
-             (catch 'eshell-external
-               (eshell/doas "-u" "USER" "echo" "-u" "hi"))
-             `(,(format "/doas:USER@%s:%s"
-                        tramp-default-host default-directory)
-               ("echo" ("-u" "hi")))))))
+  (let ((doas-directory (format "/doas:USER@%s:%s"
+                                tramp-default-host default-directory)))
+    (should (equal (catch 'eshell-replace-command
+                     (eshell/doas "-u" "USER" "echo" "hi"))
+                   `(let ((default-directory ,doas-directory))
+                      (eshell-named-command '"echo" '("hi")))))
+    (should (equal (catch 'eshell-replace-command
+                     (eshell/doas "-u" "USER" "echo" "-u" "hi"))
+                   `(let ((default-directory ,doas-directory))
+                      (eshell-named-command '"echo" '("-u" "hi")))))))
 
 (ert-deftest em-tramp-test/doas-shell ()
   "Test Eshell `doas' command with -s/--shell option."
diff --git a/test/lisp/eshell/em-unix-tests.el 
b/test/lisp/eshell/em-unix-tests.el
index d7b6c55fe45..a92c7d3f80a 100644
--- a/test/lisp/eshell/em-unix-tests.el
+++ b/test/lisp/eshell/em-unix-tests.el
@@ -1,6 +1,6 @@
 ;;; em-unix-tests.el --- em-unix test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/eshell/esh-arg-tests.el 
b/test/lisp/eshell/esh-arg-tests.el
index 1eb8e08b883..b748c5ab4c0 100644
--- a/test/lisp/eshell/esh-arg-tests.el
+++ b/test/lisp/eshell/esh-arg-tests.el
@@ -1,6 +1,6 @@
 ;;; esh-arg-tests.el --- esh-arg test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -60,13 +60,17 @@ chars."
                                 "he\\\\llo\n")))
 
 (ert-deftest esh-arg-test/escape/newline ()
-  "Test that an escaped newline is equivalent to the empty string.
-When newlines are *nonspecial*, an escaped newline should be
-treated as just a newline."
+  "Test that an escaped newline is equivalent to the empty string."
   (with-temp-eshell
    (eshell-match-command-output "echo hi\\\nthere"
                                 "hithere\n")))
 
+(ert-deftest esh-arg-test/escape/trailing-newline ()
+  "Test that an escaped newline is equivalent to the empty string."
+  (with-temp-eshell
+   (eshell-match-command-output "echo hi\\\n"
+                                "hi\n")))
+
 (ert-deftest esh-arg-test/escape/newline-conditional ()
   "Test invocation of an if/else statement using line continuations."
   (let ((eshell-test-value t))
@@ -95,9 +99,7 @@ chars."
                                 "\\\"hi\\\\\n")))
 
 (ert-deftest esh-arg-test/escape-quoted/newline ()
-  "Test that an escaped newline is equivalent to the empty string.
-When newlines are *nonspecial*, an escaped newline should be
-treated literally, as a backslash and a newline."
+  "Test that an escaped newline is equivalent to the empty string."
   (with-temp-eshell
    (eshell-match-command-output "echo \"hi\\\nthere\""
                                 "hithere\n")))
diff --git a/test/lisp/eshell/esh-cmd-tests.el 
b/test/lisp/eshell/esh-cmd-tests.el
index e0783b26ad6..ef965a896c1 100644
--- a/test/lisp/eshell/esh-cmd-tests.el
+++ b/test/lisp/eshell/esh-cmd-tests.el
@@ -1,6 +1,6 @@
 ;;; esh-cmd-tests.el --- esh-cmd test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -469,6 +469,28 @@ This tests when `eshell-lisp-form-nil-is-failure' is nil."
                                "no"))
 
 
+;; Direct invocation
+
+(defmacro esh-cmd-test--deftest-invoke-directly (name command expected)
+  "Test `eshell-invoke-directly-p' returns EXPECTED for COMMAND.
+NAME is the name of the test case."
+  (declare (indent 2))
+  `(ert-deftest ,(intern (concat "esh-cmd-test/invoke-directly/"
+                                 (symbol-name name)))
+       ()
+     (with-temp-eshell
+      (should (equal (eshell-invoke-directly-p
+                      (eshell-parse-command ,command nil t))
+                     ,expected)))))
+
+(esh-cmd-test--deftest-invoke-directly no-args "echo" t)
+(esh-cmd-test--deftest-invoke-directly with-args "echo hi" t)
+(esh-cmd-test--deftest-invoke-directly multiple-cmds "echo hi; echo bye" nil)
+(esh-cmd-test--deftest-invoke-directly subcmd "echo ${echo hi}" t)
+(esh-cmd-test--deftest-invoke-directly complex "ls ." nil)
+(esh-cmd-test--deftest-invoke-directly complex-subcmd "echo {ls .}" nil)
+
+
 ;; Error handling
 
 (ert-deftest esh-cmd-test/throw ()
diff --git a/test/lisp/eshell/esh-ext-tests.el 
b/test/lisp/eshell/esh-ext-tests.el
index aae297cd413..8abbd74f737 100644
--- a/test/lisp/eshell/esh-ext-tests.el
+++ b/test/lisp/eshell/esh-ext-tests.el
@@ -1,6 +1,6 @@
 ;;; esh-ext-tests.el --- esh-ext test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/eshell/esh-io-tests.el b/test/lisp/eshell/esh-io-tests.el
index 0201b6ab650..188570161c7 100644
--- a/test/lisp/eshell/esh-io-tests.el
+++ b/test/lisp/eshell/esh-io-tests.el
@@ -1,6 +1,6 @@
 ;;; esh-io-tests.el --- esh-io test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -328,7 +328,7 @@ stdout originally pointed (the terminal)."
                                "tuodts\nrredts\n"))
 
 (ert-deftest esh-io-test/pipeline/subcommands ()
-  "Chek that all commands in a subcommand are properly piped."
+  "Check that all commands in a subcommand are properly piped."
   (skip-unless (executable-find "rev"))
   (with-temp-eshell
    (eshell-match-command-output "{echo foo; echo bar} | rev"
diff --git a/test/lisp/eshell/esh-opt-tests.el 
b/test/lisp/eshell/esh-opt-tests.el
index f4529ed4f22..8d6e0c1e426 100644
--- a/test/lisp/eshell/esh-opt-tests.el
+++ b/test/lisp/eshell/esh-opt-tests.el
@@ -1,6 +1,6 @@
 ;;; esh-opt-tests.el --- esh-opt test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/eshell/esh-proc-tests.el 
b/test/lisp/eshell/esh-proc-tests.el
index 9118bcd1c61..63fb8f46dfa 100644
--- a/test/lisp/eshell/esh-proc-tests.el
+++ b/test/lisp/eshell/esh-proc-tests.el
@@ -1,6 +1,6 @@
 ;;; esh-proc-tests.el --- esh-proc test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/eshell/esh-util-tests.el 
b/test/lisp/eshell/esh-util-tests.el
index 7bd71b260ff..71a047b1801 100644
--- a/test/lisp/eshell/esh-util-tests.el
+++ b/test/lisp/eshell/esh-util-tests.el
@@ -1,6 +1,6 @@
 ;;; esh-util-tests.el --- esh-util test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/eshell/esh-var-tests.el 
b/test/lisp/eshell/esh-var-tests.el
index 83c0f480627..b94e8a276d7 100644
--- a/test/lisp/eshell/esh-var-tests.el
+++ b/test/lisp/eshell/esh-var-tests.el
@@ -1,6 +1,6 @@
 ;;; esh-var-tests.el --- esh-var test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -653,6 +653,21 @@ nil, use FUNCTION instead."
                                 "VAR=hello\n")
    (should (equal (getenv "VAR") "value"))))
 
+(ert-deftest esh-var-test/local-variables/cd ()
+  "Test that \"VAR=value cd DIR\" properly changes the directory."
+  (let ((parent-directory (file-name-directory
+                           (directory-file-name default-directory))))
+    (with-temp-eshell
+     (eshell-insert-command "VAR=hello cd ..")
+     (should (equal default-directory parent-directory)))))
+
+(ert-deftest esh-var-test/local-variables/env ()
+  "Test that \"env VAR=value command\" temporarily sets variables."
+  (with-temp-eshell
+   (push "VAR=value" process-environment)
+   (eshell-match-command-output "env VAR=hello env" "VAR=hello\n")
+   (should (equal (getenv "VAR") "value"))))
+
 
 ;; Variable aliases
 
diff --git a/test/lisp/eshell/eshell-tests-helpers.el 
b/test/lisp/eshell/eshell-tests-helpers.el
index c983c8fd2bb..652146fefcc 100644
--- a/test/lisp/eshell/eshell-tests-helpers.el
+++ b/test/lisp/eshell/eshell-tests-helpers.el
@@ -1,6 +1,6 @@
 ;;; eshell-tests-helpers.el --- Eshell test suite helpers  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/test/lisp/eshell/eshell-tests-unload.el 
b/test/lisp/eshell/eshell-tests-unload.el
index cdd58efef18..bf8291ba47a 100644
--- a/test/lisp/eshell/eshell-tests-unload.el
+++ b/test/lisp/eshell/eshell-tests-unload.el
@@ -1,6 +1,6 @@
 ;;; eshell-tests-unload.el --- test unloading Eshell  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el
index d2ef44ae507..e01e033e25e 100644
--- a/test/lisp/eshell/eshell-tests.el
+++ b/test/lisp/eshell/eshell-tests.el
@@ -1,6 +1,6 @@
 ;;; eshell-tests.el --- Eshell test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
diff --git a/test/lisp/faces-resources/faces-test-dark-theme.el 
b/test/lisp/faces-resources/faces-test-dark-theme.el
index c73a8823a09..6c7492c4a7e 100644
--- a/test/lisp/faces-resources/faces-test-dark-theme.el
+++ b/test/lisp/faces-resources/faces-test-dark-theme.el
@@ -1,6 +1,6 @@
 ;;; faces-test-dark-theme.el --- A dark theme from tests ;;; -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/faces-resources/faces-test-light-theme.el 
b/test/lisp/faces-resources/faces-test-light-theme.el
index acbc54d769b..76e485d3176 100644
--- a/test/lisp/faces-resources/faces-test-light-theme.el
+++ b/test/lisp/faces-resources/faces-test-light-theme.el
@@ -1,6 +1,6 @@
 ;;; faces-test-light-theme.el --- A dark theme from tests ;;; -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/faces-tests.el b/test/lisp/faces-tests.el
index 2c772a27f74..529eb846bbd 100644
--- a/test/lisp/faces-tests.el
+++ b/test/lisp/faces-tests.el
@@ -1,6 +1,6 @@
 ;;; faces-tests.el --- Tests for faces.el            -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/ffap-tests.el b/test/lisp/ffap-tests.el
index a47e1900ae4..593d2d42af6 100644
--- a/test/lisp/ffap-tests.el
+++ b/test/lisp/ffap-tests.el
@@ -1,6 +1,6 @@
 ;;; ffap-tests.el --- Test suite for ffap.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Tino Calancha <tino.calancha@gmail.com>
 
diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el
index eb485a10a92..11af1f75574 100644
--- a/test/lisp/filenotify-tests.el
+++ b/test/lisp/filenotify-tests.el
@@ -1,6 +1,6 @@
 ;;; filenotify-tests.el --- Tests of file notifications  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index 3e499fff468..718ecd51f8b 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -1,6 +1,6 @@
 ;;; files-tests.el --- tests for files.el.  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -2101,5 +2101,9 @@ Prompt users for any modified buffer with 
`buffer-offer-save' non-nil."
       (should (documentation 'bar))
       (should (documentation 'zot)))))
 
+(ert-deftest files-tests--expand-wildcards ()
+  (should (file-expand-wildcards
+           (concat (directory-file-name default-directory) "*/"))))
+
 (provide 'files-tests)
 ;;; files-tests.el ends here
diff --git a/test/lisp/files-x-tests.el b/test/lisp/files-x-tests.el
index 4e14ae68fb8..528467a5641 100644
--- a/test/lisp/files-x-tests.el
+++ b/test/lisp/files-x-tests.el
@@ -1,6 +1,6 @@
 ;;; files-x-tests.el --- tests for files-x.el.  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 
@@ -39,6 +39,7 @@
 (defconst files-x-test--variables5
   '((remote-lazy-var . nil)
     (remote-null-device . "/dev/null")))
+(defvar remote-shell-file-name)
 (defvar remote-null-device)
 (defvar remote-lazy-var nil)
 (put 'remote-shell-file-name 'safe-local-variable #'identity)
@@ -482,5 +483,123 @@ If it's not initialized yet, initialize it."
      `(connection-local-profile-alist ',clpa now)
      `(connection-local-criteria-alist ',clca now))))
 
+(ert-deftest files-x-test-connection-local-value ()
+  "Test getting connection-local values."
+
+  (let ((clpa connection-local-profile-alist)
+       (clca connection-local-criteria-alist))
+    (connection-local-set-profile-variables
+     'remote-bash files-x-test--variables1)
+    (connection-local-set-profile-variables
+     'remote-ksh files-x-test--variables2)
+    (connection-local-set-profile-variables
+     'remote-nullfile files-x-test--variables3)
+
+    (connection-local-set-profiles
+     nil 'remote-ksh 'remote-nullfile)
+
+    (connection-local-set-profile-variables
+     'remote-lazy files-x-test--variables5)
+    (connection-local-set-profiles
+     files-x-test--application 'remote-lazy 'remote-bash)
+
+    (with-temp-buffer
+      ;; We need a remote `default-directory'.
+      (let ((enable-connection-local-variables t)
+           (default-directory "/method:host:")
+           (remote-null-device "null"))
+        (should-not connection-local-variables-alist)
+        (should-not (local-variable-p 'remote-shell-file-name))
+        (should-not (local-variable-p 'remote-null-device))
+        (should-not (boundp 'remote-shell-file-name))
+        (should (string-equal (symbol-value 'remote-null-device) "null"))
+
+        ;; The proper variable values are set.
+        (should (connection-local-p remote-shell-file-name))
+        (should
+         (string-equal
+          (connection-local-value remote-shell-file-name) "/bin/ksh"))
+        (should (connection-local-p remote-null-device))
+        (should
+         (string-equal
+          (connection-local-value remote-null-device) "/dev/null"))
+        (should-not (connection-local-p remote-lazy-var))
+
+        ;; Run with a different application.
+        (should
+         (connection-local-p
+          remote-shell-file-name (cadr files-x-test--application)))
+        (should
+         (string-equal
+          (connection-local-value
+           remote-shell-file-name (cadr files-x-test--application))
+          "/bin/bash"))
+        (should
+         (connection-local-p
+          remote-null-device (cadr files-x-test--application)))
+        (should
+         (string-equal
+          (connection-local-value
+           remote-null-device (cadr files-x-test--application))
+          "/dev/null"))
+        (should
+         (connection-local-p
+          remote-lazy-var (cadr files-x-test--application)))
+
+        ;; The previous bindings haven't changed.
+        (should-not connection-local-variables-alist)
+        (should-not (local-variable-p 'remote-shell-file-name))
+        (should-not (local-variable-p 'remote-null-device))
+        (should-not (boundp 'remote-shell-file-name))
+        (should (string-equal (symbol-value 'remote-null-device) "null"))))
+
+    ;; `connection-local-value' and `connection-local-p' care about a
+    ;; local default directory.
+    (with-temp-buffer
+      (let ((enable-connection-local-variables t)
+           (default-directory temporary-file-directory)
+           (remote-null-device "null"))
+        (should-not connection-local-variables-alist)
+        (should-not (local-variable-p 'remote-shell-file-name))
+        (should-not (local-variable-p 'remote-null-device))
+        (should-not (boundp 'remote-shell-file-name))
+        (should (string-equal (symbol-value 'remote-null-device) "null"))
+
+        ;; The recent variable values are used.
+        (should-not (connection-local-p remote-shell-file-name))
+        ;; `remote-shell-file-name' is not defined, so we get an error.
+        (should-error
+         (connection-local-value remote-shell-file-name) :type 'void-variable)
+        (should-not (connection-local-p remote-null-device))
+        (should
+         (string-equal
+          (connection-local-value remote-null-device) remote-null-device))
+        (should-not (connection-local-p remote-lazy-var))
+
+        ;; Run with a different application.
+        (should-not
+         (connection-local-p
+          remote-shell-file-name (cadr files-x-test--application)))
+        ;; `remote-shell-file-name' is not defined, so we get an error.
+        (should-error
+         (connection-local-value
+          remote-shell-file-name (cadr files-x-test--application))
+         :type 'void-variable)
+        (should-not
+         (connection-local-p
+          remote-null-device (cadr files-x-test--application)))
+        (should
+         (string-equal
+          (connection-local-value
+           remote-null-device (cadr files-x-test--application))
+          remote-null-device))
+        (should-not
+         (connection-local-p remote-lazy-var (cadr 
files-x-test--application)))))
+
+    ;; Cleanup.
+    (custom-set-variables
+     `(connection-local-profile-alist ',clpa now)
+     `(connection-local-criteria-alist ',clca now))))
+
 (provide 'files-x-tests)
 ;;; files-x-tests.el ends here
diff --git a/test/lisp/find-cmd-tests.el b/test/lisp/find-cmd-tests.el
index 3fbd0fc4ea3..d1c57cc4cfa 100644
--- a/test/lisp/find-cmd-tests.el
+++ b/test/lisp/find-cmd-tests.el
@@ -1,6 +1,6 @@
 ;;; find-cmd-tests.el --- tests for find-cmd.el.  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/font-lock-tests.el b/test/lisp/font-lock-tests.el
index a4cfc19a770..d29b17d934a 100644
--- a/test/lisp/font-lock-tests.el
+++ b/test/lisp/font-lock-tests.el
@@ -1,6 +1,6 @@
 ;;; font-lock-tests.el --- Test suite for font-lock. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/format-spec-tests.el b/test/lisp/format-spec-tests.el
index 31399f37250..48866ed1066 100644
--- a/test/lisp/format-spec-tests.el
+++ b/test/lisp/format-spec-tests.el
@@ -1,6 +1,6 @@
 ;;; format-spec-tests.el --- tests for format-spec.el -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/gnus/gnus-group-tests.el 
b/test/lisp/gnus/gnus-group-tests.el
index 3f5cbefc6ea..13301650e18 100644
--- a/test/lisp/gnus/gnus-group-tests.el
+++ b/test/lisp/gnus/gnus-group-tests.el
@@ -1,6 +1,6 @@
 ;;; gnus-group-tests.el --- Tests for gnus-group.el  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/gnus/gnus-icalendar-tests.el 
b/test/lisp/gnus/gnus-icalendar-tests.el
index 8f89e8f00ab..08c85013d17 100644
--- a/test/lisp/gnus/gnus-icalendar-tests.el
+++ b/test/lisp/gnus/gnus-icalendar-tests.el
@@ -1,6 +1,6 @@
 ;;; gnus-icalendar-tests.el --- tests                -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Jan Tatarik <jan.tatarik@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/gnus/gnus-search-tests.el 
b/test/lisp/gnus/gnus-search-tests.el
index dbbe5089817..e10e31df573 100644
--- a/test/lisp/gnus/gnus-search-tests.el
+++ b/test/lisp/gnus/gnus-search-tests.el
@@ -1,6 +1,6 @@
 ;;; gnus-search-tests.el --- Tests for Gnus' search routines  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2017, 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017, 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Abrahamsen <eric@ericabrahamsen.net>
 ;; Keywords:
diff --git a/test/lisp/gnus/gnus-test-headers.el 
b/test/lisp/gnus/gnus-test-headers.el
index 936665fd1f8..7eeaf9c31c0 100644
--- a/test/lisp/gnus/gnus-test-headers.el
+++ b/test/lisp/gnus/gnus-test-headers.el
@@ -1,6 +1,6 @@
 ;;; gnus-test-headers.el --- Tests for Gnus header-related functions  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric Abrahamsen <eric@ericabrahamsen.net>
 
diff --git a/test/lisp/gnus/gnus-tests.el b/test/lisp/gnus/gnus-tests.el
index f50888e2077..2bd9fb3dff7 100644
--- a/test/lisp/gnus/gnus-tests.el
+++ b/test/lisp/gnus/gnus-tests.el
@@ -1,6 +1,6 @@
 ;;; gnus-tests.el --- Wrapper for the Gnus tests  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Teodor Zlatanov <tzz@lifelogs.com>
 
diff --git a/test/lisp/gnus/gnus-util-tests.el 
b/test/lisp/gnus/gnus-util-tests.el
index 4b904ca6f1d..c5bf17523c2 100644
--- a/test/lisp/gnus/gnus-util-tests.el
+++ b/test/lisp/gnus/gnus-util-tests.el
@@ -1,5 +1,5 @@
 ;;; gnus-util-tests.el --- Selectived tests only.  -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Jens Lechtenbörger <jens.lechtenboerger@fsfe.org>
 
diff --git a/test/lisp/gnus/message-tests.el b/test/lisp/gnus/message-tests.el
index 0844839c366..7f30a612126 100644
--- a/test/lisp/gnus/message-tests.el
+++ b/test/lisp/gnus/message-tests.el
@@ -1,6 +1,6 @@
 ;;; message-tests.el --- Tests for message-mode  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: João Távora <joaotavora@gmail.com>
 
diff --git a/test/lisp/gnus/mm-decode-tests.el 
b/test/lisp/gnus/mm-decode-tests.el
index e60295e21e7..27b3b85a053 100644
--- a/test/lisp/gnus/mm-decode-tests.el
+++ b/test/lisp/gnus/mm-decode-tests.el
@@ -1,6 +1,6 @@
 ;;; mm-decode-tests.el ---  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/gnus/mml-sec-tests.el b/test/lisp/gnus/mml-sec-tests.el
index a5dadf21c8c..2a18a13ba38 100644
--- a/test/lisp/gnus/mml-sec-tests.el
+++ b/test/lisp/gnus/mml-sec-tests.el
@@ -1,6 +1,6 @@
 ;;; mml-sec-tests.el --- Tests mml-sec.el, see README-mml-secure.txt.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2015, 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015, 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Jens Lechtenbörger <jens.lechtenboerger@fsfe.org>
 
diff --git a/test/lisp/gnus/nnrss-tests.el b/test/lisp/gnus/nnrss-tests.el
index 57ef8797475..b5bfbce9fb5 100644
--- a/test/lisp/gnus/nnrss-tests.el
+++ b/test/lisp/gnus/nnrss-tests.el
@@ -1,6 +1,6 @@
 ;;; nnrss-tests.el --- tests for gnus/nnrss.el    -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/help-fns-tests.el b/test/lisp/help-fns-tests.el
index 56c521e765e..7035c8b7773 100644
--- a/test/lisp/help-fns-tests.el
+++ b/test/lisp/help-fns-tests.el
@@ -1,6 +1,6 @@
 ;;; help-fns-tests.el --- tests for help-fns.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 
diff --git a/test/lisp/help-mode-tests.el b/test/lisp/help-mode-tests.el
index 30e944f6c80..4c149ae7430 100644
--- a/test/lisp/help-mode-tests.el
+++ b/test/lisp/help-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; help-mode-tests.el --- Tests for help-mode.el    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el
index b0b487ab169..f27fa979ef0 100644
--- a/test/lisp/help-tests.el
+++ b/test/lisp/help-tests.el
@@ -1,6 +1,6 @@
 ;;; help-tests.el --- Tests for help.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Juanma Barranquero <lekktu@gmail.com>
 ;;         Eli Zaretskii <eliz@gnu.org>
diff --git a/test/lisp/hfy-cmap-tests.el b/test/lisp/hfy-cmap-tests.el
index 0d135aa8c36..79656c069c9 100644
--- a/test/lisp/hfy-cmap-tests.el
+++ b/test/lisp/hfy-cmap-tests.el
@@ -1,6 +1,6 @@
 ;;; hfy-cmap-tests.el --- tests for hfy-cmap.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/hi-lock-tests.el b/test/lisp/hi-lock-tests.el
index 794a3b1d0c2..82bce3bef2e 100644
--- a/test/lisp/hi-lock-tests.el
+++ b/test/lisp/hi-lock-tests.el
@@ -1,6 +1,6 @@
 ;;; hi-lock-tests.el --- Tests for hi-lock.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Tino Calancha <tino.calancha@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/hl-line-tests.el b/test/lisp/hl-line-tests.el
index 9c120e0d7ff..1b0b0ebe015 100644
--- a/test/lisp/hl-line-tests.el
+++ b/test/lisp/hl-line-tests.el
@@ -1,6 +1,6 @@
 ;;; hl-line-tests.el --- Test suite for hl-line. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/htmlfontify-tests.el b/test/lisp/htmlfontify-tests.el
index 0a351f0a8a5..e1ae0bf540d 100644
--- a/test/lisp/htmlfontify-tests.el
+++ b/test/lisp/htmlfontify-tests.el
@@ -1,6 +1,6 @@
 ;;; htmlfontify-tests.el --- Test suite. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/ibuffer-tests.el b/test/lisp/ibuffer-tests.el
index ec0ba85da39..ea9e663b1ad 100644
--- a/test/lisp/ibuffer-tests.el
+++ b/test/lisp/ibuffer-tests.el
@@ -1,6 +1,6 @@
 ;;; ibuffer-tests.el --- Test suite. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/ido-tests.el b/test/lisp/ido-tests.el
index 4f753479a06..705f96ac932 100644
--- a/test/lisp/ido-tests.el
+++ b/test/lisp/ido-tests.el
@@ -1,6 +1,6 @@
 ;;; ido-tests.el --- unit tests for ido.el           -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Philipp Stephani <phst@google.com>
 
diff --git a/test/lisp/image-file-tests.el b/test/lisp/image-file-tests.el
index d934867c1cb..1f2d0635343 100644
--- a/test/lisp/image-file-tests.el
+++ b/test/lisp/image-file-tests.el
@@ -1,6 +1,6 @@
 ;;; image-file-tests.el --- Test suite for image-files  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/image-tests.el b/test/lisp/image-tests.el
index cb4821adefc..80142d6d6de 100644
--- a/test/lisp/image-tests.el
+++ b/test/lisp/image-tests.el
@@ -1,6 +1,6 @@
 ;;; image-tests.el --- tests for image.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/image/exif-tests.el b/test/lisp/image/exif-tests.el
index f803565dd62..e4ac55e4c1d 100644
--- a/test/lisp/image/exif-tests.el
+++ b/test/lisp/image/exif-tests.el
@@ -1,6 +1,6 @@
 ;;; exif-tests.el --- tests for exif.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/image/gravatar-tests.el 
b/test/lisp/image/gravatar-tests.el
index 8965be13c5d..edab6845775 100644
--- a/test/lisp/image/gravatar-tests.el
+++ b/test/lisp/image/gravatar-tests.el
@@ -1,6 +1,6 @@
 ;;; gravatar-tests.el --- tests for gravatar.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/image/image-dired-tests.el 
b/test/lisp/image/image-dired-tests.el
index 8a4acf6bd88..f58e1ba74a6 100644
--- a/test/lisp/image/image-dired-tests.el
+++ b/test/lisp/image/image-dired-tests.el
@@ -1,6 +1,6 @@
 ;;; image-dired-tests.el --- Tests for image-dired.el  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/image/image-dired-util-tests.el 
b/test/lisp/image/image-dired-util-tests.el
index 1f3747a82b1..5d3d0a512e6 100644
--- a/test/lisp/image/image-dired-util-tests.el
+++ b/test/lisp/image/image-dired-util-tests.el
@@ -1,6 +1,6 @@
 ;;; image-dired-util-tests.el --- Tests for image-dired.el  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/image/wallpaper-tests.el 
b/test/lisp/image/wallpaper-tests.el
index c4167adbef2..5fad6b12e84 100644
--- a/test/lisp/image/wallpaper-tests.el
+++ b/test/lisp/image/wallpaper-tests.el
@@ -1,6 +1,6 @@
 ;;; wallpaper-tests.el --- tests for wallpaper.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/imenu-tests.el b/test/lisp/imenu-tests.el
index cc6fdd41005..918a23160ae 100644
--- a/test/lisp/imenu-tests.el
+++ b/test/lisp/imenu-tests.el
@@ -1,6 +1,6 @@
 ;;; imenu-tests.el --- Test suite for imenu.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Masatake YAMATO <yamato@redhat.com>
 ;; Keywords: tools convenience
diff --git a/test/lisp/info-tests.el b/test/lisp/info-tests.el
index 9ab00b4b82b..0dfdbf417e8 100644
--- a/test/lisp/info-tests.el
+++ b/test/lisp/info-tests.el
@@ -1,6 +1,6 @@
 ;;; info-tests.el --- Tests for info.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -29,11 +29,17 @@
 
 (ert-deftest test-info-urls ()
   (should (equal (Info-url-for-node "(emacs)Minibuffer")
-                 
"https://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer.html";))
+                 
"https://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer";))
   (should (equal (Info-url-for-node "(emacs)Minibuffer File")
-                 
"https://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer-File.html";))
+                 
"https://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer-File";))
   (should (equal (Info-url-for-node "(elisp)Backups and Auto-Saving")
-                 
"https://www.gnu.org/software/emacs/manual/html_node/elisp/Backups-and-Auto_002dSaving.html";))
-  (should-error (Info-url-for-node "(gnus)Minibuffer File")))
+                 
"https://www.gnu.org/software/emacs/manual/html_node/elisp/Backups-and-Auto_002dSaving";))
+  (should (equal (Info-url-for-node "(eintr)car & cdr")
+                 
"https://www.gnu.org/software/emacs/manual/html_node/eintr/car-_0026-cdr";))
+  (should (equal (Info-url-for-node "(emacs-mime)\tIndex")
+                 
"https://www.gnu.org/software/emacs/manual/html_node/emacs-mime/Index";))
+  (should (equal (Info-url-for-node  "(gnus) Don't Panic")
+                 
"https://www.gnu.org/software/emacs/manual/html_node/gnus/Don_0027t-Panic";))
+  (should-error (Info-url-for-node "(nonexistent)Example")))
 
 ;;; info-tests.el ends here
diff --git a/test/lisp/info-xref-tests.el b/test/lisp/info-xref-tests.el
index 0d98a242b7e..c8eb18501f3 100644
--- a/test/lisp/info-xref-tests.el
+++ b/test/lisp/info-xref-tests.el
@@ -1,6 +1,6 @@
 ;;; info-xref-tests.el --- tests for info-xref.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -92,7 +92,15 @@ text.
 "
             )
     (write-region nil nil file nil 'silent))
-  (should (equal 0 (call-process "makeinfo" file))))
+  (if (and (eq system-type 'windows-nt)
+           (executable-find "sh"))
+      ;; If we are running from MSYS Bash, makeinfo.bat might find the
+      ;; wrong version of Perl, so make sure to run the shell script
+      ;; named just 'makeinfo' instead, because it names the correct
+      ;; Perl.
+      (should (equal 0 (call-process "sh" nil t nil
+                                     "-c" (format "makeinfo '%s'" file))))
+    (should (equal 0 (call-process "makeinfo" file)))))
 
 (ert-deftest info-xref-test-makeinfo ()
   "Test that info-xref can parse basic makeinfo output."
diff --git a/test/lisp/international/ccl-tests.el 
b/test/lisp/international/ccl-tests.el
index dfc090b3320..42862508436 100644
--- a/test/lisp/international/ccl-tests.el
+++ b/test/lisp/international/ccl-tests.el
@@ -1,6 +1,6 @@
 ;;; ccl-tests.el --- unit tests for ccl.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/international/mule-tests.el 
b/test/lisp/international/mule-tests.el
index 4dc099a18af..5c742451a57 100644
--- a/test/lisp/international/mule-tests.el
+++ b/test/lisp/international/mule-tests.el
@@ -1,6 +1,6 @@
 ;;; mule-tests.el --- unit tests for mule.el         -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -49,7 +49,7 @@
                        (kbd "C-x RET c u t f - 8 RET C-u C-u c a b RET")
                      (read-string "prompt:"))))))
 
-;;Bug#65997, ensure that old-names haven't overriden new names.
+;;Bug#65997, ensure that old-names haven't overridden new names.
 (ert-deftest mule-cmds-tests--ucs-names-old-name-override ()
   (let (code-points)
     (dotimes (u (1+ (max-char 'ucs)))
diff --git a/test/lisp/international/mule-util-tests.el 
b/test/lisp/international/mule-util-tests.el
index 848909985b2..cebcbd7ce33 100644
--- a/test/lisp/international/mule-util-tests.el
+++ b/test/lisp/international/mule-util-tests.el
@@ -1,6 +1,6 @@
 ;;; mule-util-tests.el --- tests for international/mule-util.el  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/international/textsec-tests.el 
b/test/lisp/international/textsec-tests.el
index b9243cff875..edfaff5f74b 100644
--- a/test/lisp/international/textsec-tests.el
+++ b/test/lisp/international/textsec-tests.el
@@ -1,6 +1,6 @@
 ;;; textsec-tests.el --- Tests for textsec.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/international/ucs-normalize-tests.el 
b/test/lisp/international/ucs-normalize-tests.el
index 002aa3b8c21..7b17ee56fb9 100644
--- a/test/lisp/international/ucs-normalize-tests.el
+++ b/test/lisp/international/ucs-normalize-tests.el
@@ -1,6 +1,6 @@
 ;;; ucs-normalize-tests.el --- tests for international/ucs-normalize.el -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/isearch-tests.el b/test/lisp/isearch-tests.el
index 693f15336f2..b5b1b20e932 100644
--- a/test/lisp/isearch-tests.el
+++ b/test/lisp/isearch-tests.el
@@ -1,6 +1,6 @@
 ;;; isearch-tests.el --- Tests for isearch.el        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
 
diff --git a/test/lisp/jit-lock-tests.el b/test/lisp/jit-lock-tests.el
index 6944068828a..ea04a213d57 100644
--- a/test/lisp/jit-lock-tests.el
+++ b/test/lisp/jit-lock-tests.el
@@ -1,6 +1,6 @@
 ;;; jit-lock-tests.el --- tests for jit-lock  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Dmitry Gutov <dgutov@yandex.ru>
 
diff --git a/test/lisp/json-tests.el b/test/lisp/json-tests.el
index 92edb6e13f1..fbcfa826a6f 100644
--- a/test/lisp/json-tests.el
+++ b/test/lisp/json-tests.el
@@ -1,6 +1,6 @@
 ;;; json-tests.el --- Test suite for json.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Dmitry Gutov <dgutov@yandex.ru>
 
diff --git a/test/lisp/jsonrpc-tests.el b/test/lisp/jsonrpc-tests.el
index d8795ad8586..23423b5c719 100644
--- a/test/lisp/jsonrpc-tests.el
+++ b/test/lisp/jsonrpc-tests.el
@@ -1,6 +1,6 @@
 ;;; jsonrpc-tests.el --- tests for jsonrpc.el        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: João Távora <joaotavora@gmail.com>
 ;; Keywords: tests
@@ -104,6 +104,7 @@
                         (process-get listen-server 'handlers))))))))
 
 (cl-defmacro jsonrpc--with-emacsrpc-fixture ((endpoint-sym) &body body)
+  (declare (indent 1))
   `(jsonrpc--call-with-emacsrpc-fixture (lambda (,endpoint-sym) ,@body)))
 
 (ert-deftest returns-3 ()
@@ -152,14 +153,6 @@
              [1 2 3 3 4 5]
              (jsonrpc-request conn 'vconcat [[1 2 3] [3 4 5]])))))
 
-(ert-deftest json-el-cant-serialize-this ()
-  "Can't serialize a response that is half-vector/half-list."
-  (jsonrpc--with-emacsrpc-fixture (conn)
-                                  (should-error
-                                   ;; (append [1 2 3] [3 4 5]) => (1 2 3 . [3 
4 5]), which can't be
-                                   ;; serialized
-                                   (jsonrpc-request conn 'append [[1 2 3] [3 4 
5]]))))
-
 (cl-defmethod jsonrpc-connection-ready-p
   ((conn jsonrpc--test-client) what)
   (and (cl-call-next-method)
diff --git a/test/lisp/kmacro-tests.el b/test/lisp/kmacro-tests.el
index a325220e8d9..2eead234988 100644
--- a/test/lisp/kmacro-tests.el
+++ b/test/lisp/kmacro-tests.el
@@ -1,6 +1,6 @@
 ;;; kmacro-tests.el --- Tests for kmacro.el       -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Gemini Lasswell <gazally@runbox.com>
 
diff --git a/test/lisp/loadhist-resources/loadhist--bar.el 
b/test/lisp/loadhist-resources/loadhist--bar.el
index 882d073ab56..022f9c149c4 100644
--- a/test/lisp/loadhist-resources/loadhist--bar.el
+++ b/test/lisp/loadhist-resources/loadhist--bar.el
@@ -1,6 +1,6 @@
 ;;; loadhist--bar.el --- Dummy package for loadhist-tests  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 
diff --git a/test/lisp/loadhist-resources/loadhist--foo.el 
b/test/lisp/loadhist-resources/loadhist--foo.el
index 239066b6def..9c5ee310600 100644
--- a/test/lisp/loadhist-resources/loadhist--foo.el
+++ b/test/lisp/loadhist-resources/loadhist--foo.el
@@ -1,6 +1,6 @@
 ;;; loadhist--foo.el --- Dummy package for loadhist-tests  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 
diff --git a/test/lisp/loadhist-tests.el b/test/lisp/loadhist-tests.el
index 28f6607d95c..0192edf2a8f 100644
--- a/test/lisp/loadhist-tests.el
+++ b/test/lisp/loadhist-tests.el
@@ -1,6 +1,6 @@
 ;;; loadhist-tests.el --- Tests for loadhist.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/lpr-tests.el b/test/lisp/lpr-tests.el
index 382b3ae905f..446633a9385 100644
--- a/test/lisp/lpr-tests.el
+++ b/test/lisp/lpr-tests.el
@@ -1,6 +1,6 @@
 ;;; lpr-tests.el --- Tests for lpr.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/ls-lisp-tests.el b/test/lisp/ls-lisp-tests.el
index 8c6262819c4..77046871ea7 100644
--- a/test/lisp/ls-lisp-tests.el
+++ b/test/lisp/ls-lisp-tests.el
@@ -1,6 +1,6 @@
 ;;; ls-lisp-tests.el --- tests for ls-lisp.el  -*- lexical-binding: t-*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Tino Calancha <tino.calancha@gmail.com>
 ;; Keywords:
@@ -29,13 +29,6 @@
 (require 'ls-lisp)
 (require 'dired)
 
-(ert-deftest ls-lisp-unload ()
-  "Test for https://debbugs.gnu.org/xxxxx ."
-  (should (advice-member-p 'ls-lisp--insert-directory 'insert-directory))
-  (unload-feature 'ls-lisp 'force)
-  (should-not (advice-member-p 'ls-lisp--insert-directory 'insert-directory))
-  (require 'ls-lisp))
-
 (ert-deftest ls-lisp-test-bug27762 ()
   "Test for https://debbugs.gnu.org/27762 ."
   (let* ((dir source-directory)
diff --git a/test/lisp/mail/flow-fill-tests.el 
b/test/lisp/mail/flow-fill-tests.el
index f6e92199814..1f698f538f3 100644
--- a/test/lisp/mail/flow-fill-tests.el
+++ b/test/lisp/mail/flow-fill-tests.el
@@ -1,6 +1,6 @@
 ;;; flow-fill-tests.el --- Tests for flow-fill.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mail/footnote-tests.el b/test/lisp/mail/footnote-tests.el
index 1415d2944a7..62927655375 100644
--- a/test/lisp/mail/footnote-tests.el
+++ b/test/lisp/mail/footnote-tests.el
@@ -1,6 +1,6 @@
 ;;; footnote-tests.el --- Tests for footnote-mode    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords:
diff --git a/test/lisp/mail/ietf-drums-date-tests.el 
b/test/lisp/mail/ietf-drums-date-tests.el
index 822b5bd041d..3ae3c6b9524 100644
--- a/test/lisp/mail/ietf-drums-date-tests.el
+++ b/test/lisp/mail/ietf-drums-date-tests.el
@@ -1,6 +1,6 @@
 ;;; ietf-drums-date-tests.el --- Test suite for ietf-drums-date.el  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Bob Rogers <rogers@rgrjr.com>
 
diff --git a/test/lisp/mail/ietf-drums-tests.el 
b/test/lisp/mail/ietf-drums-tests.el
index c55c5467f60..0f71d80e79d 100644
--- a/test/lisp/mail/ietf-drums-tests.el
+++ b/test/lisp/mail/ietf-drums-tests.el
@@ -1,6 +1,6 @@
 ;;; ietf-drums-tests.el --- Test suite for ietf-drums.el  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; Author: Bob Rogers <rogers@rgrjr.com>
 
diff --git a/test/lisp/mail/mail-extr-tests.el 
b/test/lisp/mail/mail-extr-tests.el
index 1013b9e2058..5e526d27da6 100644
--- a/test/lisp/mail/mail-extr-tests.el
+++ b/test/lisp/mail/mail-extr-tests.el
@@ -1,6 +1,6 @@
 ;;; mail-extr-tests.el --- Tests for mail-extr.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mail/mail-parse-tests.el 
b/test/lisp/mail/mail-parse-tests.el
index c4abbaa93ca..d0a3edd0b93 100644
--- a/test/lisp/mail/mail-parse-tests.el
+++ b/test/lisp/mail/mail-parse-tests.el
@@ -1,6 +1,6 @@
 ;;; mail-parse-tests.el --- tests for mail-parse.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mail/mail-utils-tests.el 
b/test/lisp/mail/mail-utils-tests.el
index 3bf5f2065e1..3d650485944 100644
--- a/test/lisp/mail/mail-utils-tests.el
+++ b/test/lisp/mail/mail-utils-tests.el
@@ -1,6 +1,6 @@
 ;;; mail-utils-tests.el --- tests for mail-utils.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/mail/qp-tests.el b/test/lisp/mail/qp-tests.el
index 9f0857a0ba6..2835707d89b 100644
--- a/test/lisp/mail/qp-tests.el
+++ b/test/lisp/mail/qp-tests.el
@@ -1,6 +1,6 @@
 ;;; qp-tests.el --- Tests for qp.el  -*- lexical-binding:t; coding:utf-8 -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/mail/rfc2045-tests.el b/test/lisp/mail/rfc2045-tests.el
index 0982e057609..23af9abc03e 100644
--- a/test/lisp/mail/rfc2045-tests.el
+++ b/test/lisp/mail/rfc2045-tests.el
@@ -1,6 +1,6 @@
 ;;; rfc2045-tests.el --- Tests for rfc2045.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/mail/rfc2047-tests.el b/test/lisp/mail/rfc2047-tests.el
index 3ce3bc10614..432b7632efb 100644
--- a/test/lisp/mail/rfc2047-tests.el
+++ b/test/lisp/mail/rfc2047-tests.el
@@ -1,6 +1,6 @@
 ;;; rfc2047-tests.el --- tests for rfc2047.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mail/rfc6068-tests.el b/test/lisp/mail/rfc6068-tests.el
index 6b7de3dfedd..44052237415 100644
--- a/test/lisp/mail/rfc6068-tests.el
+++ b/test/lisp/mail/rfc6068-tests.el
@@ -1,6 +1,6 @@
 ;;; rfc6068-tests.el --- Tests for rfc6068.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mail/rfc822-tests.el b/test/lisp/mail/rfc822-tests.el
index 53175fef079..9faa10ae81e 100644
--- a/test/lisp/mail/rfc822-tests.el
+++ b/test/lisp/mail/rfc822-tests.el
@@ -1,6 +1,6 @@
 ;;; rfc822-tests.el --- Tests for rfc822.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mail/rmail-tests.el b/test/lisp/mail/rmail-tests.el
index ae810c2e8df..f0c58543745 100644
--- a/test/lisp/mail/rmail-tests.el
+++ b/test/lisp/mail/rmail-tests.el
@@ -1,6 +1,6 @@
 ;;; rmail-tests.el --- Test suite. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mail/rmailmm-tests.el b/test/lisp/mail/rmailmm-tests.el
index 0daaf2954dd..1029aa19b0f 100644
--- a/test/lisp/mail/rmailmm-tests.el
+++ b/test/lisp/mail/rmailmm-tests.el
@@ -1,6 +1,6 @@
 ;;; rmailmm-tests.el --- Tests for rmailmm.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mail/undigest-tests.el b/test/lisp/mail/undigest-tests.el
index 4fe65258b1e..8a0716b61dd 100644
--- a/test/lisp/mail/undigest-tests.el
+++ b/test/lisp/mail/undigest-tests.el
@@ -1,6 +1,6 @@
 ;;; undigest-tests.el --- Tests for undigest.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mail/uudecode-tests.el b/test/lisp/mail/uudecode-tests.el
index 6cfbc5e1b53..89a9b574321 100644
--- a/test/lisp/mail/uudecode-tests.el
+++ b/test/lisp/mail/uudecode-tests.el
@@ -1,6 +1,6 @@
 ;;; uudecode-tests.el --- Tests for uudecode.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/man-tests.el b/test/lisp/man-tests.el
index e3657d7df8a..ecda189b6b2 100644
--- a/test/lisp/man-tests.el
+++ b/test/lisp/man-tests.el
@@ -1,6 +1,6 @@
 ;;; man-tests.el --- Test suite for man.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Wolfgang Jenkner <wjenkner@inode.at>
 ;; Keywords: help, internal, unix
@@ -161,6 +161,24 @@ DESCRIPTION
           (let ((button (button-at (match-beginning 0))))
             (should (and button (eq 'Man-xref-header-file (button-type 
button))))))))))
 
+(ert-deftest man-tests-Man-translate-references ()
+  (should (equal (Man-translate-references "basename")
+                 (if (memq system-type '(ms-dos windows-nt))
+                     "\"basename\""
+                     "basename")))
+  (should (equal (Man-translate-references "basename(3)")
+                 "3 basename"))
+  (should (equal (Man-translate-references "basename(3v)")
+                 "3v basename"))
+  (should (equal (Man-translate-references ";id")
+                 (if (memq system-type '(ms-dos windows-nt))
+                     "\";id\""
+                   "\\;id")))
+  (should (equal (Man-translate-references "-k basename")
+                 (if (memq system-type '(ms-dos windows-nt))
+                     "\"-k\" \"basename\""
+                   "-k basename"))))
+
 (provide 'man-tests)
 
 ;;; man-tests.el ends here
diff --git a/test/lisp/md4-tests.el b/test/lisp/md4-tests.el
index 50d1a7feabc..aa14e859b3c 100644
--- a/test/lisp/md4-tests.el
+++ b/test/lisp/md4-tests.el
@@ -1,6 +1,6 @@
 ;;; md4-tests.el --- tests for md4.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Mark Oteiza <mvoteiza@udel.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/mh-e/mh-limit-tests.el b/test/lisp/mh-e/mh-limit-tests.el
index 1fab3e1d9cc..4c6c0f389a7 100644
--- a/test/lisp/mh-e/mh-limit-tests.el
+++ b/test/lisp/mh-e/mh-limit-tests.el
@@ -1,6 +1,6 @@
 ;;; mh-limit-tests.el --- tests for mh-limit.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mh-e/mh-thread-tests.el 
b/test/lisp/mh-e/mh-thread-tests.el
index 3cc21f45ab9..1b3cf399c51 100644
--- a/test/lisp/mh-e/mh-thread-tests.el
+++ b/test/lisp/mh-e/mh-thread-tests.el
@@ -1,6 +1,6 @@
 ;;; mh-thread-tests.el --- tests for mh-thread.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mh-e/mh-utils-tests.el b/test/lisp/mh-e/mh-utils-tests.el
index 25be86070b8..2032e915387 100644
--- a/test/lisp/mh-e/mh-utils-tests.el
+++ b/test/lisp/mh-e/mh-utils-tests.el
@@ -1,6 +1,6 @@
 ;;; mh-utils-tests.el --- tests for mh-utils.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mh-e/mh-xface-tests.el b/test/lisp/mh-e/mh-xface-tests.el
index 0630c018f60..c103b951b72 100644
--- a/test/lisp/mh-e/mh-xface-tests.el
+++ b/test/lisp/mh-e/mh-xface-tests.el
@@ -1,6 +1,6 @@
 ;;; mh-xface-tests.el --- tests for mh-xface.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/mh-e/test-all-mh-variants.sh 
b/test/lisp/mh-e/test-all-mh-variants.sh
index 602d831e28c..a23289701fc 100755
--- a/test/lisp/mh-e/test-all-mh-variants.sh
+++ b/test/lisp/mh-e/test-all-mh-variants.sh
@@ -1,7 +1,7 @@
 #! /bin/bash
 # Run the mh-utils-tests against all MH variants found on this system.
 
-# Copyright (C) 2021-2023 Free Software Foundation, Inc.
+# Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index 28bca60b189..07c4dbc3197 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -1,6 +1,6 @@
 ;;; minibuffer-tests.el --- Tests for completion functions  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords:
@@ -465,6 +465,20 @@
       (previous-line-completion 4)
       (should (equal "ac" (get-text-property (point) 'completion--string))))))
 
+(ert-deftest completion-next-line-multline-test ()
+  (let ((completion-auto-wrap t))
+    (completing-read-with-minibuffer-setup
+     '("a\na" "a\nb" "ac")
+     (insert "a")
+     (minibuffer-completion-help)
+     (switch-to-completions)
+     (goto-char (point-min))
+     (next-line-completion 5)
+     (should (equal "a\nb" (get-text-property (point) 'completion--string)))
+     (goto-char (point-min))
+     (previous-line-completion 5)
+     (should (equal "a\nb" (get-text-property (point) 'completion--string))))))
+
 (ert-deftest completions-header-format-test ()
   (let ((completion-show-help nil)
         (completions-header-format nil))
@@ -505,11 +519,11 @@
 
 (ert-deftest completions-affixation-navigation-test ()
   (let ((completion-extra-properties
-         '(:affixation-function
-           (lambda (completions)
-             (mapcar (lambda (c)
-                       (list c "prefix " " suffix"))
-                     completions)))))
+         `(:affixation-function
+           ,(lambda (completions)
+              (mapcar (lambda (c)
+                        (list c "prefix " " suffix"))
+                      completions)))))
     (completing-read-with-minibuffer-setup
         '("aa" "ab" "ac")
       (insert "a")
@@ -551,35 +565,63 @@
                     (if transform
                         name
                       (pcase name
-                        (`"aa" "Group 1")
-                        (`"ab" "Group 2")
-                        (`"ac" "Group 3")))))
+                        (`"aa1" "Group 1")
+                        (`"aa2" "Group 1")
+                        (`"aa3" "Group 1")
+                        (`"aa4" "Group 1")
+                        (`"ab1" "Group 2")
+                        (`"ac1" "Group 3")
+                        (`"ac2" "Group 3")))))
              (category . unicode-name))
-         (complete-with-action action '("aa" "ab" "ac") string pred)))
+         (complete-with-action action '("aa1" "aa2" "aa3" "aa4" "ab1" "ac1" 
"ac2")
+                                string pred)))
     (insert "a")
     (minibuffer-completion-help)
     (switch-to-completions)
-    (should (equal "aa" (get-text-property (point) 'completion--string)))
+    (should (equal "aa1" (get-text-property (point) 'completion--string)))
     (let ((completion-auto-wrap t))
-      (next-completion 3))
-    (should (equal "aa" (get-text-property (point) 'completion--string)))
+      (next-completion 7))
+    (should (equal "aa1" (get-text-property (point) 'completion--string)))
     (let ((completion-auto-wrap nil))
-      (next-completion 3))
-    (should (equal "ac" (get-text-property (point) 'completion--string)))
+      (next-completion 7))
+    (should (equal "ac2" (get-text-property (point) 'completion--string)))
 
-    (first-completion)
     (let ((completion-auto-wrap t))
+      ;; First column
+      (first-completion)
       (next-line-completion 1)
-      (should (equal "ab" (get-text-property (point) 'completion--string)))
-      (next-line-completion 2)
-      (should (equal "aa" (get-text-property (point) 'completion--string)))
+      (should (equal "aa4" (get-text-property (point) 'completion--string)))
+      (next-line-completion 3)
+      (should (equal "aa1" (get-text-property (point) 'completion--string)))
       (previous-line-completion 2)
-      (should (equal "ab" (get-text-property (point) 'completion--string))))
+      (should (equal "ab1" (get-text-property (point) 'completion--string)))
+
+      ;; Second column
+      (first-completion)
+      (next-completion 1)
+      (should (equal "aa2" (get-text-property (point) 'completion--string)))
+      (next-line-completion 1)
+      (should (equal "ac2" (get-text-property (point) 'completion--string)))
+      (next-line-completion 1)
+      (should (equal "aa2" (get-text-property (point) 'completion--string)))
+      (previous-line-completion 1)
+      (should (equal "ac2" (get-text-property (point) 'completion--string)))
+      (previous-line-completion 1)
+      (should (equal "aa2" (get-text-property (point) 'completion--string)))
+
+      ;; Third column
+      (first-completion)
+      (next-completion 2)
+      (should (equal "aa3" (get-text-property (point) 'completion--string)))
+      (next-line-completion 1)
+      (should (equal "aa3" (get-text-property (point) 'completion--string))))
+
     (let ((completion-auto-wrap nil))
-      (next-line-completion 3)
-      (should (equal "ac" (get-text-property (point) 'completion--string)))
-      (previous-line-completion 3)
-      (should (equal "aa" (get-text-property (point) 'completion--string))))))
+      (first-completion)
+      (next-line-completion 7)
+      (should (equal "ac2" (get-text-property (point) 'completion--string)))
+      (previous-line-completion 7)
+      (should (equal "aa1" (get-text-property (point) 'completion--string))))))
 
 (provide 'minibuffer-tests)
 ;;; minibuffer-tests.el ends here
diff --git a/test/lisp/misc-tests.el b/test/lisp/misc-tests.el
index b9bafe4bd11..c118aba50a1 100644
--- a/test/lisp/misc-tests.el
+++ b/test/lisp/misc-tests.el
@@ -1,6 +1,6 @@
 ;;; misc-tests.el --- Tests for misc.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/mouse-tests.el b/test/lisp/mouse-tests.el
index 2af6cac6325..00ecdd79574 100644
--- a/test/lisp/mouse-tests.el
+++ b/test/lisp/mouse-tests.el
@@ -1,6 +1,6 @@
 ;;; mouse-tests.el --- unit tests for mouse.el       -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Philipp Stephani <phst@google.com>
 
diff --git a/test/lisp/mwheel-tests.el b/test/lisp/mwheel-tests.el
index 3255b5de200..2b0f0ff384a 100644
--- a/test/lisp/mwheel-tests.el
+++ b/test/lisp/mwheel-tests.el
@@ -1,6 +1,6 @@
 ;;; mwheel-tests.el --- tests for mwheel.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/net/browse-url-tests.el 
b/test/lisp/net/browse-url-tests.el
index 0fe2fa788b9..168aa1c43e0 100644
--- a/test/lisp/net/browse-url-tests.el
+++ b/test/lisp/net/browse-url-tests.el
@@ -1,6 +1,6 @@
 ;;; browse-url-tests.el --- Tests for browse-url.el  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el
index 66240efd882..fec252e12dd 100644
--- a/test/lisp/net/dbus-tests.el
+++ b/test/lisp/net/dbus-tests.el
@@ -1,6 +1,6 @@
 ;;; dbus-tests.el --- Tests of D-Bus integration into Emacs  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 
diff --git a/test/lisp/net/dig-tests.el b/test/lisp/net/dig-tests.el
index b264fd40ae1..a78c335488d 100644
--- a/test/lisp/net/dig-tests.el
+++ b/test/lisp/net/dig-tests.el
@@ -1,6 +1,6 @@
 ;;; dig-tests.el --- Tests for dig.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/net/eudc-tests.el b/test/lisp/net/eudc-tests.el
index 431d7c46231..1129e452cea 100644
--- a/test/lisp/net/eudc-tests.el
+++ b/test/lisp/net/eudc-tests.el
@@ -1,6 +1,6 @@
 ;;; eudc-tests.el --- tests for eudc.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/net/gnutls-tests.el b/test/lisp/net/gnutls-tests.el
index cb911577385..9fdf33db075 100644
--- a/test/lisp/net/gnutls-tests.el
+++ b/test/lisp/net/gnutls-tests.el
@@ -1,6 +1,6 @@
 ;;; gnutls-tests.el --- Test suite for gnutls.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Ted Zlatanov <tzz@lifelogs.com>
 
diff --git a/test/lisp/net/hmac-md5-tests.el b/test/lisp/net/hmac-md5-tests.el
index 0caa6c46952..9481f618ad2 100644
--- a/test/lisp/net/hmac-md5-tests.el
+++ b/test/lisp/net/hmac-md5-tests.el
@@ -1,6 +1,6 @@
 ;;; hmac-md5-tests.el --- Tests for hmac-md5.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/net/mailcap-tests.el b/test/lisp/net/mailcap-tests.el
index 175c3e88da9..5c03e73d371 100644
--- a/test/lisp/net/mailcap-tests.el
+++ b/test/lisp/net/mailcap-tests.el
@@ -1,6 +1,6 @@
 ;;; mailcap-tests.el --- tests for mailcap.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Mark Oteiza <mvoteiza@udel.edu>
 
diff --git a/test/lisp/net/network-stream-tests.el 
b/test/lisp/net/network-stream-tests.el
index 8b1ae398930..4e600573e7a 100644
--- a/test/lisp/net/network-stream-tests.el
+++ b/test/lisp/net/network-stream-tests.el
@@ -1,6 +1,6 @@
 ;;; network-stream-tests.el --- tests for network processes       -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Ingebrigtsen <larsi@gnus.org>
 
diff --git a/test/lisp/net/newsticker-tests.el 
b/test/lisp/net/newsticker-tests.el
index 3ed4b7b1dd5..7daa9f83a6d 100644
--- a/test/lisp/net/newsticker-tests.el
+++ b/test/lisp/net/newsticker-tests.el
@@ -1,6 +1,6 @@
 ;;; newsticker-tests.el --- Test suite for newsticker.  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author:      Ulf Jasper <ulf.jasper@web.de>
 ;; Keywords:    News, RSS, Atom
diff --git a/test/lisp/net/nsm-tests.el b/test/lisp/net/nsm-tests.el
index 391015dae9a..ba4ec2d5717 100644
--- a/test/lisp/net/nsm-tests.el
+++ b/test/lisp/net/nsm-tests.el
@@ -1,6 +1,6 @@
 ;;; nsm-tests.el --- tests for network security manager  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Robert Pluim <rpluim@gmail.com>
 
diff --git a/test/lisp/net/ntlm-tests.el b/test/lisp/net/ntlm-tests.el
index 625c5e902bb..0f4d1d02b5e 100644
--- a/test/lisp/net/ntlm-tests.el
+++ b/test/lisp/net/ntlm-tests.el
@@ -1,6 +1,6 @@
 ;;; ntlm-tests.el --- tests for ntlm.el            -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/net/puny-tests.el b/test/lisp/net/puny-tests.el
index 48d03791853..57f4380e758 100644
--- a/test/lisp/net/puny-tests.el
+++ b/test/lisp/net/puny-tests.el
@@ -1,6 +1,6 @@
 ;;; puny-tests.el --- tests for net/puny.el  -*- coding: utf-8; 
lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/net/rcirc-tests.el b/test/lisp/net/rcirc-tests.el
index 0a49951b410..2912462c796 100644
--- a/test/lisp/net/rcirc-tests.el
+++ b/test/lisp/net/rcirc-tests.el
@@ -1,6 +1,6 @@
 ;;; rcirc-tests.el --- Tests for rcirc -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 ;;
diff --git a/test/lisp/net/rfc2104-tests.el b/test/lisp/net/rfc2104-tests.el
index 713a08d6dde..be5da619eaa 100644
--- a/test/lisp/net/rfc2104-tests.el
+++ b/test/lisp/net/rfc2104-tests.el
@@ -1,6 +1,6 @@
 ;;; rfc2104-tests.el --- Tests of RFC2104 hashes  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Ingebrigtsen <larsi@gnus.org>
 
diff --git a/test/lisp/net/sasl-cram-tests.el b/test/lisp/net/sasl-cram-tests.el
index be703685fc3..3955fc6ca8c 100644
--- a/test/lisp/net/sasl-cram-tests.el
+++ b/test/lisp/net/sasl-cram-tests.el
@@ -1,6 +1,6 @@
 ;;; sasl-cram-tests.el --- tests for sasl-cram.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/net/sasl-scram-rfc-tests.el 
b/test/lisp/net/sasl-scram-rfc-tests.el
index 8b624f9123f..6866493759f 100644
--- a/test/lisp/net/sasl-scram-rfc-tests.el
+++ b/test/lisp/net/sasl-scram-rfc-tests.el
@@ -1,6 +1,6 @@
 ;;; sasl-scram-rfc-tests.el --- tests for SCRAM       -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Magnus Henoch <magnus.henoch@gmail.com>
 
diff --git a/test/lisp/net/sasl-tests.el b/test/lisp/net/sasl-tests.el
index 2abbfd559f0..3aa0f15e94f 100644
--- a/test/lisp/net/sasl-tests.el
+++ b/test/lisp/net/sasl-tests.el
@@ -1,6 +1,6 @@
 ;;; sasl-tests.el --- tests for sasl.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/net/secrets-tests.el b/test/lisp/net/secrets-tests.el
index 6307390aad5..9feba514413 100644
--- a/test/lisp/net/secrets-tests.el
+++ b/test/lisp/net/secrets-tests.el
@@ -1,6 +1,6 @@
 ;;; secrets-tests.el --- Tests of Secret Service API -*- lexical-binding: t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 
diff --git a/test/lisp/net/shr-tests.el b/test/lisp/net/shr-tests.el
index 64ed070f851..0c6e2c091bf 100644
--- a/test/lisp/net/shr-tests.el
+++ b/test/lisp/net/shr-tests.el
@@ -1,6 +1,6 @@
 ;;; shr-tests.el --- tests for shr.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Ingebrigtsen <larsi@gnus.org>
 
diff --git a/test/lisp/net/socks-tests.el b/test/lisp/net/socks-tests.el
index 1a4bac37bf9..b9515876d6c 100644
--- a/test/lisp/net/socks-tests.el
+++ b/test/lisp/net/socks-tests.el
@@ -1,6 +1,6 @@
 ;;; socks-tests.el --- tests for SOCKS -*- coding: utf-8; lexical-binding: t; 
-*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/net/tramp-archive-tests.el 
b/test/lisp/net/tramp-archive-tests.el
index 9500ce0efca..978342b1bb1 100644
--- a/test/lisp/net/tramp-archive-tests.el
+++ b/test/lisp/net/tramp-archive-tests.el
@@ -1,6 +1,6 @@
 ;;; tramp-archive-tests.el --- Tests of file archive access  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index d8932a28e4d..489b682d0c3 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -1,6 +1,6 @@
 ;;; tramp-tests.el --- Tests of remote file access  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 
@@ -134,7 +134,7 @@ A resource file is in the resource directory as per
   (eval-and-compile
     ;; There is no default value on w32 systems, which could work out
     ;; of the box.
-    (defconst ert-remote-temporary-file-directory
+    (defvar ert-remote-temporary-file-directory
       (cond
        ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
        ((eq system-type 'windows-nt) null-device)
@@ -3811,7 +3811,7 @@ This tests also `access-file', `file-readable-p',
            (should (eq (file-attribute-type attr) t)))
 
        ;; Cleanup.
-       (ignore-errors (delete-directory tmp-name1))
+       (ignore-errors (delete-directory tmp-name1 'recursive))
        (ignore-errors (delete-file tmp-name1))
        (ignore-errors (delete-file tmp-name2))))))
 
@@ -4719,57 +4719,55 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
   "Check `file-name-completion' and `file-name-all-completions'."
   (skip-unless (tramp--test-enabled))
 
-  ;; Method and host name in completion mode.  This kind of completion
-  ;; does not work on MS Windows.
-  (unless (memq system-type '(cygwin windows-nt))
-    (let ((tramp-fuse-remove-hidden-files t)
-         (method (file-remote-p ert-remote-temporary-file-directory 'method))
-         (host (file-remote-p ert-remote-temporary-file-directory 'host))
-          (orig-syntax tramp-syntax)
-          (minibuffer-completing-file-name t))
-      (when (and (stringp host) (string-match tramp-host-with-port-regexp 
host))
-       (setq host (match-string 1 host)))
+  ;; Method and host name in completion mode.
+  (let ((tramp-fuse-remove-hidden-files t)
+       (method (file-remote-p ert-remote-temporary-file-directory 'method))
+       (host (file-remote-p ert-remote-temporary-file-directory 'host))
+        (orig-syntax tramp-syntax)
+        (minibuffer-completing-file-name t))
+    (when (and (stringp host) (string-match tramp-host-with-port-regexp host))
+      (setq host (match-string 1 host)))
 
-      (unwind-protect
-          (dolist (syntax (if (tramp--test-expensive-test-p)
-                             (tramp-syntax-values) `(,orig-syntax)))
-            (tramp-change-syntax syntax)
-           ;; This has cleaned up all connection data, which are used
-           ;; for completion.  We must refill the cache.
-           (tramp-set-connection-property tramp-test-vec "property" nil)
-
-            (let (;; This is needed for the `separate' syntax.
-                  (prefix-format (substring tramp-prefix-format 1))
-                 ;; This is needed for the IPv6 host name syntax.
-                 (ipv6-prefix
-                  (and (string-match-p tramp-ipv6-regexp host)
-                       tramp-prefix-ipv6-format))
-                 (ipv6-postfix
-                  (and (string-match-p tramp-ipv6-regexp host)
-                       tramp-postfix-ipv6-format)))
-              ;; Complete method name.
-             (unless (or (tramp-string-empty-or-nil-p method)
-                          (string-empty-p tramp-method-regexp))
-               (should
-                (member
-                 (concat prefix-format method tramp-postfix-method-format)
-                 (file-name-all-completions
-                   (concat prefix-format (substring method 0 1)) "/"))))
-              ;; Complete host name.
-             (unless (or (tramp-string-empty-or-nil-p method)
-                          (string-empty-p tramp-method-regexp)
-                          (tramp-string-empty-or-nil-p host))
-               (should
-                (member
-                 (concat
-                   prefix-format method tramp-postfix-method-format
-                  ipv6-prefix host ipv6-postfix tramp-postfix-host-format)
-                 (file-name-all-completions
-                  (concat prefix-format method tramp-postfix-method-format)
-                   "/"))))))
+    (unwind-protect
+        (dolist (syntax (if (tramp--test-expensive-test-p)
+                           (tramp-syntax-values) `(,orig-syntax)))
+          (tramp-change-syntax syntax)
+         ;; This has cleaned up all connection data, which are used
+         ;; for completion.  We must refill the cache.
+         (tramp-set-connection-property tramp-test-vec "property" nil)
 
-       ;; Cleanup.
-        (tramp-change-syntax orig-syntax))))
+          (let (;; This is needed for the `separate' syntax.
+                (prefix-format (substring tramp-prefix-format 1))
+               ;; This is needed for the IPv6 host name syntax.
+               (ipv6-prefix
+                (and (string-match-p tramp-ipv6-regexp host)
+                     tramp-prefix-ipv6-format))
+               (ipv6-postfix
+                (and (string-match-p tramp-ipv6-regexp host)
+                     tramp-postfix-ipv6-format)))
+            ;; Complete method name.
+           (unless (or (tramp-string-empty-or-nil-p method)
+                        (string-empty-p tramp-method-regexp))
+             (should
+              (member
+               (concat prefix-format method tramp-postfix-method-format)
+               (file-name-all-completions
+                 (concat prefix-format (substring method 0 1)) "/"))))
+            ;; Complete host name.
+           (unless (or (tramp-string-empty-or-nil-p method)
+                        (string-empty-p tramp-method-regexp)
+                        (tramp-string-empty-or-nil-p host))
+             (should
+              (member
+               (concat
+                 prefix-format method tramp-postfix-method-format
+                ipv6-prefix host ipv6-postfix tramp-postfix-host-format)
+               (file-name-all-completions
+                (concat prefix-format method tramp-postfix-method-format)
+                 "/"))))))
+
+      ;; Cleanup.
+      (tramp-change-syntax orig-syntax)))
 
   (dolist (non-essential '(nil t))
     (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
@@ -4851,9 +4849,7 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
 ;; and Bug#60505.
 (ert-deftest tramp-test26-interactive-file-name-completion ()
   "Check interactive completion with different `completion-styles'."
-  ;; Method, user and host name in completion mode.  This kind of
-  ;; completion does not work on MS Windows.
-  (skip-unless (not (memq system-type '(cygwin windows-nt))))
+  ;; Method, user and host name in completion mode.
   (tramp-cleanup-connection tramp-test-vec nil 'keep-password)
 
   (let ((method (file-remote-p ert-remote-temporary-file-directory 'method))
@@ -5159,8 +5155,8 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
                (should-not (get-buffer-window (current-buffer) t))
                (delete-file tmp-name)))
 
-           ;; Check remote and local DESTNATION file.  This isn't
-           ;; implemented yet ina all file name handler backends.
+           ;; Check remote and local DESTINATION file.  This isn't
+           ;; implemented yet in all file name handler backends.
            ;; (dolist (local '(nil t))
            ;;   (setq tmp-name (tramp--test-make-temp-name local quoted))
            ;;   (should
@@ -6347,6 +6343,8 @@ INPUT, if non-nil, is a string sent to the process."
       ;; Cleanup.
       (ignore-errors (delete-file tmp-name)))))
 
+(tramp--test-deftest-direct-async-process tramp-test35-exec-path)
+
 ;; This test is inspired by Bug#33781.
 (ert-deftest tramp-test35-remote-path ()
   "Check loooong `tramp-remote-path'."
@@ -6360,6 +6358,8 @@ INPUT, if non-nil, is a string sent to the process."
          (tramp-remote-path tramp-remote-path)
         (orig-tramp-remote-path tramp-remote-path)
         path)
+    ;; The "flatpak" method modifies `tramp-remote-path'.
+    (skip-unless (not (tramp-compat-connection-local-p tramp-remote-path)))
     (unwind-protect
        (progn
           ;; Non existing directories are removed.
@@ -6409,6 +6409,8 @@ INPUT, if non-nil, is a string sent to the process."
       (setq tramp-remote-path orig-tramp-remote-path)
       (ignore-errors (delete-directory tmp-name 'recursive)))))
 
+(tramp--test-deftest-direct-async-process tramp-test35-remote-path)
+
 (ert-deftest tramp-test36-vc-registered ()
   "Check `vc-registered'."
   :tags '(:expensive-test)
diff --git a/test/lisp/net/webjump-tests.el b/test/lisp/net/webjump-tests.el
index ffdebf2bb6f..eeec499b557 100644
--- a/test/lisp/net/webjump-tests.el
+++ b/test/lisp/net/webjump-tests.el
@@ -1,6 +1,6 @@
 ;;; webjump-tests.el --- Tests for webjump.el        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/newcomment-tests.el b/test/lisp/newcomment-tests.el
index cb0f304c463..8bc08825aa4 100644
--- a/test/lisp/newcomment-tests.el
+++ b/test/lisp/newcomment-tests.el
@@ -1,6 +1,6 @@
 ;;; newcomment-tests.el --- Tests for newcomment.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/nxml/nxml-mode-tests.el 
b/test/lisp/nxml/nxml-mode-tests.el
index 973f2ebb67e..de60070555f 100644
--- a/test/lisp/nxml/nxml-mode-tests.el
+++ b/test/lisp/nxml/nxml-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; nxml-mode-tests.el --- Test NXML Mode -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/nxml/xsd-regexp-tests.el 
b/test/lisp/nxml/xsd-regexp-tests.el
index 6258e6c0fb0..797da3a3155 100644
--- a/test/lisp/nxml/xsd-regexp-tests.el
+++ b/test/lisp/nxml/xsd-regexp-tests.el
@@ -1,6 +1,6 @@
 ;;; xsd-regexp-tests.el --- Test NXML Mode -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/obarray-tests.el b/test/lisp/obarray-tests.el
index 1831dc07a6d..d7e547fcf29 100644
--- a/test/lisp/obarray-tests.el
+++ b/test/lisp/obarray-tests.el
@@ -1,6 +1,6 @@
 ;;; obarray-tests.el --- Tests for obarray -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Przemysław Wojnowski <esperanto@cumego.com>
 
diff --git a/test/lisp/obsolete/cl-tests.el b/test/lisp/obsolete/cl-tests.el
index f52c4749c9a..6a798f6792b 100644
--- a/test/lisp/obsolete/cl-tests.el
+++ b/test/lisp/obsolete/cl-tests.el
@@ -1,6 +1,6 @@
 ;;; cl-tests.el --- tests for emacs-lisp/cl.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/obsolete/inversion-tests.el 
b/test/lisp/obsolete/inversion-tests.el
index 728362eae0e..29c9705ba5d 100644
--- a/test/lisp/obsolete/inversion-tests.el
+++ b/test/lisp/obsolete/inversion-tests.el
@@ -1,6 +1,6 @@
 ;;; inversion-tests.el --- Tests for inversion.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/lisp/obsolete/makesum-tests.el 
b/test/lisp/obsolete/makesum-tests.el
index 280a43f77d5..68e464413ca 100644
--- a/test/lisp/obsolete/makesum-tests.el
+++ b/test/lisp/obsolete/makesum-tests.el
@@ -1,6 +1,6 @@
 ;;; makesum-tests.el --- Tests for makesum.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/obsolete/rfc2368-tests.el 
b/test/lisp/obsolete/rfc2368-tests.el
index a7f80a689f8..2421ce6b912 100644
--- a/test/lisp/obsolete/rfc2368-tests.el
+++ b/test/lisp/obsolete/rfc2368-tests.el
@@ -1,6 +1,6 @@
 ;;; rfc2368-tests.el --- Tests for rfc2368.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/obsolete/thumbs-tests.el 
b/test/lisp/obsolete/thumbs-tests.el
index 87f8227c978..483418895fe 100644
--- a/test/lisp/obsolete/thumbs-tests.el
+++ b/test/lisp/obsolete/thumbs-tests.el
@@ -1,6 +1,6 @@
 ;;; thumbs-tests.el --- tests for thumbs.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/org/org-tests.el b/test/lisp/org/org-tests.el
index a498164f2f4..f519822cb42 100644
--- a/test/lisp/org/org-tests.el
+++ b/test/lisp/org/org-tests.el
@@ -1,6 +1,6 @@
 ;;; org-tests.el --- tests for org/org.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 
diff --git a/test/lisp/paren-tests.el b/test/lisp/paren-tests.el
index 5e8b906a37f..352d436efb3 100644
--- a/test/lisp/paren-tests.el
+++ b/test/lisp/paren-tests.el
@@ -1,6 +1,6 @@
 ;;; paren-tests.el --- Tests for paren.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/password-cache-tests.el 
b/test/lisp/password-cache-tests.el
index 45d2ec76f7b..08d85744ea1 100644
--- a/test/lisp/password-cache-tests.el
+++ b/test/lisp/password-cache-tests.el
@@ -1,6 +1,6 @@
 ;;; password-cache-tests.el --- Tests for password-cache.el  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/pcmpl-linux-tests.el b/test/lisp/pcmpl-linux-tests.el
index eaceb216d38..da20428df9e 100644
--- a/test/lisp/pcmpl-linux-tests.el
+++ b/test/lisp/pcmpl-linux-tests.el
@@ -1,6 +1,6 @@
 ;;; pcmpl-linux-tests.el --- Tests for pcmpl-linux.el  -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/pcomplete-tests.el b/test/lisp/pcomplete-tests.el
index 805a645198a..25f572090b6 100644
--- a/test/lisp/pcomplete-tests.el
+++ b/test/lisp/pcomplete-tests.el
@@ -1,6 +1,6 @@
 ;;; pcomplete-tests.el --- Tests for pcomplete.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/play/animate-tests.el b/test/lisp/play/animate-tests.el
index a11ac6f1730..3dc34370789 100644
--- a/test/lisp/play/animate-tests.el
+++ b/test/lisp/play/animate-tests.el
@@ -1,6 +1,6 @@
 ;;; animate-tests.el --- Tests for animate.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/play/cookie1-tests.el b/test/lisp/play/cookie1-tests.el
index 0432ffb0f7e..058c80416a6 100644
--- a/test/lisp/play/cookie1-tests.el
+++ b/test/lisp/play/cookie1-tests.el
@@ -1,6 +1,6 @@
 ;;; cookie1-tests.el --- Tests for cookie1.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/play/dissociate-tests.el 
b/test/lisp/play/dissociate-tests.el
index 7bc15bb9827..f9b9ad7fd81 100644
--- a/test/lisp/play/dissociate-tests.el
+++ b/test/lisp/play/dissociate-tests.el
@@ -1,6 +1,6 @@
 ;;; dissociate-tests.el --- Tests for dissociate.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/play/fortune-tests.el b/test/lisp/play/fortune-tests.el
index 5f0ee6d0d6a..c90bad02b69 100644
--- a/test/lisp/play/fortune-tests.el
+++ b/test/lisp/play/fortune-tests.el
@@ -1,6 +1,6 @@
 ;;; fortune-tests.el --- Tests for fortune.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/play/life-tests.el b/test/lisp/play/life-tests.el
index 98ab11a886a..794dd14a774 100644
--- a/test/lisp/play/life-tests.el
+++ b/test/lisp/play/life-tests.el
@@ -1,6 +1,6 @@
 ;;; life-tests.el --- Tests for life.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/play/morse-tests.el b/test/lisp/play/morse-tests.el
index 3fe4c9335c2..397cc3fa346 100644
--- a/test/lisp/play/morse-tests.el
+++ b/test/lisp/play/morse-tests.el
@@ -1,6 +1,6 @@
 ;;; morse-tests.el --- Tests for morse.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/play/studly-tests.el b/test/lisp/play/studly-tests.el
index c563023ad12..e291e3302a6 100644
--- a/test/lisp/play/studly-tests.el
+++ b/test/lisp/play/studly-tests.el
@@ -1,6 +1,6 @@
 ;;; studly-tests.el --- Tests for studly.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/proced-tests.el b/test/lisp/proced-tests.el
index 44596f92490..6f16a241146 100644
--- a/test/lisp/proced-tests.el
+++ b/test/lisp/proced-tests.el
@@ -1,6 +1,6 @@
 ;;; proced-tests.el --- Test suite for proced.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -46,7 +46,7 @@
   (move-to-column (string-match attribute proced-header-line)))
 
 (defun proced--assert-process-valid-pid-refinement (pid)
-  "Fail unless the process at point could be present after a refinment using 
PID."
+  "Fail unless the process at point could be present after a refinement using 
PID."
   (proced--move-to-column "PID")
   (let ((pid-equal (string= pid (word-at-point))))
     (should
diff --git a/test/lisp/progmodes/asm-mode-tests.el 
b/test/lisp/progmodes/asm-mode-tests.el
index f4191493b27..55e937bd9ce 100644
--- a/test/lisp/progmodes/asm-mode-tests.el
+++ b/test/lisp/progmodes/asm-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; asm-mode-tests.el --- Tests for asm-mode.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/progmodes/autoconf-tests.el 
b/test/lisp/progmodes/autoconf-tests.el
index 3b67e6483d9..d170c9497fc 100644
--- a/test/lisp/progmodes/autoconf-tests.el
+++ b/test/lisp/progmodes/autoconf-tests.el
@@ -1,6 +1,6 @@
 ;;; autoconf-tests.el --- Tests for autoconf.el      -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/progmodes/bat-mode-tests.el 
b/test/lisp/progmodes/bat-mode-tests.el
index 8b80956c9af..80a5b5aa6b3 100644
--- a/test/lisp/progmodes/bat-mode-tests.el
+++ b/test/lisp/progmodes/bat-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; bat-mode-tests.el --- Tests for bat-mode.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Vladimir Panteleev <vladimir@thecybershadow.net>
 ;; Keywords:
diff --git a/test/lisp/progmodes/bug-reference-tests.el 
b/test/lisp/progmodes/bug-reference-tests.el
index e5b207748bf..8cca354705b 100644
--- a/test/lisp/progmodes/bug-reference-tests.el
+++ b/test/lisp/progmodes/bug-reference-tests.el
@@ -1,6 +1,6 @@
 ;;; bug-reference-tests.el --- Tests for bug-reference.el  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
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 74e34fe821b..fa65ba83a69 100644
--- a/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts
+++ b/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts
@@ -91,3 +91,37 @@ main (int   argc,
   }
 }
 =-=-=
+
+Name: Bracketless Simple Statement (bug#66152)
+
+=-=
+for (int i = 0; i < 5; i++)
+continue;
+
+while (true)
+return 1;
+
+do
+i++;
+while (true)
+
+if (true)
+break;
+else
+break;
+=-=
+for (int i = 0; i < 5; i++)
+  continue;
+
+while (true)
+  return 1;
+
+do
+  i++;
+while (true)
+
+if (true)
+  break;
+else
+  break;
+=-=-=
diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts 
b/test/lisp/progmodes/c-ts-mode-resources/indent.erts
index bac76fb7378..24b244c1611 100644
--- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts
+++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts
@@ -84,7 +84,7 @@ int main()
 }
 =-=-=
 
-Name: Concecutive blocks (GNU Style) (bug#60873)
+Name: Consecutive blocks (GNU Style) (bug#60873)
 
 =-=
 int
@@ -330,7 +330,7 @@ label:
 
 Name: Bracket-less Block-Statement (Linux Style) (bug#61026)
 
-=-=-=
+=-=
 int main() {
   while (true)
     if (true) {
@@ -351,6 +351,8 @@ int main() {
     if (true) {
       puts ("Hello");
     }
+    else
+      puts("Hello");
 }
 =-=-=
 
@@ -399,6 +401,34 @@ void foo(
 }
 =-=-=
 
+Name: Block-Statement where first siblings are comments (Linux Style)
+
+=-=
+int main() {
+  while (true) { /* foo */
+    if (true) { // bar
+      puts ("Hello");
+    }
+  }
+  for (;;) {  // 1. fooo
+    /* 2. baaa */
+    /* 3. rrr */
+    if (true)
+      // 2. baaa
+      puts ("Hello");
+  }
+  if (1) { // 1
+    /*
+     * 2
+     */
+    if (1) /*3*/ {
+      /* 4 */
+      puts("Hello");
+    }
+  }
+}
+=-=-=
+
 Name: Initializer List (Linux Style) (Bug#61398)
 
 =-=
@@ -498,3 +528,19 @@ main (void)
 {
   |
 =-=-=
+
+Code:
+  (lambda ()
+    (c-ts-mode)
+    (setq-local indent-tabs-mode nil)
+    (goto-line 3)
+    (indent-for-tab-command))
+
+Name: Block-Statement where previous sibling is comment
+
+=-=
+int main() {
+    puts ("Hello"); // unusual indent and has trailing comment.
+    return true; // Should align with previous non-comment sibling (rather 
than one level up against parent).
+}
+=-=-=
diff --git a/test/lisp/progmodes/c-ts-mode-tests.el 
b/test/lisp/progmodes/c-ts-mode-tests.el
index ea5fab4cbef..d8d8aabaa36 100644
--- a/test/lisp/progmodes/c-ts-mode-tests.el
+++ b/test/lisp/progmodes/c-ts-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; c-ts-mode-tests.el --- Tests for Tree-sitter-based C mode         -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/cc-mode-tests.el 
b/test/lisp/progmodes/cc-mode-tests.el
index 7158b8f9e45..c6e43ab3360 100644
--- a/test/lisp/progmodes/cc-mode-tests.el
+++ b/test/lisp/progmodes/cc-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; cc-mode-tests.el --- Test suite for cc-mode.  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Michal Nazarewicz <mina86@mina86.com>
 ;; Keywords:       internal
diff --git a/test/lisp/progmodes/compile-tests.el 
b/test/lisp/progmodes/compile-tests.el
index d497644c389..20beed955d2 100644
--- a/test/lisp/progmodes/compile-tests.el
+++ b/test/lisp/progmodes/compile-tests.el
@@ -1,6 +1,6 @@
 ;;; compile-tests.el --- Test suite for compile.el.  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Chong Yidong <cyd@stupidchicken.com>
 ;; Keywords:       internal
@@ -206,6 +206,33 @@
      1 0 31 "/usr/include/c++/3.3/backward/iostream.h")
     (gcc-include "                 from test_clt.cc:1:"
      1 nil 1 "test_clt.cc")
+    ;; Lua
+    (lua "lua: database.lua:10: assertion failed!\nstack traceback:\n\t"
+         6 nil 10 "database.lua")
+    (lua "lua 5.4: database 2.lua:10: assertion failed!\nstack traceback:\n\t"
+         10 nil 10 "database 2.lua")
+    (lua "/usr/local/bin/lua: core/database.lua:20: assertion failed!\nstack 
traceback:\n\t"
+         21 nil 20 "core/database.lua")
+    (lua "C:\\Lua\\Lua.exe: Core\\Database.lua:20: assertion failed!\nstack 
traceback:\n\t"
+         17 nil 20 "Core\\Database.lua")
+    (lua "lua: /tmp/database.lua:20: assertion failed!\nstack traceback:\n\t"
+         6 nil 20 "/tmp/database.lua")
+    (lua "Lua.exe: C:\\Temp\\Database.lua:20: assertion failed!\nstack 
traceback:\n\t"
+         10 nil 20 "C:\\Temp\\Database.lua")
+    (lua-stack "       database.lua: in field 'statement'"
+               2 nil nil "database.lua" 0)
+    (lua-stack "       database.lua:10: in field 'statement'"
+               2 nil 10 "database.lua" 0)
+    (lua-stack "       core/database.lua:20: in field 'statement'"
+               2 nil 20 "core/database.lua" 0)
+    (lua-stack "       database 2.lua: in field 'statement'"
+               2 nil nil "database 2.lua" 0)
+    (lua-stack "       Core\\Database.lua:20: in field 'statement'"
+               2 nil 20 "Core\\Database.lua" 0)
+    (lua-stack "       /tmp/database.lua: in field 'statement'"
+               2 nil nil "/tmp/database.lua" 0)
+    (lua-stack "       C:\\Core\\Database.lua: in field 'statement'"
+               2 nil nil "C:\\Core\\Database.lua" 0)
     ;; gmake
     (gmake "make: *** [Makefile:20: all] Error 2" 12 nil 20 "Makefile" 0)
     (gmake "make[4]: *** [sub/make.mk:19: all] Error 127" 15 nil 19
@@ -507,9 +534,9 @@ The test data is in `compile-tests--test-regexps-data'."
                    1 15 5 "alpha.c")))
         (compile--test-error-line test))
 
-      (should (eq compilation-num-errors-found 100))
+      (should (eq compilation-num-errors-found 106))
       (should (eq compilation-num-warnings-found 35))
-      (should (eq compilation-num-infos-found 28)))))
+      (should (eq compilation-num-infos-found 35)))))
 
 (ert-deftest compile-test-grep-regexps ()
   "Test the `grep-regexp-alist' regexps.
diff --git a/test/lisp/progmodes/cperl-mode-tests.el 
b/test/lisp/progmodes/cperl-mode-tests.el
index 0af44c8e08d..62b7fdab7f7 100644
--- a/test/lisp/progmodes/cperl-mode-tests.el
+++ b/test/lisp/progmodes/cperl-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; cperl-mode-tests.el --- Test for cperl-mode  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Harald Jörg <haj@posteo.de>
 ;; Maintainer: Harald Jörg
@@ -111,9 +111,8 @@ end of the statement."
   (skip-unless (eq cperl-test-mode #'cperl-mode))
   (cperl--run-test-cases
    (ert-resource-file "cperl-indent-styles.pl")
-   (cperl-set-style "PBP")
-   (indent-region (point-min) (point-max)) ; here we go!
-   (cperl-set-style-back)))
+   (cperl-file-style "PBP")
+   (indent-region (point-min) (point-max)))) ; here we go!
 
 ;;; Fontification tests
 
@@ -1145,17 +1144,16 @@ Perl is not Lisp: An open paren in column 0 does not 
start a function."
 
 (ert-deftest cperl-test-bug-35925 ()
   "Check that indentation is correct after a terminating format declaration."
-  (cperl-set-style "PBP") ; Make cperl-mode use the same settings as perl-mode.
   (cperl--run-test-cases
    (ert-resource-file "cperl-bug-35925.pl")
+   (cperl-file-style "PBP") ; Make cperl-mode use the same settings as 
perl-mode.
    (let ((tab-function
           (if (equal cperl-test-mode 'perl-mode)
               #'indent-for-tab-command
             #'cperl-indent-command)))
      (goto-char (point-max))
      (forward-line -2)
-     (funcall tab-function)))
-  (cperl-set-style-back))
+     (funcall tab-function))))
 
 (ert-deftest cperl-test-bug-37127 ()
   "Verify that closing a paren in a regex goes without a message.
@@ -1363,12 +1361,13 @@ as a regex."
 
 (ert-deftest cperl-test-bug-64364 ()
   "Check that multi-line subroutine declarations indent correctly."
-  (cperl-set-style "PBP") ; make cperl-mode use the same settings as perl-mode
   (cperl--run-test-cases
    (ert-resource-file "cperl-bug-64364.pl")
+   (cperl-file-style "PBP") ; make cperl-mode use the same settings as 
perl-mode
    (indent-region (point-min) (point-max)))
   (cperl--run-test-cases
    (ert-resource-file "cperl-bug-64364.pl")
+   (cperl-file-style "PBP") ; make cperl-mode use the same settings as 
perl-mode
    (let ((tab-function
           (if (equal cperl-test-mode 'perl-mode)
               #'indent-for-tab-command
@@ -1376,8 +1375,7 @@ as a regex."
      (goto-char (point-min))
      (while (null (eobp))
        (funcall tab-function)
-       (forward-line 1))))
-  (cperl-set-style-back))
+       (forward-line 1)))))
 
 (ert-deftest cperl-test-bug-65834 ()
   "Verify that CPerl mode identifies a left-shift operator.
diff --git a/test/lisp/progmodes/eglot-tests.el 
b/test/lisp/progmodes/eglot-tests.el
index 575a6ac8ef1..4725885038e 100644
--- a/test/lisp/progmodes/eglot-tests.el
+++ b/test/lisp/progmodes/eglot-tests.el
@@ -1,6 +1,6 @@
 ;;; eglot-tests.el --- Tests for eglot.el            -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: João Távora <joaotavora@gmail.com>
 ;; Keywords: tests
@@ -199,40 +199,40 @@ directory hierarchy."
                               &rest body)
   "Run BODY saving LSP JSON messages in variables, most recent first."
   (declare (indent 1) (debug (sexp &rest form)))
-  (let ((log-event-ad-sym (make-symbol "eglot--event-sniff")))
-    `(unwind-protect
-         (let ,(delq nil (list server-requests
-                               server-notifications
-                               server-replies
-                               client-requests
-                               client-notifications
-                               client-replies))
-           (advice-add
-            #'jsonrpc--log-event :before
-            (lambda (_proc message &optional type)
-              (cl-destructuring-bind (&key method id _error &allow-other-keys)
-                  message
-                (let ((req-p (and method id))
-                      (notif-p method)
-                      (reply-p id))
-                  (cond
-                   ((eq type 'server)
-                    (cond (req-p ,(when server-requests
-                                    `(push message ,server-requests)))
-                          (notif-p ,(when server-notifications
-                                      `(push message ,server-notifications)))
-                          (reply-p ,(when server-replies
-                                      `(push message ,server-replies)))))
-                   ((eq type 'client)
-                    (cond (req-p ,(when client-requests
-                                    `(push message ,client-requests)))
-                          (notif-p ,(when client-notifications
-                                      `(push message ,client-notifications)))
-                          (reply-p ,(when client-replies
-                                      `(push message ,client-replies)))))))))
-            '((name . ,log-event-ad-sym)))
-           ,@body)
-       (advice-remove #'jsonrpc--log-event ',log-event-ad-sym))))
+  (let ((log-event-hook-sym (make-symbol "eglot--event-sniff")))
+    `(let* (,@(delq nil (list server-requests
+                              server-notifications
+                              server-replies
+                              client-requests
+                              client-notifications
+                              client-replies)))
+       (cl-flet ((,log-event-hook-sym (_connection
+                                       origin
+                                       &key _json kind message _foreign-message
+                                       &allow-other-keys)
+                   (let ((req-p (eq kind 'request))
+                         (notif-p (eq kind 'notification))
+                         (reply-p (eql kind 'reply)))
+                     (cond
+                      ((eq origin 'server)
+                       (cond (req-p ,(when server-requests
+                                       `(push message ,server-requests)))
+                             (notif-p ,(when server-notifications
+                                         `(push message 
,server-notifications)))
+                             (reply-p ,(when server-replies
+                                         `(push message ,server-replies)))))
+                      ((eq origin 'client)
+                       (cond (req-p ,(when client-requests
+                                       `(push message ,client-requests)))
+                             (notif-p ,(when client-notifications
+                                         `(push message 
,client-notifications)))
+                             (reply-p ,(when client-replies
+                                         `(push message 
,client-replies)))))))))
+         (unwind-protect
+             (progn
+               (add-hook 'jsonrpc-event-hook #',log-event-hook-sym)
+               ,@body)
+           (remove-hook 'jsonrpc-event-hook #',log-event-hook-sym))))))
 
 (cl-defmacro eglot--wait-for ((events-sym &optional (timeout 1) message) args 
&body body)
   (declare (indent 2) (debug (sexp sexp sexp &rest form)))
@@ -544,10 +544,7 @@ directory hierarchy."
       `(("project" . (("coiso.c" . "#include <stdio.h>\nint main () {fprin"))))
     (with-current-buffer
         (eglot--find-file-noselect "project/coiso.c")
-      (eglot--sniffing (:server-notifications s-notifs)
-        (eglot--wait-for-clangd)
-        (eglot--wait-for (s-notifs 20) (&key method &allow-other-keys)
-          (string= method "textDocument/publishDiagnostics")))
+      (eglot--wait-for-clangd)
       (goto-char (point-max))
       (completion-at-point)
       (message (buffer-string))
diff --git a/test/lisp/progmodes/elisp-mode-tests.el 
b/test/lisp/progmodes/elisp-mode-tests.el
index 4fa869c773f..1d1ef9981e5 100644
--- a/test/lisp/progmodes/elisp-mode-tests.el
+++ b/test/lisp/progmodes/elisp-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; elisp-mode-tests.el --- Tests for emacs-lisp-mode  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Dmitry Gutov <dgutov@yandex.ru>
 ;; Author: Stephen Leake <stephen_leake@member.fsf.org>
diff --git a/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts 
b/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts
index fe09a37a32b..f2d0eacee5b 100644
--- a/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts
+++ b/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts
@@ -134,7 +134,7 @@ Name: Pipe statements with fn
 end)
 =-=-=
 
-Name: Pipe statements stab clases
+Name: Pipe statements stab clauses
 
 =-=
 [1, 2]
diff --git a/test/lisp/progmodes/elixir-ts-mode-tests.el 
b/test/lisp/progmodes/elixir-ts-mode-tests.el
index 488fc1b646f..109030a4476 100644
--- a/test/lisp/progmodes/elixir-ts-mode-tests.el
+++ b/test/lisp/progmodes/elixir-ts-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; elixir-ts-mode-tests.el --- Tests for elixir-ts-mode         -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/etags-tests.el 
b/test/lisp/progmodes/etags-tests.el
index 2e1a73d977e..99d66a20e6d 100644
--- a/test/lisp/progmodes/etags-tests.el
+++ b/test/lisp/progmodes/etags-tests.el
@@ -1,6 +1,6 @@
 ;;; etags-tests.el --- Test suite for etags.el.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Eli Zaretskii <eliz@gnu.org>
 
diff --git a/test/lisp/progmodes/executable-tests.el 
b/test/lisp/progmodes/executable-tests.el
index 406762fe4de..be4fe7de049 100644
--- a/test/lisp/progmodes/executable-tests.el
+++ b/test/lisp/progmodes/executable-tests.el
@@ -1,6 +1,6 @@
 ;;; executable-tests.el --- Tests for executable.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/f90-tests.el b/test/lisp/progmodes/f90-tests.el
index 6028b58bb9e..e8e16534a97 100644
--- a/test/lisp/progmodes/f90-tests.el
+++ b/test/lisp/progmodes/f90-tests.el
@@ -1,6 +1,6 @@
 ;;; f90-tests.el --- tests for progmodes/f90.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Glenn Morris <rgm@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/progmodes/flymake-tests.el 
b/test/lisp/progmodes/flymake-tests.el
index c3ef4827ef2..21dbb0711d2 100644
--- a/test/lisp/progmodes/flymake-tests.el
+++ b/test/lisp/progmodes/flymake-tests.el
@@ -1,6 +1,6 @@
 ;;; flymake-tests.el --- Test suite for flymake -*- lexical-binding: t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Eduard Wiebe <usenet@pusto.de>
 
diff --git a/test/lisp/progmodes/gdb-mi-tests.el 
b/test/lisp/progmodes/gdb-mi-tests.el
index b75de1a9d45..d85f8e6cbb1 100644
--- a/test/lisp/progmodes/gdb-mi-tests.el
+++ b/test/lisp/progmodes/gdb-mi-tests.el
@@ -1,6 +1,6 @@
 ;;; gdb-mi-tests.el --- tests for gdb-mi.el    -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/glasses-tests.el 
b/test/lisp/progmodes/glasses-tests.el
index a577d9a46d8..cb1b17b1c05 100644
--- a/test/lisp/progmodes/glasses-tests.el
+++ b/test/lisp/progmodes/glasses-tests.el
@@ -1,6 +1,6 @@
 ;;; glasses-tests.el --- Tests for glasses.el        -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/progmodes/go-ts-mode-tests.el 
b/test/lisp/progmodes/go-ts-mode-tests.el
index 548465208f9..fd9b57e8691 100644
--- a/test/lisp/progmodes/go-ts-mode-tests.el
+++ b/test/lisp/progmodes/go-ts-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; go-ts-mode-tests.el --- Tests for Tree-sitter-based Go mode         -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/grep-tests.el 
b/test/lisp/progmodes/grep-tests.el
index 9b7f83086bf..303e5e90042 100644
--- a/test/lisp/progmodes/grep-tests.el
+++ b/test/lisp/progmodes/grep-tests.el
@@ -1,6 +1,6 @@
 ;;; grep-tests.el --- Test suite for grep.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/heex-ts-mode-tests.el 
b/test/lisp/progmodes/heex-ts-mode-tests.el
index def6d845de9..7f9c0bf272c 100644
--- a/test/lisp/progmodes/heex-ts-mode-tests.el
+++ b/test/lisp/progmodes/heex-ts-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; heex-ts-mode-tests.el --- Tests for heex-ts-mode         -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/hideshow-tests.el 
b/test/lisp/progmodes/hideshow-tests.el
index ce3efb6dc95..1c0b9333656 100644
--- a/test/lisp/progmodes/hideshow-tests.el
+++ b/test/lisp/progmodes/hideshow-tests.el
@@ -1,6 +1,6 @@
 ;;; hideshow-tests.el --- Test suite for hideshow.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/java-ts-mode-tests.el 
b/test/lisp/progmodes/java-ts-mode-tests.el
index 4fd8fc3019f..9fa313e173e 100644
--- a/test/lisp/progmodes/java-ts-mode-tests.el
+++ b/test/lisp/progmodes/java-ts-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; java-ts-mode-tests.el --- Tests for Tree-sitter-based Java mode  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/js-resources/js-ts-indents.erts 
b/test/lisp/progmodes/js-resources/js-ts-indents.erts
new file mode 100644
index 00000000000..2e34b23acef
--- /dev/null
+++ b/test/lisp/progmodes/js-resources/js-ts-indents.erts
@@ -0,0 +1,44 @@
+Code:
+  (lambda ()
+    (setq indent-tabs-mode nil)
+    (setq js-indent-level 2)
+    (js-ts-mode)
+    (indent-region (point-min) (point-max)))
+
+Name: Basic indentation
+
+=-=
+const foo = () => {
+  console.log("bar");
+  if (x) {
+    return y;
+  } else if (y) {
+    return u;
+  }
+  return baz.x()
+    ? true
+    : false;
+}
+=-=-=
+
+Name: Statement indentation without braces
+
+=-=
+function bracketless_statements(x) {
+  if (x == 0)
+    console.log("if_statement");
+  else if (x == 1)
+    console.log("if_statement");
+  else
+    console.log("else_clause");
+  for (let i = 0; i < 1; i++)
+    console.log("for_statement");
+  for (let _ of [true])
+    console.log("for_in_statement");
+  while (x-- > 0)
+    console.log("while_statement");
+  do
+    console.log("do_statement");
+  while (false)
+};
+=-=-=
diff --git a/test/lisp/progmodes/js-tests.el b/test/lisp/progmodes/js-tests.el
index 5db92b08f8a..39c5c4fb565 100644
--- a/test/lisp/progmodes/js-tests.el
+++ b/test/lisp/progmodes/js-tests.el
@@ -1,6 +1,6 @@
 ;;; js-tests.el --- Test suite for js-mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -288,6 +288,12 @@ function bar() {
     ;; end-of-defun should move point to eob.
     (should (eobp))))
 
+;;;; Tree-sitter tests.
+
+(ert-deftest js-ts-mode-test-indentation ()
+  (skip-unless (treesit-ready-p 'javascript))
+  (ert-test-erts-file (ert-resource-file "js-ts-indents.erts")))
+
 (provide 'js-tests)
 
 ;;; js-tests.el ends here
diff --git a/test/lisp/progmodes/lua-ts-mode-resources/font-lock.lua 
b/test/lisp/progmodes/lua-ts-mode-resources/font-lock.lua
new file mode 100644
index 00000000000..93d589e3825
--- /dev/null
+++ b/test/lisp/progmodes/lua-ts-mode-resources/font-lock.lua
@@ -0,0 +1,339 @@
+#!/usr/bin/env lua
+-- ^ font-lock-comment-face
+-- Comment
+-- <- font-lock-comment-delimiter-face
+-- ^ font-lock-comment-face
+--[[
+-- ^ font-lock-comment-face
+Multi-line comment
+-- ^ font-lock-comment-face
+]]
+-- <- font-lock-comment-face
+local line_comment = "comment" -- comment
+--                                ^ font-lock-comment-face
+
+-- Definition
+local function f1() end
+--             ^ font-lock-function-name-face
+local f2 = function() end
+--    ^ font-lock-function-name-face
+local tb = { f1 = function() end }
+--           ^ font-lock-function-name-face
+function tb.f2() end
+--          ^ font-lock-function-name-face
+function tb:f3() end
+--          ^ font-lock-function-name-face
+tbl.f4 = function() end
+--  ^ font-lock-function-name-face
+function x.y:z() end
+--           ^ font-lock-function-name-face
+
+-- Keyword
+if true then
+-- <- font-lock-keyword-face
+--      ^ font-lock-keyword-face
+elseif true then
+-- <- font-lock-keyword-face
+else end
+-- <- font-lock-keyword-face
+--   ^ font-lock-keyword-face
+local p = {}
+-- ^ font-lock-keyword-face
+for k,v in pairs({}) do end
+-- <- font-lock-keyword-face
+--      ^ font-lock-keyword-face
+repeat if true then break end until false
+-- <- font-lock-keyword-face
+--                  ^ font-lock-keyword-face
+--                            ^ font-lock-keyword-face
+while true do end
+-- <- font-lock-keyword-face
+--         ^ font-lock-keyword-face
+function fn() return true end
+-- <- font-lock-keyword-face
+--            ^ font-lock-keyword-face
+goto label1
+-- ^ font-lock-keyword-face
+::label1::
+if true and not false or nil then
+--      ^ font-lock-keyword-face
+--          ^ font-lock-keyword-face
+--                    ^ font-lock-keyword-face
+end
+
+-- String
+local _
+_ = "x"
+--   ^ font-lock-string-face
+_ = 'x'
+--   ^ font-lock-string-face
+_ = "x\ty"
+--   ^ font-lock-string-face
+--      ^ font-lock-string-face
+_ = "x\"y"
+--   ^ font-lock-string-face
+--      ^ font-lock-string-face
+_ = 'x\'y'
+--   ^ font-lock-string-face
+--      ^ font-lock-string-face
+_ = "x\z
+    y"
+--  ^ font-lock-string-face
+_ = "x\0900y"
+--        ^ font-lock-string-face
+_ = "x\09y"
+--       ^ font-lock-string-face
+_ = "x\0y"
+--      ^ font-lock-string-face
+_ = "x\u{1f602}y"
+--             ^ font-lock-string-face
+_ = [[x]]
+--    ^ font-lock-string-face
+_ = [=[x]=]
+--     ^ font-lock-string-face
+
+-- Assignment
+local n = 0
+--    ^ font-lock-variable-name-face
+o, p, q = 1, 2, 3
+-- <- font-lock-variable-name-face
+-- ^ font-lock-variable-name-face
+--    ^ font-lock-variable-name-face
+tbl[k] = "A"
+--  ^ font-lock-variable-name-face
+tbl.x = 1
+--  ^ font-lock-variable-name-face
+for i=0,9 do end
+--  ^ font-lock-variable-name-face
+
+-- Constant
+local x <const> = 1
+--      ^ font-lock-constant-face
+local f <close> = io.open('/file')
+--      ^ font-lock-constant-face
+local a, b, c = true, false, nil
+--              ^ font-lock-constant-face
+--                    ^ font-lock-constant-face
+--                           ^ font-lock-constant-face
+::label2::
+-- ^ font-lock-constant-face
+goto label2
+--   ^ font-lock-constant-face
+
+-- Number
+n = 123
+--  ^ font-lock-number-face
+print(99)
+--    ^ font-lock-number-face
+print(tbl[1])
+--        ^ font-lock-number-face
+
+-- Bracket
+local t = {}
+--        ^ font-lock-bracket-face
+--         ^ font-lock-bracket-face
+print(t[1])
+--   ^ font-lock-bracket-face
+--     ^ font-lock-bracket-face
+--       ^ font-lock-bracket-face
+--        ^ font-lock-bracket-face
+
+-- Builtin
+assert()
+-- <- font-lock-builtin-face
+bit32()
+-- <- font-lock-builtin-face
+collectgarbage()
+-- <- font-lock-builtin-face
+coroutine()
+-- <- font-lock-builtin-face
+debug()
+-- <- font-lock-builtin-face
+dofile()
+-- <- font-lock-builtin-face
+error()
+-- <- font-lock-builtin-face
+getmetatable()
+-- <- font-lock-builtin-face
+io()
+-- <- font-lock-builtin-face
+ipairs()
+-- <- font-lock-builtin-face
+load()
+-- <- font-lock-builtin-face
+loadfile()
+-- <- font-lock-builtin-face
+math()
+-- <- font-lock-builtin-face
+next()
+-- <- font-lock-builtin-face
+os()
+-- <- font-lock-builtin-face
+package()
+-- <- font-lock-builtin-face
+pairs()
+-- <- font-lock-builtin-face
+pcall()
+-- <- font-lock-builtin-face
+print()
+-- <- font-lock-builtin-face
+rawequal()
+-- <- font-lock-builtin-face
+rawget()
+-- <- font-lock-builtin-face
+rawlen()
+-- <- font-lock-builtin-face
+rawset()
+-- <- font-lock-builtin-face
+require()
+-- <- font-lock-builtin-face
+select()
+-- <- font-lock-builtin-face
+setmetatable()
+-- <- font-lock-builtin-face
+string()
+-- <- font-lock-builtin-face
+table()
+-- <- font-lock-builtin-face
+tonumber()
+-- <- font-lock-builtin-face
+tostring()
+-- <- font-lock-builtin-face
+type()
+-- <- font-lock-builtin-face
+utf8()
+-- <- font-lock-builtin-face
+warn()
+-- <- font-lock-builtin-face
+xpcall()
+-- <- font-lock-builtin-face
+print(_G)
+--    ^ font-lock-builtin-face
+print(_VERSION)
+--    ^ font-lock-builtin-face
+f.close()
+-- ^ font-lock-builtin-face
+f.flush()
+-- ^ font-lock-builtin-face
+f.lines()
+-- ^ font-lock-builtin-face
+f.read()
+-- ^ font-lock-builtin-face
+f.seek()
+-- ^ font-lock-builtin-face
+f.setvbuf()
+-- ^ font-lock-builtin-face
+f.write()
+-- ^ font-lock-builtin-face
+
+-- Delimiter
+t = { 1, 2 };
+--     ^ font-lock-delimiter-face
+--          ^ font-lock-delimiter-face
+
+-- Escape
+_ = "x\ty"
+--    ^ font-lock-escape-face
+--     ^ font-lock-escape-face
+_ = "x\"y"
+--    ^ font-lock-escape-face
+--     ^ font-lock-escape-face
+_ = 'x\'y'
+--    ^ font-lock-escape-face
+--     ^ font-lock-escape-face
+_ = "x\z
+    y"
+-- <- font-lock-escape-face
+_ = "x\x5Ay"
+--     ^ font-lock-escape-face
+--      ^ font-lock-escape-face
+_ = "x\0900y"
+--       ^ font-lock-escape-face
+_ = "x\09y"
+--      ^ font-lock-escape-face
+_ = "x\0y"
+--     ^ font-lock-escape-face
+_ = "x\u{1f602}y"
+--     ^ font-lock-escape-face
+--         ^ font-lock-escape-face
+
+-- Function
+func_one()
+--  ^ font-lock-function-call-face
+tbl.func_two()
+--  ^ font-lock-function-call-face
+tbl:func_three()
+--  ^ font-lock-function-call-face
+tbl.f = f4()
+--      ^ font-lock-function-call-face
+
+-- Operator
+local a, b = 1, 2
+--         ^ font-lock-operator-face
+print(a & b)
+--      ^ font-lock-operator-face
+print(a | b)
+--      ^ font-lock-operator-face
+print(a ~ b)
+--      ^ font-lock-operator-face
+print(a << 1)
+--      ^ font-lock-operator-face
+--       ^ font-lock-operator-face
+print(a >> 1)
+--      ^ font-lock-operator-face
+--       ^ font-lock-operator-face
+print(a+b-a*b/a%b^a//b)
+--     ^ font-lock-operator-face
+--       ^ font-lock-operator-face
+--         ^ font-lock-operator-face
+--           ^ font-lock-operator-face
+--             ^ font-lock-operator-face
+--               ^ font-lock-operator-face
+--                 ^ font-lock-operator-face
+print(#t)
+--    ^ font-lock-operator-face
+print("h".."at")
+--       ^ font-lock-operator-face
+print(a==b)
+--     ^ font-lock-operator-face
+print(a~=b)
+--     ^ font-lock-operator-face
+print(a<=b)
+--     ^ font-lock-operator-face
+print(a>=b)
+--     ^ font-lock-operator-face
+print(a<b)
+--     ^ font-lock-operator-face
+print(a>b)
+--     ^ font-lock-operator-face
+function ff(...) end
+--          ^ font-lock-operator-face
+
+-- Property
+t = { a=1 }
+--    ^ font-lock-property-name-face
+print(t.a)
+--      ^ font-lock-property-use-face
+
+-- Punctuation
+tbl.f2()
+-- ^ font-lock-punctuation-face
+tbl:f3()
+-- ^ font-lock-punctuation-face
+
+-- Variable
+function fn(x, y) end
+--          ^ font-lock-variable-name-face
+--             ^ font-lock-variable-name-face
+fn(a, b)
+-- ^ font-lock-variable-use-face
+--    ^ font-lock-variable-use-face
+print(a + b)
+--    ^ font-lock-variable-use-face
+--        ^ font-lock-variable-use-face
+print(t[a])
+--      ^ font-lock-variable-use-face
+tbl.f1(p)
+--     ^ font-lock-variable-use-face
+tbl:f2(q)
+--     ^ font-lock-variable-use-face
diff --git a/test/lisp/progmodes/lua-ts-mode-resources/indent.erts 
b/test/lisp/progmodes/lua-ts-mode-resources/indent.erts
index 9797467bbe5..48184160b4d 100644
--- a/test/lisp/progmodes/lua-ts-mode-resources/indent.erts
+++ b/test/lisp/progmodes/lua-ts-mode-resources/indent.erts
@@ -529,6 +529,58 @@ local Other = {
 }
 =-=-=
 
+Name: Continuation Indent
+
+=-=
+local very_long_variable_name =
+"ok"..
+      "ok"
+local n = a +
+b *
+c /
+1
+local x = "A"..
+"B"
+.."C"
+if a
+     and b
+           and c then
+             if x
+                   and y then
+    local x = 1 +
+2 *
+         3
+     end
+elseif a
+     or b
+    or c then
+end
+=-=
+local very_long_variable_name =
+  "ok"..
+  "ok"
+local n = a +
+  b *
+  c /
+  1
+local x = "A"..
+  "B"
+  .."C"
+if a
+  and b
+  and c then
+  if x
+    and y then
+    local x = 1 +
+      2 *
+      3
+  end
+elseif a
+  or b
+  or c then
+end
+=-=-=
+
 Code:
   (lambda ()
     (setq indent-tabs-mode nil)
@@ -677,3 +729,57 @@ function e (n, t)
                 end)(i(...))
 end end end
 =-=-=
+
+Code:
+  (lambda ()
+    (setq indent-tabs-mode nil)
+    (setq lua-ts-indent-continuation-lines nil)
+    (setq lua-ts-indent-offset 2)
+    (lua-ts-mode)
+    (indent-region (point-min) (point-max)))
+
+Name: Unaligned Continuation Indent
+
+=-=
+local n = a +
+  b *
+  c /
+  1
+if a
+     and b
+and c then
+ if x
+  and y then
+      local x = 1 +
+       2 *
+             3
+   end
+elseif a
+       or b
+          or c then
+          if x
+              or y
+              end
+end
+=-=
+local n = a +
+  b *
+  c /
+  1
+if a
+and b
+and c then
+  if x
+  and y then
+    local x = 1 +
+      2 *
+      3
+  end
+elseif a
+or b
+or c then
+  if x
+  or y
+  end
+end
+=-=-=
diff --git a/test/lisp/progmodes/lua-ts-mode-tests.el 
b/test/lisp/progmodes/lua-ts-mode-tests.el
index d2105b66f6d..565e6f91dbd 100644
--- a/test/lisp/progmodes/lua-ts-mode-tests.el
+++ b/test/lisp/progmodes/lua-ts-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; lua-ts-mode-tests.el --- Tests for lua-ts-mode -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -20,17 +20,23 @@
 ;;; Code:
 
 (require 'ert)
+(require 'ert-font-lock)
 (require 'ert-x)
 (require 'treesit)
 
-(ert-deftest lua-ts-mode-test-indentation ()
+(ert-deftest lua-ts-test-indentation ()
   (skip-unless (treesit-ready-p 'lua))
   (ert-test-erts-file (ert-resource-file "indent.erts")))
 
-(ert-deftest lua-ts-mode-test-movement ()
+(ert-deftest lua-ts-test-movement ()
   (skip-unless (treesit-ready-p 'lua))
   (ert-test-erts-file (ert-resource-file "movement.erts")))
 
+(ert-deftest lua-ts-test-font-lock ()
+  (skip-unless (treesit-ready-p 'lua))
+  (let ((treesit-font-lock-level 4))
+    (ert-font-lock-test-file (ert-resource-file "font-lock.lua") 
'lua-ts-mode)))
+
 (provide 'lua-ts-mode-tests)
 
 ;;; lua-ts-mode-tests.el ends here
diff --git a/test/lisp/progmodes/octave-tests.el 
b/test/lisp/progmodes/octave-tests.el
index bb7e3cd6531..8753c7eef0d 100644
--- a/test/lisp/progmodes/octave-tests.el
+++ b/test/lisp/progmodes/octave-tests.el
@@ -1,6 +1,6 @@
 ;;; octave-tests.el --- Test suite for octave.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/opascal-tests.el 
b/test/lisp/progmodes/opascal-tests.el
index 25eb2b4c1cd..e3f14def943 100644
--- a/test/lisp/progmodes/opascal-tests.el
+++ b/test/lisp/progmodes/opascal-tests.el
@@ -1,6 +1,6 @@
 ;;; opascal-tests.el --- tests for opascal.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/pascal-tests.el 
b/test/lisp/progmodes/pascal-tests.el
index db14a320a70..e7f3ee7cae7 100644
--- a/test/lisp/progmodes/pascal-tests.el
+++ b/test/lisp/progmodes/pascal-tests.el
@@ -1,6 +1,6 @@
 ;;; pascal-tests.el --- tests for pascal.el    -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/perl-mode-tests.el 
b/test/lisp/progmodes/perl-mode-tests.el
index a47a6722e20..49320566139 100644
--- a/test/lisp/progmodes/perl-mode-tests.el
+++ b/test/lisp/progmodes/perl-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; perl-mode-tests.el --- Test for perl-mode  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -45,7 +45,7 @@
     (skip-chars-forward " \t")
     (should (equal (current-column) perl-indent-level))))
 
-;;;; Re-use cperl-mode tests
+;;;; Reuse cperl-mode tests
 
 (defvar cperl-test-mode)
 (setq cperl-test-mode #'perl-mode)
diff --git a/test/lisp/progmodes/project-tests.el 
b/test/lisp/progmodes/project-tests.el
index d335864ca2e..04cdf1dea29 100644
--- a/test/lisp/progmodes/project-tests.el
+++ b/test/lisp/progmodes/project-tests.el
@@ -1,6 +1,6 @@
 ;;; project-tests.el --- tests for project.el -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Keywords:
 
diff --git a/test/lisp/progmodes/ps-mode-tests.el 
b/test/lisp/progmodes/ps-mode-tests.el
index 3d7408cda10..9bf355900b9 100644
--- a/test/lisp/progmodes/ps-mode-tests.el
+++ b/test/lisp/progmodes/ps-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; ps-mode-tests.el --- Test suite for ps-mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/python-tests.el 
b/test/lisp/progmodes/python-tests.el
index a44a11896f0..59957ff0712 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -1,6 +1,6 @@
 ;;; python-tests.el --- Test suite for python.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -474,6 +474,28 @@ def f(x: CustomInt) -> CustomInt:
      (136 . font-lock-operator-face) (137)
      (144 . font-lock-keyword-face) (150))))
 
+(ert-deftest python-font-lock-operator-1 ()
+  (python-tests-assert-faces
+   "1 << 2 ** 3 == +4%-5|~6&7^8%9"
+   '((1)
+     (3 . font-lock-operator-face) (5)
+     (8 . font-lock-operator-face) (10)
+     (13 . font-lock-operator-face) (15)
+     (16 . font-lock-operator-face) (17)
+     (18 . font-lock-operator-face) (20)
+     (21 . font-lock-operator-face) (23)
+     (24 . font-lock-operator-face) (25)
+     (26 . font-lock-operator-face) (27)
+     (28 . font-lock-operator-face) (29))))
+
+(ert-deftest python-font-lock-operator-2 ()
+  "Keyword operators are font-locked as keywords."
+  (python-tests-assert-faces
+   "is_ is None"
+   '((1)
+     (5 . font-lock-keyword-face) (7)
+     (8 . font-lock-constant-face))))
+
 (ert-deftest python-font-lock-escape-sequence-string-newline ()
   (python-tests-assert-faces
    "'\\n'
@@ -585,62 +607,70 @@ u\"\\n\""
      (845 . font-lock-string-face) (886))))
 
 (ert-deftest python-font-lock-escape-sequence-bytes-newline ()
-  :expected-result :failed
   (python-tests-assert-faces
    "b'\\n'
 b\"\\n\""
    '((1)
-     (2 . font-lock-doc-face)
+     (2 . font-lock-string-face)
      (3 . font-lock-constant-face)
-     (5 . font-lock-doc-face) (6)
-     (8 . font-lock-doc-face)
+     (5 . font-lock-string-face) (6)
+     (8 . font-lock-string-face)
      (9 . font-lock-constant-face)
-     (11 . font-lock-doc-face))))
+     (11 . font-lock-string-face))))
 
 (ert-deftest python-font-lock-escape-sequence-hex-octal ()
-  :expected-result :failed
   (python-tests-assert-faces
    "b'\\x12 \\777 \\1\\23'
 '\\x12 \\777 \\1\\23'"
    '((1)
-     (2 . font-lock-doc-face)
+     (2 . font-lock-string-face)
      (3 . font-lock-constant-face)
-     (7 . font-lock-doc-face)
+     (7 . font-lock-string-face)
      (8 . font-lock-constant-face)
-     (12 . font-lock-doc-face)
+     (12 . font-lock-string-face)
      (13 . font-lock-constant-face)
-     (18 . font-lock-doc-face) (19)
-     (20 . font-lock-doc-face)
+     (18 . font-lock-string-face) (19)
+     (20 . font-lock-string-face)
      (21 . font-lock-constant-face)
-     (25 . font-lock-doc-face)
+     (25 . font-lock-string-face)
      (26 . font-lock-constant-face)
-     (30 . font-lock-doc-face)
+     (30 . font-lock-string-face)
      (31 . font-lock-constant-face)
-     (36 . font-lock-doc-face))))
+     (36 . font-lock-string-face))))
 
 (ert-deftest python-font-lock-escape-sequence-unicode ()
-  :expected-result :failed
   (python-tests-assert-faces
    "b'\\u1234 \\U00010348 \\N{Plus-Minus Sign}'
 '\\u1234 \\U00010348 \\N{Plus-Minus Sign}'"
    '((1)
-     (2 . font-lock-doc-face) (41)
-     (42 . font-lock-doc-face)
+     (2 . font-lock-string-face) (41)
+     (42 . font-lock-string-face)
      (43 . font-lock-constant-face)
-     (49 . font-lock-doc-face)
+     (49 . font-lock-string-face)
      (50 . font-lock-constant-face)
-     (60 . font-lock-doc-face)
+     (60 . font-lock-string-face)
      (61 . font-lock-constant-face)
-     (80 . font-lock-doc-face))))
+     (80 . font-lock-string-face))))
 
 (ert-deftest python-font-lock-raw-escape-sequence ()
-  :expected-result :failed
   (python-tests-assert-faces
    "rb'\\x12 \123 \\n'
 r'\\x12 \123 \\n \\u1234 \\U00010348 \\N{Plus-Minus Sign}'"
    '((1)
-     (3 . font-lock-doc-face) (14)
-     (16 . font-lock-doc-face))))
+     (3 . font-lock-string-face) (14)
+     (16 . font-lock-string-face))))
+
+(ert-deftest python-font-lock-string-literal-concatenation ()
+  "Test for bug#45897."
+  (python-tests-assert-faces
+   "x = \"hello\"\"\"
+y = \"confused\""
+   '((1 . font-lock-variable-name-face) (2)
+     (3 . font-lock-operator-face) (4)
+     (5 . font-lock-string-face) (14)
+     (15 . font-lock-variable-name-face) (16)
+     (17 . font-lock-operator-face) (18)
+     (19 . font-lock-string-face))))
 
 
 ;;; Indentation
@@ -6647,6 +6677,15 @@ class Class:
    (python-tests-look-at "Also not a docstring")
    (should-not (python-info-docstring-p))))
 
+(ert-deftest python-info-docstring-p-8 ()
+  "Test string in the 2nd line of a buffer."
+  (python-tests-with-temp-buffer
+   "import sys
+'''Not a docstring.'''
+"
+   (python-tests-look-at "Not a docstring")
+   (should-not (python-info-docstring-p))))
+
 (ert-deftest python-info-triple-quoted-string-p-1 ()
   "Test triple quoted string."
   (python-tests-with-temp-buffer
@@ -7299,6 +7338,308 @@ buffer with overlapping strings."
                          "Unused import a.b.c (unused-import)"
                        "W0611: Unused import a.b.c (unused-import)"))))))
 
+;;; python-ts-mode font-lock tests
+
+(defmacro python-ts-tests-with-temp-buffer (contents &rest body)
+  "Create a `python-ts-mode' enabled temp buffer with CONTENTS.
+BODY is code to be executed within the temp buffer.  Point is
+always located at the beginning of buffer."
+  (declare (indent 1) (debug t))
+  `(with-temp-buffer
+     (skip-unless (treesit-ready-p 'python))
+     (require 'python)
+     (let ((python-indent-guess-indent-offset nil))
+       (python-ts-mode)
+       (setopt treesit-font-lock-level 3)
+       (insert ,contents)
+       (font-lock-ensure)
+       (goto-char (point-min))
+       ,@body)))
+
+(ert-deftest python-ts-mode-compound-keywords-face ()
+  (dolist (test '("is not" "not in"))
+    (python-ts-tests-with-temp-buffer
+     (concat "t " test " t")
+     (forward-to-word 1)
+     (should (eq (face-at-point) font-lock-keyword-face))
+     (forward-to-word 1)
+     (should (eq (face-at-point) font-lock-keyword-face)))))
+
+(ert-deftest python-ts-mode-named-assignement-face-1 ()
+  (python-ts-tests-with-temp-buffer
+   "var := 3"
+   (should (eq (face-at-point) font-lock-variable-name-face))))
+
+(ert-deftest python-ts-mode-assignement-face-2 ()
+  (python-ts-tests-with-temp-buffer
+   "var, *rest = call()"
+   (dolist (test '("var" "rest"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-variable-name-face))))
+
+  (python-ts-tests-with-temp-buffer
+   "def func(*args):"
+   (dolist (test '("args"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (not (eq (face-at-point) font-lock-variable-name-face))))))
+
+(ert-deftest python-ts-mode-nested-types-face-1 ()
+  (python-ts-tests-with-temp-buffer
+   "def func(v:dict[ list[ tuple[str] ], int | None] | None):"
+   (dolist (test '("dict" "list" "tuple" "str" "int" "None" "None"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-union-types-face-1 ()
+  (python-ts-tests-with-temp-buffer
+   "def f(val: tuple[tuple, list[Lvl1 | Lvl2[Lvl3[Lvl4[Lvl5 | None]], 
Lvl2]]]):"
+   (dolist (test '("tuple" "tuple" "list" "Lvl1" "Lvl2" "Lvl3" "Lvl4" "Lvl5" 
"None" "Lvl2"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-union-types-face-2 ()
+  (python-ts-tests-with-temp-buffer
+   "def f(val: Type0 | Type1[Type2, pack0.Type3] | pack1.pack2.Type4 | None):"
+   (dolist (test '("Type0" "Type1" "Type2" "Type3" "Type4" "None"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))
+
+   (goto-char (point-min))
+   (dolist (test '("pack0" "pack1" "pack2"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (not (eq (face-at-point) font-lock-type-face))))))
+
+(ert-deftest python-ts-mode-types-face-1 ()
+  (python-ts-tests-with-temp-buffer
+   "def f(val: Callable[[Type0], (Type1, Type2)]):"
+   (dolist (test '("Callable" "Type0" "Type1" "Type2"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-types-face-2 ()
+  (python-ts-tests-with-temp-buffer
+   "def annot3(val:pack0.Type0)->pack1.pack2.pack3.Type1:"
+   (dolist (test '("Type0" "Type1"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))
+   (goto-char (point-min))
+   (dolist (test '("pack0" "pack1" "pack2" "pack3"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (not (eq (face-at-point) font-lock-type-face))))))
+
+(ert-deftest python-ts-mode-types-face-3 ()
+  (python-ts-tests-with-temp-buffer
+   "def annot3(val:collections.abc.Iterator[Type0]):"
+   (dolist (test '("Iterator" "Type0"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))
+   (goto-char (point-min))
+   (dolist (test '("collections" "abc"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (not (eq (face-at-point) font-lock-type-face))))))
+
+(ert-deftest python-ts-mode-isinstance-type-face-1 ()
+  (python-ts-tests-with-temp-buffer
+   "isinstance(var1, pkg.Type0)
+    isinstance(var2, (str, dict, Type1, type(None)))
+    isinstance(var3, my_type())"
+
+   (dolist (test '("var1" "pkg" "var2" "type" "None" "var3" "my_type"))
+     (let ((case-fold-search nil))
+       (search-forward test))
+     (goto-char (match-beginning 0))
+     (should (not (eq (face-at-point) font-lock-type-face))))
+
+   (goto-char (point-min))
+   (dolist (test '("Type0" "str" "dict" "Type1"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-isinstance-type-face-2 ()
+  (python-ts-tests-with-temp-buffer
+   "issubclass(mytype, int|list|collections.abc.Iterable)"
+   (dolist (test '("int" "list" "Iterable"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-isinstance-type-face-3 ()
+  (python-ts-tests-with-temp-buffer
+   "issubclass(mytype, typevar1)
+    isinstance(mytype, (Type1, typevar2, tuple, abc.Coll))
+    isinstance(mytype, pkg0.Type2|self.typevar3|typevar4)"
+
+   (dolist (test '("typevar1" "typevar2" "pkg0" "self" "typevar3" "typevar4"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (not (eq (face-at-point) font-lock-type-face))))
+
+   (goto-char (point-min))
+   (dolist (test '("Type1" "tuple" "Coll" "Type2"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-superclass-type-face ()
+  (python-ts-tests-with-temp-buffer
+   "class Temp(Base1, pack0.Base2,  Sequence[T1, T2]):"
+
+   (dolist (test '("Base1" "Base2" "Sequence" "T1" "T2"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))
+
+   (goto-char (point-min))
+   (dolist (test '("pack0"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (not (eq (face-at-point) font-lock-type-face))))))
+
+(ert-deftest python-ts-mode-class-patterns-face ()
+  (python-ts-tests-with-temp-buffer
+   "match tt:
+        case str():
+            pass
+        case [Type0() | bytes(b) | pack0.pack1.Type1()]:
+            pass
+        case {'i': int(i), 'f': float() as f}:
+            pass"
+
+   (dolist (test '("str" "Type0" "bytes" "Type1" "int" "float"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))
+
+   (goto-char (point-min))
+   (dolist (test '("pack0" "pack1"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (not (eq (face-at-point) font-lock-type-face))))))
+
+(ert-deftest python-ts-mode-dotted-decorator-face-1 ()
+  (python-ts-tests-with-temp-buffer
+   "@pytest.mark.skip
+    @pytest.mark.skip(reason='msg')
+    def test():"
+
+   (dolist (test '("pytest" "mark" "skip" "pytest" "mark" "skip"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-dotted-decorator-face-2 ()
+  (python-ts-tests-with-temp-buffer
+   "@pytest.mark.skip(reason='msg')
+    def test():"
+
+   (setopt treesit-font-lock-level 4)
+   (dolist (test '("pytest" "mark" "skip"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-builtin-call-face ()
+  (python-ts-tests-with-temp-buffer
+   "all()"
+   ;; enable 'function' feature from 4th level
+   (setopt treesit-font-lock-level 4)
+   (should (eq (face-at-point) font-lock-builtin-face))))
+
+(ert-deftest python-ts-mode-interpolation-nested-string ()
+  (python-ts-tests-with-temp-buffer
+   "t = f\"beg {True + 'string'}\""
+
+   (search-forward "True")
+   (goto-char (match-beginning 0))
+   (should (eq (face-at-point) font-lock-constant-face))
+
+   (goto-char (point-min))
+   (dolist (test '("f" "{" "+" "}"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (not (eq (face-at-point) font-lock-string-face))))
+
+
+   (goto-char (point-min))
+   (dolist (test '("beg" "'string'" "\""))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-string-face)))))
+
+(ert-deftest python-ts-mode-level-fontification-wo-interpolation ()
+  (python-ts-tests-with-temp-buffer
+   "t = f\"beg {True + var}\""
+
+   (setopt treesit-font-lock-level 2)
+   (search-forward "f")
+   (goto-char (match-beginning 0))
+   (should (not (eq (face-at-point) font-lock-string-face)))
+
+   (dolist (test '("\"" "beg" "{" "True" "var" "}" "\""))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-string-face)))))
+
+(ert-deftest python-ts-mode-disabled-string-interpolation ()
+  (python-ts-tests-with-temp-buffer
+   "t = f\"beg {True + var}\""
+
+   (unwind-protect
+       (progn
+         (setf (nth 2 treesit-font-lock-feature-list)
+               (remq 'string-interpolation (nth 2 
treesit-font-lock-feature-list)))
+         (setopt treesit-font-lock-level 3)
+
+         (search-forward "f")
+         (goto-char (match-beginning 0))
+         (should (not (eq (face-at-point) font-lock-string-face)))
+
+         (dolist (test '("\"" "beg" "{" "True" "var" "}" "\""))
+           (search-forward test)
+           (goto-char (match-beginning 0))
+           (should (eq (face-at-point) font-lock-string-face))))
+
+    (setf (nth 2 treesit-font-lock-feature-list)
+          (append (nth 2 treesit-font-lock-feature-list) 
'(string-interpolation))))))
+
+(ert-deftest python-ts-mode-interpolation-doc-string ()
+  (python-ts-tests-with-temp-buffer
+   "f\"\"\"beg {'s1' + True + 's2'} end\"\"\""
+
+   (search-forward "True")
+   (goto-char (match-beginning 0))
+   (should (eq (face-at-point) font-lock-constant-face))
+
+   (goto-char (point-min))
+   (dolist (test '("f" "{" "+" "}"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (not (eq (face-at-point) font-lock-string-face))))
+
+   (goto-char (point-min))
+   (dolist (test '("\"\"\"" "beg" "end" "\"\"\""))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-doc-face)))
+
+   (goto-char (point-min))
+   (dolist (test '("'s1'" "'s2'"))
+     (search-forward test)
+     (goto-char (match-beginning 0))
+     (should (eq (face-at-point) font-lock-string-face)))))
+
 (provide 'python-tests)
 
 ;;; python-tests.el ends here
diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb 
b/test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb
index 4be532a5e9d..8e372de6e45 100644
--- a/test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb
+++ b/test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb
@@ -85,6 +85,10 @@ foo(foo, bar:
 foo(foo, :bar =>
     tee)
 
+foo = %w[
+  asd
+]
+
 # Local Variables:
 # mode: ruby-ts
 # ruby-after-operator-indent: t
diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby.rb 
b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
index 81d0dfd75c9..a411b39a8fc 100644
--- a/test/lisp/progmodes/ruby-mode-resources/ruby.rb
+++ b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
@@ -34,11 +34,11 @@ x = # "tot %q/to"; =
 # Regexp after whitelisted method.
 "abc".sub /b/, 'd'
 
-# Don't mismatch "sub" at the end of words.
-a = asub / aslb + bsub / bslb;
+# Don't mistake division for regexp.
+a = sub / aslb + bsub / bslb;
 
 # Highlight the regexp after "if".
-x = toto / foo if /do bar/ =~ "dobar"
+x = toto / foo if / do bar/ =~ "dobar"
 
 # Regexp options are highlighted.
 
diff --git a/test/lisp/progmodes/ruby-mode-tests.el 
b/test/lisp/progmodes/ruby-mode-tests.el
index 117385ea3e8..2b8506a7adc 100644
--- a/test/lisp/progmodes/ruby-mode-tests.el
+++ b/test/lisp/progmodes/ruby-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; ruby-mode-tests.el --- Test suite for ruby-mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -157,6 +157,18 @@ VALUES-PLIST is a list with alternating index and value 
elements."
 (ert-deftest ruby-regexp-is-not-mistaken-for-slash-symbol ()
   (ruby-assert-state "x = /foo:/" 3 nil))
 
+(ert-deftest ruby-slash-not-regexp-when-surrounded-by-spaces ()
+  (ruby-assert-state "x = index / 3" 3 nil))
+
+(ert-deftest ruby-slash-not-regexp-when-no-spaces ()
+  (ruby-assert-state "x = index/3" 3 nil))
+
+(ert-deftest ruby-regexp-not-division-when-only-space-before ()
+  (ruby-assert-state "x = foo_index /3" 3 ?/))
+
+(ert-deftest ruby-slash-not-regexp-when-only-space-after ()
+  (ruby-assert-state "x = index/ 3" 3 nil))
+
 (ert-deftest ruby-indent-simple ()
   (ruby-should-indent-buffer
    "if foo
diff --git a/test/lisp/progmodes/ruby-ts-mode-tests.el 
b/test/lisp/progmodes/ruby-ts-mode-tests.el
index 55782f886f6..61ef80eb610 100644
--- a/test/lisp/progmodes/ruby-ts-mode-tests.el
+++ b/test/lisp/progmodes/ruby-ts-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; ruby-mode-tests.el --- Test suite for ruby-mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/scheme-tests.el 
b/test/lisp/progmodes/scheme-tests.el
index ce41413e949..08e09883ea5 100644
--- a/test/lisp/progmodes/scheme-tests.el
+++ b/test/lisp/progmodes/scheme-tests.el
@@ -1,6 +1,6 @@
 ;;; scheme-tests.el --- Test suite for scheme.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/sh-script-tests.el 
b/test/lisp/progmodes/sh-script-tests.el
index 135d7afe3fe..e73d52399d3 100644
--- a/test/lisp/progmodes/sh-script-tests.el
+++ b/test/lisp/progmodes/sh-script-tests.el
@@ -1,6 +1,6 @@
 ;;; sh-script-tests.el --- Tests for sh-script.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/sql-tests.el b/test/lisp/progmodes/sql-tests.el
index b0a1f8b0519..0ba7c31acc5 100644
--- a/test/lisp/progmodes/sql-tests.el
+++ b/test/lisp/progmodes/sql-tests.el
@@ -1,6 +1,6 @@
 ;;; sql-tests.el --- Tests for sql.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/progmodes/subword-tests.el 
b/test/lisp/progmodes/subword-tests.el
index 278db9287ef..592bc794d8b 100644
--- a/test/lisp/progmodes/subword-tests.el
+++ b/test/lisp/progmodes/subword-tests.el
@@ -1,6 +1,6 @@
 ;;; subword-tests.el --- Testing the subword rules  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords:
diff --git a/test/lisp/progmodes/tcl-tests.el b/test/lisp/progmodes/tcl-tests.el
index 7d3a67d1610..ddb5c4e040b 100644
--- a/test/lisp/progmodes/tcl-tests.el
+++ b/test/lisp/progmodes/tcl-tests.el
@@ -1,6 +1,6 @@
 ;;; tcl-tests.el --- Test suite for tcl-mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/progmodes/typescript-ts-mode-tests.el 
b/test/lisp/progmodes/typescript-ts-mode-tests.el
index 126f5e3298f..effd9551fb0 100644
--- a/test/lisp/progmodes/typescript-ts-mode-tests.el
+++ b/test/lisp/progmodes/typescript-ts-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; typescript-ts-mode-tests.el --- Tests for Tree-sitter-based TypeScript 
mode  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -24,7 +24,8 @@
 (require 'treesit)
 
 (ert-deftest typescript-ts-mode-test-indentation ()
-  (skip-unless (treesit-ready-p 'typescript))
+  (skip-unless (and (treesit-ready-p 'typescript)
+                    (treesit-ready-p 'tsx)))
   (ert-test-erts-file (ert-resource-file "indent.erts")))
 
 (provide 'typescript-ts-mode-tests)
diff --git a/test/lisp/progmodes/which-func-tests.el 
b/test/lisp/progmodes/which-func-tests.el
index 73709f1c5e5..0baee576463 100644
--- a/test/lisp/progmodes/which-func-tests.el
+++ b/test/lisp/progmodes/which-func-tests.el
@@ -1,6 +1,6 @@
 ;;; which-func-tests.el --- tests for which-func     -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: Spencer Baugh <sbaugh@catern.com>
 
diff --git a/test/lisp/progmodes/xref-tests.el 
b/test/lisp/progmodes/xref-tests.el
index e74f38cb616..89051256273 100644
--- a/test/lisp/progmodes/xref-tests.el
+++ b/test/lisp/progmodes/xref-tests.el
@@ -1,6 +1,6 @@
 ;;; xref-tests.el --- tests for xref  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Dmitry Gutov <dgutov@yandex.ru>
 
diff --git a/test/lisp/ps-print-tests.el b/test/lisp/ps-print-tests.el
index 05a74ebf241..bb1cd3f1891 100644
--- a/test/lisp/ps-print-tests.el
+++ b/test/lisp/ps-print-tests.el
@@ -1,6 +1,6 @@
 ;;; ps-print-tests.el --- Test suite for ps-print.el  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Phillip Lord <phillip.lord@russet.org.uk>
 
diff --git a/test/lisp/buff-menu-tests.el b/test/lisp/register-tests.el
similarity index 52%
copy from test/lisp/buff-menu-tests.el
copy to test/lisp/register-tests.el
index b3a54093c54..bbb470c0aa1 100644
--- a/test/lisp/buff-menu-tests.el
+++ b/test/lisp/register-tests.el
@@ -1,8 +1,9 @@
-;;; buff-menu-tests.el --- Test suite for buff-menu.el -*- lexical-binding: t 
-*-
+;;; register-tests.el --- tests for register.el  -*- lexical-binding: t-*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Tino Calancha <tino.calancha@gmail.com>
+;; Keywords:
 
 ;; This file is part of GNU Emacs.
 
@@ -21,24 +22,22 @@
 
 ;;; Commentary:
 
+
 ;;; Code:
-
 (require 'ert)
-(eval-when-compile (require 'ert-x))
-
-(ert-deftest buff-menu-24962 ()
-  "Test for https://debbugs.gnu.org/24962 ."
-  (ert-with-temp-file file
-    :suffix "foo"
-    (let ((buf (find-file file)))
-      (unwind-protect
-          (progn
-            (rename-buffer " foo")
-            (list-buffers)
-            (with-current-buffer "*Buffer List*"
-              (should (string= " foo" (buffer-name (Buffer-menu-buffer))))))
-        (and (buffer-live-p buf) (kill-buffer buf))))))
-
-(provide 'buff-menu-tests)
-
-;;; buff-menu-tests.el ends here
+(require 'cl-lib)
+
+(ert-deftest register-test-bug27634 ()
+  "Test for https://debbugs.gnu.org/27634 ."
+  (dolist (event (list ?\C-g 'escape ?\C-\[))
+    (cl-letf (((symbol-function 'read-key) #'ignore)
+              (last-input-event event)
+              (register-alist nil))
+      (should (equal 'quit
+                     (condition-case err
+                         (call-interactively 'point-to-register)
+                       (quit (car err)))))
+      (should-not register-alist))))
+
+(provide 'register-tests)
+;;; register-tests.el ends here
diff --git a/test/lisp/repeat-tests.el b/test/lisp/repeat-tests.el
index 64a7ba2cde9..4e86510f19b 100644
--- a/test/lisp/repeat-tests.el
+++ b/test/lisp/repeat-tests.el
@@ -1,6 +1,6 @@
 ;;; repeat-tests.el --- Tests for repeat.el          -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Juri Linkov <juri@linkov.net>
 
diff --git a/test/lisp/replace-tests.el b/test/lisp/replace-tests.el
index 899c3cb3c6c..11260204750 100644
--- a/test/lisp/replace-tests.el
+++ b/test/lisp/replace-tests.el
@@ -1,6 +1,6 @@
 ;;; replace-tests.el --- tests for replace.el.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Richard <youngfrog@members.fsf.org>
 ;; Author: Juri Linkov <juri@jurta.org>
diff --git a/test/lisp/rot13-tests.el b/test/lisp/rot13-tests.el
index 788a80f368c..8025081a6e5 100644
--- a/test/lisp/rot13-tests.el
+++ b/test/lisp/rot13-tests.el
@@ -1,6 +1,6 @@
 ;;; rot13-tests.el --- Tests for rot13.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/saveplace-tests.el b/test/lisp/saveplace-tests.el
index 3c0b14c8c03..dca888555cc 100644
--- a/test/lisp/saveplace-tests.el
+++ b/test/lisp/saveplace-tests.el
@@ -1,6 +1,6 @@
 ;;; saveplace-tests.el --- Tests for saveplace.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/scroll-lock-tests.el b/test/lisp/scroll-lock-tests.el
index b8d3d82bd5b..288693f72d2 100644
--- a/test/lisp/scroll-lock-tests.el
+++ b/test/lisp/scroll-lock-tests.el
@@ -1,6 +1,6 @@
 ;;; scroll-lock-tests.el --- Test suite for scroll-lock -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/server-tests.el b/test/lisp/server-tests.el
index de1aa80c272..420338346f1 100644
--- a/test/lisp/server-tests.el
+++ b/test/lisp/server-tests.el
@@ -1,6 +1,6 @@
 ;;; server-tests.el --- Emacs server test suite  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/ses-tests.el b/test/lisp/ses-tests.el
index a941605a4d8..a916aed9eb3 100644
--- a/test/lisp/ses-tests.el
+++ b/test/lisp/ses-tests.el
@@ -1,6 +1,6 @@
-;;; ses-tests.el --- Tests for ses.el              -*- lexical-binding: t; -*-
+;;; SES-tests.el --- Tests for ses.el              -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Vincent Belaïche <vincentb1@users.sourceforge.net>
 
@@ -241,6 +241,28 @@ to `ses--bar' and inserting a row, makes A2 value empty, 
and `ses--bar' equal to
       (ses-command-hook)
       (should (eq (ses--cell-at-pos (point)) 'ses--toto)))))
 
+(ert-deftest ses-set-formula-write-cells-with-changed-references ()
+  "Test fix of bug#5852.
+When setting a formula has some cell with changed references, this
+cell has to be rewritten to data area."
+  (let ((ses-initial-size '(4 . 3))
+        (ses-after-entry-functions nil))
+    (with-temp-buffer
+      (ses-mode)
+      (dolist (c '((0 1 1); B1
+                   (1 0 2) (1 1 (+ B1 A2)); A2 B2
+                   (2 0 4); A3
+                   (3 0 3) (3 1 (+ B2 A4))));A4 B4
+        (apply 'ses-cell-set-formula c)
+        (apply 'ses-calculate-cell (list (car c) (cadr c) nil)))
+      (ses-cell-set-formula 2 1 '(+ B2 A3)); B3
+      (ses-command-hook)
+      (ses-cell-set-formula 3 1 '(+ B3 A4)); B4
+      (ses-command-hook)
+      (should (equal (ses-cell-references 1 1) '(B3)))
+      (ses-mode)
+      (should (equal (ses-cell-references 1 1) '(B3))))))
+
 (provide 'ses-tests)
 
 ;;; ses-tests.el ends here
diff --git a/test/lisp/shadowfile-tests.el b/test/lisp/shadowfile-tests.el
index b1c06ad2d05..4485c73a7bc 100644
--- a/test/lisp/shadowfile-tests.el
+++ b/test/lisp/shadowfile-tests.el
@@ -1,6 +1,6 @@
 ;;; shadowfile-tests.el --- Tests of shadowfile  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 
diff --git a/test/lisp/shell-tests.el b/test/lisp/shell-tests.el
index ddddfdb2e0f..9bdf6b1c0eb 100644
--- a/test/lisp/shell-tests.el
+++ b/test/lisp/shell-tests.el
@@ -1,6 +1,6 @@
 ;;; shell-tests.el --- Tests for shell.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el
index b632c908443..afd75786804 100644
--- a/test/lisp/simple-tests.el
+++ b/test/lisp/simple-tests.el
@@ -1,6 +1,6 @@
 ;;; simple-tests.el --- Tests for simple.el           -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
 
diff --git a/test/lisp/so-long-tests/autoload-longlines-mode-tests.el 
b/test/lisp/so-long-tests/autoload-longlines-mode-tests.el
index f015103eecb..771f6c3085a 100644
--- a/test/lisp/so-long-tests/autoload-longlines-mode-tests.el
+++ b/test/lisp/so-long-tests/autoload-longlines-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; autoload-longlines-mode-tests.el --- Test suite for so-long.el  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Phil Sainty <psainty@orcon.net.nz>
 ;; Keywords: convenience
diff --git a/test/lisp/so-long-tests/autoload-major-mode-tests.el 
b/test/lisp/so-long-tests/autoload-major-mode-tests.el
index a3bed852f60..baa50275472 100644
--- a/test/lisp/so-long-tests/autoload-major-mode-tests.el
+++ b/test/lisp/so-long-tests/autoload-major-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; autoload-major-mode-tests.el --- Test suite for so-long.el  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Phil Sainty <psainty@orcon.net.nz>
 ;; Keywords: convenience
diff --git a/test/lisp/so-long-tests/autoload-minor-mode-tests.el 
b/test/lisp/so-long-tests/autoload-minor-mode-tests.el
index c4545c8dd0b..23d9a433110 100644
--- a/test/lisp/so-long-tests/autoload-minor-mode-tests.el
+++ b/test/lisp/so-long-tests/autoload-minor-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; autoload-minor-mode-tests.el --- Test suite for so-long.el  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Phil Sainty <psainty@orcon.net.nz>
 ;; Keywords: convenience
diff --git a/test/lisp/so-long-tests/so-long-tests-helpers.el 
b/test/lisp/so-long-tests/so-long-tests-helpers.el
index 21f96602fbe..324cbbefed3 100644
--- a/test/lisp/so-long-tests/so-long-tests-helpers.el
+++ b/test/lisp/so-long-tests/so-long-tests-helpers.el
@@ -1,6 +1,6 @@
 ;;; so-long-tests-helpers.el --- Test suite for so-long.el  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Phil Sainty <psainty@orcon.net.nz>
 ;; Keywords: convenience
diff --git a/test/lisp/so-long-tests/so-long-tests.el 
b/test/lisp/so-long-tests/so-long-tests.el
index d725c07d881..b9326ce54ba 100644
--- a/test/lisp/so-long-tests/so-long-tests.el
+++ b/test/lisp/so-long-tests/so-long-tests.el
@@ -1,6 +1,6 @@
 ;;; so-long-tests.el --- Test suite for so-long.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Phil Sainty <psainty@orcon.net.nz>
 ;; Keywords: convenience
diff --git a/test/lisp/so-long-tests/spelling-tests.el 
b/test/lisp/so-long-tests/spelling-tests.el
index 5e5d1d34c71..6fb5f2d5f58 100644
--- a/test/lisp/so-long-tests/spelling-tests.el
+++ b/test/lisp/so-long-tests/spelling-tests.el
@@ -1,6 +1,6 @@
 ;;; spelling-tests.el --- Test suite for so-long.el  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Phil Sainty <psainty@orcon.net.nz>
 ;; Keywords: convenience
diff --git a/test/lisp/sort-tests.el b/test/lisp/sort-tests.el
index d8af5595a5e..bbf349350dd 100644
--- a/test/lisp/sort-tests.el
+++ b/test/lisp/sort-tests.el
@@ -1,6 +1,6 @@
 ;;; sort-tests.el --- Tests for sort.el              -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
 
diff --git a/test/lisp/soundex-tests.el b/test/lisp/soundex-tests.el
index 47d6394df03..afe2a56ebd9 100644
--- a/test/lisp/soundex-tests.el
+++ b/test/lisp/soundex-tests.el
@@ -1,6 +1,6 @@
 ;;; soundex-tests.el --- tests for soundex.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 
diff --git a/test/lisp/startup-tests.el b/test/lisp/startup-tests.el
index 3e71d8ccec5..46654d1a80f 100644
--- a/test/lisp/startup-tests.el
+++ b/test/lisp/startup-tests.el
@@ -1,6 +1,6 @@
 ;;; startup-tests.el --- unit tests for startup.el   -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Philipp Stephani <phst@google.com>
 
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index f485328aa7a..4e3f743cc93 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -1,6 +1,6 @@
 ;;; subr-tests.el --- Tests for subr.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Oleh Krehel <ohwoeowho@gmail.com>,
 ;;         Nicolas Petton <nicolas@petton.fr>
diff --git a/test/lisp/tab-bar-tests.el b/test/lisp/tab-bar-tests.el
index 543bb8717fe..aa8384b24e8 100644
--- a/test/lisp/tab-bar-tests.el
+++ b/test/lisp/tab-bar-tests.el
@@ -1,6 +1,6 @@
 ;;; tab-bar-tests.el --- Tests for tab-bar.el          -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Juri Linkov <juri@linkov.net>
 
diff --git a/test/lisp/tabify-tests.el b/test/lisp/tabify-tests.el
index 5ff2f311296..f8348e52386 100644
--- a/test/lisp/tabify-tests.el
+++ b/test/lisp/tabify-tests.el
@@ -1,6 +1,6 @@
 ;;; tabify-tests.el --- tests for tabify.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/tar-mode-tests.el b/test/lisp/tar-mode-tests.el
index 919602ecef2..b40cd39d112 100644
--- a/test/lisp/tar-mode-tests.el
+++ b/test/lisp/tar-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; tar-mode-tests.el --- Test suite for tar-mode. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/tempo-tests.el b/test/lisp/tempo-tests.el
index 89edccf4fa7..ba3ca670286 100644
--- a/test/lisp/tempo-tests.el
+++ b/test/lisp/tempo-tests.el
@@ -1,6 +1,6 @@
 ;;; tempo-tests.el --- Test suite for tempo.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Federico Tedin <federicotedin@gmail.com>
 ;; Keywords: abbrev
diff --git a/test/lisp/term-tests.el b/test/lisp/term-tests.el
index 911d03d5628..f5209d6f580 100644
--- a/test/lisp/term-tests.el
+++ b/test/lisp/term-tests.el
@@ -1,6 +1,6 @@
 ;;; term-tests.el --- tests for term.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017, 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017, 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/term/tty-colors-tests.el 
b/test/lisp/term/tty-colors-tests.el
index 934e635183c..ef7c839295a 100644
--- a/test/lisp/term/tty-colors-tests.el
+++ b/test/lisp/term/tty-colors-tests.el
@@ -1,6 +1,6 @@
 ;;; tty-colors-tests.el --- tests for tty-colors.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/textmodes/bibtex-tests.el 
b/test/lisp/textmodes/bibtex-tests.el
index 5e53cab3515..d2721d2829f 100644
--- a/test/lisp/textmodes/bibtex-tests.el
+++ b/test/lisp/textmodes/bibtex-tests.el
@@ -1,6 +1,6 @@
 ;;; bibtex-tests.el --- Test suite for bibtex.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Keywords: bibtex
 
diff --git a/test/lisp/textmodes/conf-mode-tests.el 
b/test/lisp/textmodes/conf-mode-tests.el
index 677a6d35d66..343342be886 100644
--- a/test/lisp/textmodes/conf-mode-tests.el
+++ b/test/lisp/textmodes/conf-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; conf-mode-tests.el --- Test suite for conf mode  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: J. Alexander Branham <alex.branham@gmail.com>
 ;; Keywords: internal
diff --git a/test/lisp/textmodes/css-mode-tests.el 
b/test/lisp/textmodes/css-mode-tests.el
index 9a5f4fcc92a..290b73f7e85 100644
--- a/test/lisp/textmodes/css-mode-tests.el
+++ b/test/lisp/textmodes/css-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; css-mode-tests.el --- Test suite for CSS mode  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords: internal
diff --git a/test/lisp/textmodes/dns-mode-tests.el 
b/test/lisp/textmodes/dns-mode-tests.el
index f9c81b7f842..197dde6f6a0 100644
--- a/test/lisp/textmodes/dns-mode-tests.el
+++ b/test/lisp/textmodes/dns-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; dns-mode-tests.el --- Test suite for dns-mode  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Peder O. Klingenberg <peder@klingenberg.no>
 ;; Keywords: dns zone
diff --git a/test/lisp/textmodes/emacs-news-mode-tests.el 
b/test/lisp/textmodes/emacs-news-mode-tests.el
index 676a3270da6..5894114b20a 100644
--- a/test/lisp/textmodes/emacs-news-mode-tests.el
+++ b/test/lisp/textmodes/emacs-news-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; emacs-news-mode-tests.el --- Tests for emacs-news-mode.el  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/textmodes/fill-tests.el 
b/test/lisp/textmodes/fill-tests.el
index ef822ba805b..484f6ed395b 100644
--- a/test/lisp/textmodes/fill-tests.el
+++ b/test/lisp/textmodes/fill-tests.el
@@ -1,9 +1,9 @@
 ;;; fill-tests.el --- ERT tests for fill.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author:     Marcin Borkowski <mbork@mbork.pl>
-;; Keywords:   text, wp
+;; Keywords:   text
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/textmodes/mhtml-mode-tests.el 
b/test/lisp/textmodes/mhtml-mode-tests.el
index ec48188fc11..c9e0dc8f888 100644
--- a/test/lisp/textmodes/mhtml-mode-tests.el
+++ b/test/lisp/textmodes/mhtml-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; mhtml-mode-tests.el --- Tests for mhtml-mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Keywords: tests
 
diff --git a/test/lisp/textmodes/page-tests.el 
b/test/lisp/textmodes/page-tests.el
index 4bfa8d9941c..fdefca36c0b 100644
--- a/test/lisp/textmodes/page-tests.el
+++ b/test/lisp/textmodes/page-tests.el
@@ -1,6 +1,6 @@
 ;;; page-tests.el --- Tests for page.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
@@ -106,10 +106,14 @@
     (insert "foo\n\nbar\n\nbaz")
     (goto-char (point-min))
     (should (equal (page--what-page) '(1 1)))
+    (forward-char)
+    (should (equal (page--what-page) '(1 1)))
     (forward-page)
+    (should (equal (page--what-page) '(2 1)))
+    (forward-line)
     (should (equal (page--what-page) '(2 2)))
     (forward-page)
-    (should (equal (page--what-page) '(3 4)))))
+    (should (equal (page--what-page) '(3 1)))))
 
 
 ;;; page-tests.el ends here
diff --git a/test/lisp/textmodes/paragraphs-tests.el 
b/test/lisp/textmodes/paragraphs-tests.el
index 81e88113c2a..ff8cdfe8b44 100644
--- a/test/lisp/textmodes/paragraphs-tests.el
+++ b/test/lisp/textmodes/paragraphs-tests.el
@@ -1,6 +1,6 @@
 ;;; paragraphs-tests.el --- Tests for paragraphs.el  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/textmodes/po-tests.el b/test/lisp/textmodes/po-tests.el
index 2bfb0dd5330..a9b405df609 100644
--- a/test/lisp/textmodes/po-tests.el
+++ b/test/lisp/textmodes/po-tests.el
@@ -1,6 +1,6 @@
 ;;; po-tests.el --- Tests for po.el                  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Simen Heggestøyl <simenheg@gmail.com>
 ;; Keywords:
diff --git a/test/lisp/textmodes/reftex-tests.el 
b/test/lisp/textmodes/reftex-tests.el
index 6aa12bc3b58..7f7c99a40a4 100644
--- a/test/lisp/textmodes/reftex-tests.el
+++ b/test/lisp/textmodes/reftex-tests.el
@@ -1,6 +1,6 @@
 ;;; reftex-tests.el --- Test suite for reftex. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
 ;; Keywords:       internal
diff --git a/test/lisp/textmodes/sgml-mode-tests.el 
b/test/lisp/textmodes/sgml-mode-tests.el
index 57467483bfe..f74fe84f1bd 100644
--- a/test/lisp/textmodes/sgml-mode-tests.el
+++ b/test/lisp/textmodes/sgml-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; sgml-mode-tests.el --- Tests for sgml-mode  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Przemysław Wojnowski <esperanto@cumego.com>
 ;; Keywords: tests
diff --git a/test/lisp/textmodes/texinfo-tests.el 
b/test/lisp/textmodes/texinfo-tests.el
index 37a461167e9..b4bbcbc0ab1 100644
--- a/test/lisp/textmodes/texinfo-tests.el
+++ b/test/lisp/textmodes/texinfo-tests.el
@@ -1,6 +1,6 @@
 ;;; texinfo-tests.el --- Tests for texinfo.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/textmodes/tildify-tests.el 
b/test/lisp/textmodes/tildify-tests.el
index 962aeb4747c..b6bdae5edd5 100644
--- a/test/lisp/textmodes/tildify-tests.el
+++ b/test/lisp/textmodes/tildify-tests.el
@@ -1,10 +1,10 @@
 ;;; tildify-tests.el --- ERT tests for tildify.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author:     Michal Nazarewicz <mina86@mina86.com>
 ;; Version:    4.5
-;; Keywords:   text, TeX, SGML, wp
+;; Keywords:   text, TeX, SGML
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/textmodes/underline-tests.el 
b/test/lisp/textmodes/underline-tests.el
index d0f899f8f5c..bf3fcaa13d1 100644
--- a/test/lisp/textmodes/underline-tests.el
+++ b/test/lisp/textmodes/underline-tests.el
@@ -1,6 +1,6 @@
 ;;; underline-tests.el --- Tests for underline.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/thingatpt-tests.el b/test/lisp/thingatpt-tests.el
index 7cf41d2817b..ba51f375cc6 100644
--- a/test/lisp/thingatpt-tests.el
+++ b/test/lisp/thingatpt-tests.el
@@ -1,6 +1,6 @@
 ;;; thingatpt-tests.el --- tests for thing-at-point.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -85,16 +85,16 @@
     ("<foo@example.com>" 5 email "<foo@example.com>")
     ("<foo@example.com>" 16 email "<foo@example.com>")
     ("<foo@example.com>" 17 email "<foo@example.com>")
-    ;; email adresses containing numbers
+    ;; email addresses containing numbers
     ("foo1@example.com" 1 email "foo1@example.com")
     ("1foo@example.com" 1 email "1foo@example.com")
     ("11@example.com" 1 email "11@example.com")
     ("1@example.com" 1 email "1@example.com")
-    ;; email adresses user portion containing dots
+    ;; email addresses user portion containing dots
     ("foo.bar@example.com" 1 email "foo.bar@example.com")
     (".foobar@example.com" 1 email nil)
     (".foobar@example.com" 2 email "foobar@example.com")
-    ;; email adresses domain portion containing dots and dashes
+    ;; email addresses domain portion containing dots and dashes
     ("foobar@.example.com" 1 email nil)
     ("foobar@-example.com" 1 email "foobar@-example.com")
     ;; These are illegal, but thingatpt doesn't yet handle them
diff --git a/test/lisp/thread-tests.el b/test/lisp/thread-tests.el
index 5d684a96a18..c0f8396e6ec 100644
--- a/test/lisp/thread-tests.el
+++ b/test/lisp/thread-tests.el
@@ -1,6 +1,6 @@
 ;;; thread-tests.el --- Test suite for thread.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Gemini Lasswell <gazally@runbox.com>
 ;; Keywords: threads
diff --git a/test/lisp/time-stamp-tests.el b/test/lisp/time-stamp-tests.el
index c1036f636e5..a4c30d64225 100644
--- a/test/lisp/time-stamp-tests.el
+++ b/test/lisp/time-stamp-tests.el
@@ -1,6 +1,6 @@
 ;;; time-stamp-tests.el --- tests for time-stamp.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/time-tests.el b/test/lisp/time-tests.el
index 359f3ea3313..1c63e87d786 100644
--- a/test/lisp/time-tests.el
+++ b/test/lisp/time-tests.el
@@ -1,6 +1,6 @@
 ;;; time-tests.el --- Tests for time.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/timezone-tests.el b/test/lisp/timezone-tests.el
index 5f8896656cc..484477e0428 100644
--- a/test/lisp/timezone-tests.el
+++ b/test/lisp/timezone-tests.el
@@ -1,6 +1,6 @@
 ;;; timezone-tests.el --- Tests for timezone.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/lisp/uniquify-tests.el b/test/lisp/uniquify-tests.el
index 38510c3bd77..4124ce056d3 100644
--- a/test/lisp/uniquify-tests.el
+++ b/test/lisp/uniquify-tests.el
@@ -1,6 +1,6 @@
 ;;; uniquify-tests.el --- Tests for uniquify         -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: Spencer Baugh <sbaugh@janestreet.com>
 
diff --git a/test/lisp/url/url-auth-tests.el b/test/lisp/url/url-auth-tests.el
index 5527d3a3bfc..d9262a24870 100644
--- a/test/lisp/url/url-auth-tests.el
+++ b/test/lisp/url/url-auth-tests.el
@@ -1,6 +1,6 @@
 ;;; url-auth-tests.el --- Test suite for url-auth.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Jarno Malmari <jarno@malmari.fi>
 
diff --git a/test/lisp/url/url-domsuf-tests.el 
b/test/lisp/url/url-domsuf-tests.el
index 8dbf65dae44..cae25d8e04e 100644
--- a/test/lisp/url/url-domsuf-tests.el
+++ b/test/lisp/url/url-domsuf-tests.el
@@ -1,6 +1,6 @@
 ;;; url-domsuf-tests.el --- Tests for url-domsuf.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/url/url-expand-tests.el 
b/test/lisp/url/url-expand-tests.el
index 651bd690811..127c18b73b6 100644
--- a/test/lisp/url/url-expand-tests.el
+++ b/test/lisp/url/url-expand-tests.el
@@ -1,9 +1,8 @@
 ;;; url-expand-tests.el --- Test suite for relative URI/URL resolution.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Alain Schneble <a.s@realize.ch>
-;; Version: 1.0
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/url/url-file-tests.el b/test/lisp/url/url-file-tests.el
index 4c3bcc9163e..a841195e8c4 100644
--- a/test/lisp/url/url-file-tests.el
+++ b/test/lisp/url/url-file-tests.el
@@ -1,6 +1,6 @@
 ;;; url-file-tests.el --- Test suite for url-file. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/url/url-future-tests.el 
b/test/lisp/url/url-future-tests.el
index 18e6e31c8ce..af56fb59ee0 100644
--- a/test/lisp/url/url-future-tests.el
+++ b/test/lisp/url/url-future-tests.el
@@ -1,6 +1,6 @@
 ;;; url-future-tests.el --- Test suite for url-future.  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Teodor Zlatanov <tzz@lifelogs.com>
 ;; Keywords: data
diff --git a/test/lisp/url/url-handlers-tests.el 
b/test/lisp/url/url-handlers-tests.el
index 68afee4ce93..eef6050886a 100644
--- a/test/lisp/url/url-handlers-tests.el
+++ b/test/lisp/url/url-handlers-tests.el
@@ -1,6 +1,6 @@
 ;;; url-handlers-tests.el --- Test suite for url-handlers.el  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Petton <nicolas@petton.fr>
 
diff --git a/test/lisp/url/url-misc-tests.el b/test/lisp/url/url-misc-tests.el
index 8d2e20f11d0..432aa6c0e6c 100644
--- a/test/lisp/url/url-misc-tests.el
+++ b/test/lisp/url/url-misc-tests.el
@@ -1,6 +1,6 @@
 ;;; url-misc-tests.el --- Test suite for url-misc. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/url/url-parse-tests.el b/test/lisp/url/url-parse-tests.el
index cf75738d00a..6882ed26932 100644
--- a/test/lisp/url/url-parse-tests.el
+++ b/test/lisp/url/url-parse-tests.el
@@ -1,9 +1,8 @@
 ;;; url-parse-tests.el --- Test suite for URI/URL parsing.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Alain Schneble <a.s@realize.ch>
-;; Version: 1.0
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/url/url-tramp-tests.el b/test/lisp/url/url-tramp-tests.el
index b31913c8371..1751b4ed603 100644
--- a/test/lisp/url/url-tramp-tests.el
+++ b/test/lisp/url/url-tramp-tests.el
@@ -1,6 +1,6 @@
 ;;; url-tramp-tests.el --- Test suite for Tramp / URL conversion.  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 
diff --git a/test/lisp/url/url-util-tests.el b/test/lisp/url/url-util-tests.el
index 092a25ebfff..133aa0ffd88 100644
--- a/test/lisp/url/url-util-tests.el
+++ b/test/lisp/url/url-util-tests.el
@@ -1,6 +1,6 @@
 ;;; url-util-tests.el --- Test suite for url-util.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Teodor Zlatanov <tzz@lifelogs.com>
 ;; Keywords: data
diff --git a/test/lisp/use-package/use-package-tests.el 
b/test/lisp/use-package/use-package-tests.el
index ddf1f2e450d..4622379921e 100644
--- a/test/lisp/use-package/use-package-tests.el
+++ b/test/lisp/use-package/use-package-tests.el
@@ -1,6 +1,6 @@
 ;;; use-package-tests.el --- Tests for use-package.el  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/vc/add-log-tests.el b/test/lisp/vc/add-log-tests.el
index 07da65c74f6..510807dc825 100644
--- a/test/lisp/vc/add-log-tests.el
+++ b/test/lisp/vc/add-log-tests.el
@@ -1,6 +1,6 @@
 ;;; add-log-tests.el --- Test suite for add-log.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Masatake YAMATO <yamato@redhat.com>
 ;; Keywords: vc tools
diff --git a/test/lisp/vc/diff-mode-tests.el b/test/lisp/vc/diff-mode-tests.el
index 8033dc9cbbd..5ab159c7ab6 100644
--- a/test/lisp/vc/diff-mode-tests.el
+++ b/test/lisp/vc/diff-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; diff-mode-tests.el --- Tests for diff-mode.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Dima Kogan <dima@secretsauce.net>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/vc/ediff-diff-tests.el b/test/lisp/vc/ediff-diff-tests.el
index b250148da8d..8ee6bdc2559 100644
--- a/test/lisp/vc/ediff-diff-tests.el
+++ b/test/lisp/vc/ediff-diff-tests.el
@@ -1,6 +1,6 @@
 ;;; ediff-diff-tests.el --- Unit tests for ediff-diff.el  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Philipp Stephani <phst@google.com>
 
diff --git a/test/lisp/vc/ediff-ptch-tests.el b/test/lisp/vc/ediff-ptch-tests.el
index 74701ee1802..7b8ff7ebc1a 100644
--- a/test/lisp/vc/ediff-ptch-tests.el
+++ b/test/lisp/vc/ediff-ptch-tests.el
@@ -1,6 +1,6 @@
 ;;; ediff-ptch-tests.el --- Tests for ediff-ptch.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Tino Calancha <tino.calancha@gmail.com>
 
diff --git a/test/lisp/vc/log-edit-tests.el b/test/lisp/vc/log-edit-tests.el
index 237b743aa24..8373156587d 100644
--- a/test/lisp/vc/log-edit-tests.el
+++ b/test/lisp/vc/log-edit-tests.el
@@ -1,6 +1,6 @@
 ;;; log-edit-tests.el --- Unit tests for log-edit.el  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -134,4 +134,214 @@ lines."))))
 * 
a-very-long-directory-name/another-long-directory-name/and-a-long-file-name.ext
 \(a-really-long-function-name):"))))
 
+(ert-deftest log-edit-fill-entry-confinement ()
+  (let (string string1 string2 string3 string4)
+    (setq string
+          ;; This entry is precisely 65 columns in length;
+          ;; log-edit-fill-column should leave it unmodified.
+          "* file2.txt (fun4, fun5, fun6, fun7, fun8, fun9, fun10, fun1134):"
+          string1
+          ;; This entry is 66 columns in length, and must be filled.
+          "* file2.txt (fun4, fun5, fun6, fun7, fun8, fun9, fun10, fun11345):"
+          string2
+          ;; The first line of this entry totals 65 columns in length,
+          ;; and should be preserved intact.
+          "* file2.txt (fun4, fun5, fun6, fun7, fun8, fun9, fun10, fun11345)
+(fun11356):"
+          string3
+          ;; The first defun in this entry is a file name that brings
+          ;; the total to 40 columns in length and should be preserved
+          ;; intact.
+          "* file2.txt (abcdefghijklmnopqrstuvwxyz)
+(ABC):"
+          string4
+          ;; The first defun brings that total to 41, and should be
+          ;; placed on the next line.
+          "* file2.txt (abcdefghijklmnopqrstuvwxyz):")
+    (with-temp-buffer
+      (insert string)
+      (let ((fill-column 64)) (log-edit-fill-entry))
+      (should (equal (buffer-string) string))
+      (erase-buffer)
+      (insert string1)
+      (let ((fill-column 64)) (log-edit-fill-entry))
+      (should (equal (buffer-string)
+                     "* file2.txt (fun4, fun5, fun6, fun7, fun8, fun9, fun10)
+(fun11345):"))
+      (erase-buffer)
+      (insert string2)
+      (let ((fill-column 64)) (log-edit-fill-entry))
+      (should (equal (buffer-string) string2))
+      (erase-buffer)
+      (insert string3)
+      (let ((fill-column 39)) (log-edit-fill-entry))
+      (should (equal (buffer-string) string3))
+      (erase-buffer)
+      (insert string4)
+      (let ((fill-column 39)) (log-edit-fill-entry))
+      (should (equal (buffer-string)
+                     ;; There is whitespace after "file2.txt" which
+                     ;; should not be erased!
+                     "* file2.txt 
+(abcdefghijklmnopqrstuvwxyz):")))))
+
+(ert-deftest log-edit-fill-entry-space-substitution ()
+  ;; This test verifies that filling the paragraph surrounding the
+  ;; last line of defuns does not break between defun lists with
+  ;; spaces in identifiers.
+  (let (string wanted)
+    (setq string "
+* src/sfnt.c (xmalloc, xrealloc): Improve behavior upon allocation
+failures during test.
+(sfnt_table_names): Add prep.
+(sfnt_transform_coordinates): Allow applying offsets during
+coordinate transform.
+(sfnt_decompose_compound_glyph): Defer offset computation until
+any component compound glyph is loaded, then apply it during the
+transform process.
+(sfnt_multiply_divide): Make available everywhere.  Implement on
+64 bit systems.
+(sfnt_multiply_divide_signed): New function.
+(sfnt_mul_fixed): Fix division overflow.
+(sfnt_curve_to_and_build_1, sfnt_build_glyph_outline): Remove
+outdated comment.
+(sfnt_build_outline_edges): Fix coding style.
+(sfnt_lookup_glyph_metrics): Allow looking up metrics without
+scaling.
+(struct sfnt_cvt_table): Fix type of cvt values.
+(struct sfnt_prep_table): New structure.
+(sfnt_read_cvt_table): Read cvt values in terms of fwords, not
+longs (as Apple's doc seems to say).
+(sfnt_read_fpgm_table): Fix memory allocation for font program
+table.
+(sfnt_read_prep_table): New function.
+(struct sfnt_interpreter_zone): New structure.
+(struct sfnt_interpreter_graphics_state): New fields `project',
+`move', `vector_dot_product'.  Rename to `sfnt_graphics_state'.
+(struct sfnt_interpreter, sfnt_mul_f26dot6): Stop doing rounding
+division.
+(sfnt_init_graphics_state, sfnt_make_interpreter, MOVE, SSW, RAW)
+(SDS, ADD, SUB, ABS, NEG, WCVTF, _MIN, S45ROUND, SVTCAx)
+(sfnt_set_srounding_state, sfnt_skip_code)
+(sfnt_interpret_unimplemented, sfnt_interpret_fdef)
+(sfnt_interpret_idef, sfnt_interpret_if, sfnt_interpret_else)
+(sfnt_round_none, sfnt_round_to_grid, sfnt_round_to_double_grid)
+"
+          wanted "
+* src/sfnt.c 
+(xmalloc, xrealloc):
+Improve behavior
+upon allocation
+failures during
+test.
+(sfnt_table_names):
+Add prep.
+(sfnt_transform_coordinates):
+Allow applying
+offsets during
+coordinate
+transform.
+(sfnt_decompose_compound_glyph):
+Defer offset
+computation until
+any component
+compound glyph is
+loaded, then apply
+it during the
+transform process.
+(sfnt_multiply_divide):
+Make available
+everywhere.
+Implement on 64 bit
+systems.
+(sfnt_multiply_divide_signed):
+New function.
+(sfnt_mul_fixed):
+Fix division
+overflow.
+(sfnt_curve_to_and_build_1)
+(sfnt_build_glyph_outline):
+Remove outdated
+comment.
+(sfnt_build_outline_edges):
+Fix coding style.
+(sfnt_lookup_glyph_metrics):
+Allow looking up
+metrics without
+scaling.
+(struct sfnt_cvt_table):
+Fix type of cvt
+values.
+(struct sfnt_prep_table):
+New structure.
+(sfnt_read_cvt_table):
+Read cvt values in
+terms of fwords, not
+longs (as Apple's
+doc seems to say).
+(sfnt_read_fpgm_table):
+Fix memory
+allocation for font
+program table.
+(sfnt_read_prep_table):
+New function.
+(struct sfnt_interpreter_zone):
+New structure.
+(struct sfnt_interpreter_graphics_state):
+New fields
+`project', `move',
+`vector_dot_product'.
+Rename to
+`sfnt_graphics_state'.
+(struct sfnt_interpreter)
+(sfnt_mul_f26dot6):
+Stop doing rounding
+division.
+(sfnt_init_graphics_state)
+(sfnt_make_interpreter)
+(MOVE, SSW, RAW, SDS)
+(ADD, SUB, ABS, NEG)
+(WCVTF, _MIN)
+(S45ROUND, SVTCAx)
+(sfnt_set_srounding_state)
+(sfnt_skip_code)
+(sfnt_interpret_unimplemented)
+(sfnt_interpret_fdef)
+(sfnt_interpret_idef)
+(sfnt_interpret_if)
+(sfnt_interpret_else)
+(sfnt_round_none)
+(sfnt_round_to_grid)
+(sfnt_round_to_double_grid):
+")
+    (with-temp-buffer
+      (insert string)
+      (let ((fill-column 20)) (log-edit-fill-entry))
+      (should (equal (buffer-string) wanted)))))
+
+(ert-deftest log-edit-fill-entry-initial-wrapping ()
+  ;; This test verifies that a newline is inserted before a defun
+  ;; itself longer than the fill column when such a defun is being
+  ;; inserted after a file name, and not otherwise.
+  (let (string wanted)
+    (setq string "
+* src/sfnt.c (long_entry_1): This entry should be placed on a
+new line.
+(but_this_entry_should_not): With the prose displaced to the
+next line instead."
+          wanted "
+* src/sfnt.c 
+(long_entry_1): This
+entry should be
+placed on a new
+line.
+(but_this_entry_should_not):
+With the prose
+displaced to the
+next line instead.")
+    (with-temp-buffer
+      (insert string)
+      (let ((fill-column 20)) (log-edit-fill-entry))
+      (should (equal (buffer-string) wanted)))))
+
 ;;; log-edit-tests.el ends here
diff --git a/test/lisp/vc/smerge-mode-tests.el 
b/test/lisp/vc/smerge-mode-tests.el
index a7d41607bc5..d69c629ad69 100644
--- a/test/lisp/vc/smerge-mode-tests.el
+++ b/test/lisp/vc/smerge-mode-tests.el
@@ -1,6 +1,6 @@
 ;;; smerge-mode-tests.el --- Tests for smerge-mode.el  -*- lexical-binding:t 
-*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 
diff --git a/test/lisp/vc/vc-bzr-tests.el b/test/lisp/vc/vc-bzr-tests.el
index d8ed1013c38..8ed63d11a8f 100644
--- a/test/lisp/vc/vc-bzr-tests.el
+++ b/test/lisp/vc/vc-bzr-tests.el
@@ -1,6 +1,6 @@
 ;;; vc-bzr-tests.el --- tests for vc/vc-bzr.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Glenn Morris <rgm@gnu.org>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/vc/vc-cvs-tests.el b/test/lisp/vc/vc-cvs-tests.el
index 473ac69e24c..f6fa7a81a1a 100644
--- a/test/lisp/vc/vc-cvs-tests.el
+++ b/test/lisp/vc/vc-cvs-tests.el
@@ -1,6 +1,6 @@
 ;;; vc-cvs-tests.el --- tests for vc/vc-cvs.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: Olivier Certner <olce.emacs@certner.fr>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/vc/vc-git-tests.el b/test/lisp/vc/vc-git-tests.el
index b331b77cf01..c52cd9c5875 100644
--- a/test/lisp/vc/vc-git-tests.el
+++ b/test/lisp/vc/vc-git-tests.el
@@ -1,6 +1,6 @@
 ;;; vc-git-tests.el --- tests for vc/vc-git.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Justin Schell <justinmschell@gmail.com>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/vc/vc-hg-tests.el b/test/lisp/vc/vc-hg-tests.el
index 89d518b2a91..f578c86d401 100644
--- a/test/lisp/vc/vc-hg-tests.el
+++ b/test/lisp/vc/vc-hg-tests.el
@@ -1,6 +1,6 @@
 ;;; vc-hg-tests.el --- tests for vc/vc-hg.el  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Dmitry Gutov <dgutov@yandex.ru>
 ;; Maintainer: emacs-devel@gnu.org
@@ -53,6 +53,8 @@
 (ert-deftest vc-hg-annotate-time ()
   (with-temp-buffer
     (save-excursion (insert "philringnalda 218075 2014-11-28 CLOBBER:"))
-    (should (floatp (vc-hg-annotate-time)))))
+    (should (equal (vc-hg-annotate-time)
+                   (vc-annotate-convert-time
+                    (encode-time 0 0 0 28 11 2014))))))
 
 ;;; vc-hg-tests.el ends here
diff --git a/test/lisp/vc/vc-tests.el b/test/lisp/vc/vc-tests.el
index f40cee8cc5b..6be8af40e3a 100644
--- a/test/lisp/vc/vc-tests.el
+++ b/test/lisp/vc/vc-tests.el
@@ -1,6 +1,6 @@
 ;;; vc-tests.el --- Tests of different backends of vc.el  -*- 
lexical-binding:t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Michael Albinus <michael.albinus@gmx.de>
 
diff --git a/test/lisp/version-tests.el b/test/lisp/version-tests.el
index 95ecf9600b5..81bb769d089 100644
--- a/test/lisp/version-tests.el
+++ b/test/lisp/version-tests.el
@@ -1,6 +1,6 @@
 ;;; version-tests.el --- Tests for version.el  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/wdired-tests.el b/test/lisp/wdired-tests.el
index 20caaff17c7..f7bff743058 100644
--- a/test/lisp/wdired-tests.el
+++ b/test/lisp/wdired-tests.el
@@ -1,6 +1,6 @@
 ;;; wdired-tests.el --- tests for wdired.el          -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/whitespace-tests.el b/test/lisp/whitespace-tests.el
index f059104cdb9..73c7e742ec5 100644
--- a/test/lisp/whitespace-tests.el
+++ b/test/lisp/whitespace-tests.el
@@ -1,6 +1,6 @@
 ;;; whitespace-tests.el --- Test suite for whitespace -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/wid-edit-tests.el b/test/lisp/wid-edit-tests.el
index 66bff4ad2e3..4b049478b29 100644
--- a/test/lisp/wid-edit-tests.el
+++ b/test/lisp/wid-edit-tests.el
@@ -1,6 +1,6 @@
 ;;; wid-edit-tests.el --- tests for wid-edit.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/x-dnd-tests.el b/test/lisp/x-dnd-tests.el
index 2ed4c3e7662..37a1beafd54 100644
--- a/test/lisp/x-dnd-tests.el
+++ b/test/lisp/x-dnd-tests.el
@@ -1,6 +1,6 @@
 ;;; dnd-tests.el --- Tests for X DND support -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/lisp/xdg-tests.el b/test/lisp/xdg-tests.el
index 962f26cd975..c10a258210c 100644
--- a/test/lisp/xdg-tests.el
+++ b/test/lisp/xdg-tests.el
@@ -1,6 +1,6 @@
 ;;; xdg-tests.el --- tests for xdg.el -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Author: Mark Oteiza <mvoteiza@udel.edu>
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/xml-tests.el b/test/lisp/xml-tests.el
index 8d419765fe6..d423a34f70e 100644
--- a/test/lisp/xml-tests.el
+++ b/test/lisp/xml-tests.el
@@ -1,6 +1,6 @@
 ;;; xml-tests.el --- Test suite for XML parsing.  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Chong Yidong <cyd@stupidchicken.com>
 ;; Keywords:       internal
diff --git a/test/lisp/xt-mouse-tests.el b/test/lisp/xt-mouse-tests.el
index 19719c75fc3..cfc8042f796 100644
--- a/test/lisp/xt-mouse-tests.el
+++ b/test/lisp/xt-mouse-tests.el
@@ -1,6 +1,6 @@
 ;;; xt-mouse-tests.el --- Test suite for xt-mouse.  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Philipp Stephani <phst@google.com>
 
diff --git a/test/lisp/yank-media-tests.el b/test/lisp/yank-media-tests.el
index 2ce879c418f..2eee60002fe 100644
--- a/test/lisp/yank-media-tests.el
+++ b/test/lisp/yank-media-tests.el
@@ -1,6 +1,6 @@
 ;;; yank-media-tests.el --- Tests for yank-media.el  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/manual/biditest.el b/test/manual/biditest.el
index aefd322dede..7c49591b84e 100644
--- a/test/manual/biditest.el
+++ b/test/manual/biditest.el
@@ -1,6 +1,6 @@
 ;;; biditest.el --- test bidi reordering in GNU Emacs display engine.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Eli Zaretskii
 ;; Maintainer: emacs-devel@gnu.org
diff --git a/test/manual/cedet/cedet-utests.el 
b/test/manual/cedet/cedet-utests.el
index 336e417c44f..49a18b2ac55 100644
--- a/test/manual/cedet/cedet-utests.el
+++ b/test/manual/cedet/cedet-utests.el
@@ -1,6 +1,6 @@
 ;;; cedet-utests.el --- Run all unit tests in the CEDET suite.  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/manual/cedet/ede-tests.el b/test/manual/cedet/ede-tests.el
index 89407108e58..0c9fc72e2ce 100644
--- a/test/manual/cedet/ede-tests.el
+++ b/test/manual/cedet/ede-tests.el
@@ -1,6 +1,6 @@
 ;;; ede-tests.el --- Some tests for the Emacs Development Environment  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/manual/cedet/semantic-tests.el 
b/test/manual/cedet/semantic-tests.el
index 5eca5fb5c62..f928a2f8b0b 100644
--- a/test/manual/cedet/semantic-tests.el
+++ b/test/manual/cedet/semantic-tests.el
@@ -1,6 +1,6 @@
 ;;; semantic-tests.el --- Miscellaneous Semantic tests.  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/manual/cedet/tests/test.c b/test/manual/cedet/tests/test.c
index cddbd85b45b..093b806ac3b 100644
--- a/test/manual/cedet/tests/test.c
+++ b/test/manual/cedet/tests/test.c
@@ -1,6 +1,6 @@
 /* test.c --- Semantic unit test for C.
 
-   Copyright (C) 2001-2023 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
 
    Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/manual/cedet/tests/test.el b/test/manual/cedet/tests/test.el
index c75ea331223..d96289296fa 100644
--- a/test/manual/cedet/tests/test.el
+++ b/test/manual/cedet/tests/test.el
@@ -1,6 +1,6 @@
 ;;; test.el --- Unit test file for Semantic Emacs Lisp support.  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/manual/cedet/tests/test.make 
b/test/manual/cedet/tests/test.make
index fc171214420..7bb1e4133a7 100644
--- a/test/manual/cedet/tests/test.make
+++ b/test/manual/cedet/tests/test.make
@@ -1,6 +1,6 @@
 # test.make --- Semantic unit test for Make -*- makefile -*-
 
-# Copyright (C) 2001-2002, 2010-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2002, 2010-2024 Free Software Foundation, Inc.
 
 # Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/manual/cedet/tests/testpolymorph.cpp 
b/test/manual/cedet/tests/testpolymorph.cpp
index 0cf645c2f43..b3cb90be2d6 100644
--- a/test/manual/cedet/tests/testpolymorph.cpp
+++ b/test/manual/cedet/tests/testpolymorph.cpp
@@ -1,6 +1,6 @@
 /** testpolymorph.cpp --- A sequence of polymorphism examples.
  *
- * Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ * Copyright (C) 2009-2024 Free Software Foundation, Inc.
  *
  * Author: Eric M. Ludlam <zappo@gnu.org>
  *
diff --git a/test/manual/cedet/tests/testspp.c 
b/test/manual/cedet/tests/testspp.c
index a439cee2a7d..05326ef6e1f 100644
--- a/test/manual/cedet/tests/testspp.c
+++ b/test/manual/cedet/tests/testspp.c
@@ -1,6 +1,6 @@
 /* testspp.cpp --- Semantic unit test for the C preprocessor
 
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
    Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/manual/cedet/tests/testsppreplace.c 
b/test/manual/cedet/tests/testsppreplace.c
index 2c913934bea..acb4c9bbce2 100644
--- a/test/manual/cedet/tests/testsppreplace.c
+++ b/test/manual/cedet/tests/testsppreplace.c
@@ -1,5 +1,5 @@
 /* testsppreplace.c --- unit test for CPP/SPP Replacement
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
    Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/manual/cedet/tests/testsppreplaced.c 
b/test/manual/cedet/tests/testsppreplaced.c
index f0f78ca8dd2..f4520d3d48f 100644
--- a/test/manual/cedet/tests/testsppreplaced.c
+++ b/test/manual/cedet/tests/testsppreplaced.c
@@ -1,5 +1,5 @@
 /* testsppreplaced.c --- unit test for CPP/SPP Replacement
-   Copyright (C) 2007-2023 Free Software Foundation, Inc.
+   Copyright (C) 2007-2024 Free Software Foundation, Inc.
 
    Author: Eric M. Ludlam <zappo@gnu.org>
 
diff --git a/test/manual/etags/c-src/abbrev.c b/test/manual/etags/c-src/abbrev.c
index acd5884886c..70f4987eccc 100644
--- a/test/manual/etags/c-src/abbrev.c
+++ b/test/manual/etags/c-src/abbrev.c
@@ -1,5 +1,5 @@
 /* Primitives for word-abbrev mode.
-   Copyright (C) 1985-1986, 1993, 1996, 1998, 2016-2023 Free Software
+   Copyright (C) 1985-1986, 1993, 1996, 1998, 2016-2024 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
diff --git a/test/manual/etags/c-src/emacs/src/gmalloc.c 
b/test/manual/etags/c-src/emacs/src/gmalloc.c
index cf3ad6ee766..afa36994b59 100644
--- a/test/manual/etags/c-src/emacs/src/gmalloc.c
+++ b/test/manual/etags/c-src/emacs/src/gmalloc.c
@@ -1,5 +1,5 @@
 /* Declarations for `malloc' and friends.
-   Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2023 Free
+   Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2024 Free
    Software Foundation, Inc.
                  Written May 1989 by Mike Haertel.
 
diff --git a/test/manual/etags/c-src/emacs/src/keyboard.c 
b/test/manual/etags/c-src/emacs/src/keyboard.c
index 310dba27c89..b27f98903ce 100644
--- a/test/manual/etags/c-src/emacs/src/keyboard.c
+++ b/test/manual/etags/c-src/emacs/src/keyboard.c
@@ -1,6 +1,6 @@
 /* Keyboard and mouse input; editor command loop.
 
-Copyright (C) 1985-1989, 1993-1997, 1999-2023 Free Software Foundation,
+Copyright (C) 1985-1989, 1993-1997, 1999-2024 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
diff --git a/test/manual/etags/c-src/emacs/src/lisp.h 
b/test/manual/etags/c-src/emacs/src/lisp.h
index aa8dc8c9a66..0382acf06ed 100644
--- a/test/manual/etags/c-src/emacs/src/lisp.h
+++ b/test/manual/etags/c-src/emacs/src/lisp.h
@@ -1,6 +1,6 @@
 /* Fundamental definitions for GNU Emacs Lisp interpreter.
 
-Copyright (C) 1985-1987, 1993-1995, 1997-2023 Free Software Foundation,
+Copyright (C) 1985-1987, 1993-1995, 1997-2024 Free Software Foundation,
 Inc.
 
 This file is part of GNU Emacs.
diff --git a/test/manual/etags/c-src/emacs/src/regex.h 
b/test/manual/etags/c-src/emacs/src/regex.h
index b31fa9982d9..75a9b5893be 100644
--- a/test/manual/etags/c-src/emacs/src/regex.h
+++ b/test/manual/etags/c-src/emacs/src/regex.h
@@ -1,7 +1,7 @@
 /* Definitions for data structures and routines for the regular
    expression library, version 0.12.
 
-   Copyright (C) 1985, 1989-1993, 1995, 2000-2023 Free Software
+   Copyright (C) 1985, 1989-1993, 1995, 2000-2024 Free Software
    Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
diff --git a/test/manual/etags/c-src/etags.c b/test/manual/etags/c-src/etags.c
index bd09e75a5d0..a5b464ae520 100644
--- a/test/manual/etags/c-src/etags.c
+++ b/test/manual/etags/c-src/etags.c
@@ -28,7 +28,7 @@ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
SOFTWARE, EVEN
 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2023 Free Software
+Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2024 Free Software
 Foundation, Inc.
 
 This file is not considered part of GNU Emacs.
diff --git a/test/manual/etags/c-src/exit.c b/test/manual/etags/c-src/exit.c
index 8101562c985..bd21f5dcd9b 100644
--- a/test/manual/etags/c-src/exit.c
+++ b/test/manual/etags/c-src/exit.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 2016-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 2016-2024 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
 
 The GNU C Library is free software; you can redistribute it and/or
diff --git a/test/manual/etags/c-src/exit.strange_suffix 
b/test/manual/etags/c-src/exit.strange_suffix
index 8101562c985..bd21f5dcd9b 100644
--- a/test/manual/etags/c-src/exit.strange_suffix
+++ b/test/manual/etags/c-src/exit.strange_suffix
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 2016-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 2016-2024 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
 
 The GNU C Library is free software; you can redistribute it and/or
diff --git a/test/manual/etags/c-src/getopt.h b/test/manual/etags/c-src/getopt.h
index 29536410f29..069d7b9bc3b 100644
--- a/test/manual/etags/c-src/getopt.h
+++ b/test/manual/etags/c-src/getopt.h
@@ -1,5 +1,5 @@
 /* Declarations for getopt.
-   Copyright (C) 1989-1992, 2016-2023 Free Software Foundation, Inc.
+   Copyright (C) 1989-1992, 2016-2024 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
diff --git a/test/manual/etags/c-src/sysdep.h b/test/manual/etags/c-src/sysdep.h
index c29ed8b64a6..d8fc292e185 100644
--- a/test/manual/etags/c-src/sysdep.h
+++ b/test/manual/etags/c-src/sysdep.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-1993, 2016-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1992-1993, 2016-2024 Free Software Foundation, Inc.
 This file is part of the GNU C Library.
 
 The GNU C Library is free software; you can redistribute it and/or
diff --git a/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el 
b/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el
index 4f4663701f0..288bd325c04 100644
--- a/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el
+++ b/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el
@@ -1,6 +1,6 @@
 ;;; etags.el --- etags facility for Emacs  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1985-1986, 1988-1989, 1992-1996, 1998, 2000-2023 Free
+;; Copyright (C) 1985-1986, 1988-1989, 1992-1996, 1998, 2000-2024 Free
 ;; Software Foundation, Inc.
 
 ;; Author: Roland McGrath <roland@gnu.org>
diff --git a/test/manual/etags/tex-src/texinfo.tex 
b/test/manual/etags/tex-src/texinfo.tex
index f523af7da30..cc8b80aa3c3 100644
--- a/test/manual/etags/tex-src/texinfo.tex
+++ b/test/manual/etags/tex-src/texinfo.tex
@@ -1,6 +1,6 @@
 %% TeX macros to handle texinfo files
 
-%   Copyright (C) 1985--1986, 1988, 1990--1991, 2016--2023 Free Software
+%   Copyright (C) 1985--1986, 1988, 1990--1991, 2016--2024 Free Software
 %   Foundation, Inc.
 
 %This texinfo.tex file is free software; you can redistribute it and/or
diff --git a/test/manual/etags/y-src/cccp.c b/test/manual/etags/y-src/cccp.c
index 879de5b0d8f..bc30e23772c 100644
--- a/test/manual/etags/y-src/cccp.c
+++ b/test/manual/etags/y-src/cccp.c
@@ -320,7 +320,7 @@ static const short yycheck[] =
 #line 3 "/usr/share/bison/bison.simple"
 
 /* Skeleton output parser for bison,
-   Copyright (C) 1984, 1989-1990, 2000-2001, 2016-2023 Free Software
+   Copyright (C) 1984, 1989-1990, 2000-2001, 2016-2024 Free Software
    Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
diff --git a/test/manual/etags/y-src/parse.c b/test/manual/etags/y-src/parse.c
index 8ba6b23675d..c4aac438fc5 100644
--- a/test/manual/etags/y-src/parse.c
+++ b/test/manual/etags/y-src/parse.c
@@ -28,7 +28,7 @@
 
 #line 1 "y-src/parse.y"
 
-/*     Copyright (C) 1990, 1992-1993, 2016-2023 Free Software Foundation,
+/*     Copyright (C) 1990, 1992-1993, 2016-2024 Free Software Foundation,
  *     Inc.
 
 This file is part of Oleo, the GNU Spreadsheet.
diff --git a/test/manual/etags/y-src/parse.y b/test/manual/etags/y-src/parse.y
index c4d4b1e0eac..9812787f914 100644
--- a/test/manual/etags/y-src/parse.y
+++ b/test/manual/etags/y-src/parse.y
@@ -1,5 +1,5 @@
 %{
-/*     Copyright (C) 1990, 1992-1993, 2016-2023 Free Software Foundation,
+/*     Copyright (C) 1990, 1992-1993, 2016-2024 Free Software Foundation,
  *     Inc.
 
 This file is part of Oleo, the GNU Spreadsheet.
diff --git a/test/manual/image-circular-tests.el 
b/test/manual/image-circular-tests.el
index efd96895f84..ac62d1c58ec 100644
--- a/test/manual/image-circular-tests.el
+++ b/test/manual/image-circular-tests.el
@@ -1,6 +1,6 @@
 ;;; image-circular-tests.el --- test image functions with circular objects  
-*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019, 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019, 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Pip Cet <pipcet@gmail.com>
 ;; Keywords:       internal
diff --git a/test/manual/image-size-tests.el b/test/manual/image-size-tests.el
index 544a38b6ba3..a96e1afc960 100644
--- a/test/manual/image-size-tests.el
+++ b/test/manual/image-size-tests.el
@@ -1,6 +1,6 @@
 ;;; image-size-tests.el --- tests for image scaling  -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/manual/image-tests.el b/test/manual/image-tests.el
index eb5bf13e8b0..e186586be3b 100644
--- a/test/manual/image-tests.el
+++ b/test/manual/image-tests.el
@@ -1,6 +1,6 @@
 ;;; image-tests.el --- tests for image.c  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 ;; Keywords: internal
diff --git a/test/manual/image-transforms-tests.el 
b/test/manual/image-transforms-tests.el
index cdf812ee177..92dd73263b1 100644
--- a/test/manual/image-transforms-tests.el
+++ b/test/manual/image-transforms-tests.el
@@ -1,6 +1,6 @@
 ;;; image-transforms-tests.el --- Test suite for image transforms.  -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Alan Third <alan@idiocy.org>
 ;; Keywords:       internal
diff --git a/test/manual/indent/pascal.pas b/test/manual/indent/pascal.pas
index 3b35acdc801..54794895be7 100644
--- a/test/manual/indent/pascal.pas
+++ b/test/manual/indent/pascal.pas
@@ -1,6 +1,6 @@
 { GPC demo program for the CRT unit.
 
-Copyright (C) 1999-2006, 2013-2023 Free Software Foundation, Inc.
+Copyright (C) 1999-2006, 2013-2024 Free Software Foundation, Inc.
 
 Author: Frank Heckenbach <frank@pascal.gnu.de>
 
diff --git a/test/manual/indent/shell.sh b/test/manual/indent/shell.sh
index 5b3fb0e66fb..42a981d312e 100755
--- a/test/manual/indent/shell.sh
+++ b/test/manual/indent/shell.sh
@@ -189,3 +189,10 @@ bar () {
 
     fi
 }
+
+case $i {                       # Bug#55764
+    *pattern)
+        (cd .; echo hi);
+        do1 ;;
+    *pattern2) do2 ;;
+}
diff --git a/test/manual/noverlay/Makefile.in b/test/manual/noverlay/Makefile.in
index 29c7bacd258..280230b569a 100644
--- a/test/manual/noverlay/Makefile.in
+++ b/test/manual/noverlay/Makefile.in
@@ -1,6 +1,6 @@
 ### @configure_input@
 
-# Copyright (C) 2017-2023 Free Software Foundation, Inc.
+# Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 # This file is part of GNU Emacs.
 
diff --git a/test/manual/noverlay/check-sanitize.sh 
b/test/manual/noverlay/check-sanitize.sh
index 735b85bbeeb..bec4f2f8e10 100755
--- a/test/manual/noverlay/check-sanitize.sh
+++ b/test/manual/noverlay/check-sanitize.sh
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 ### check-sanitize.sh - strip confusing parts of Check error output
 
-## Copyright (C) 2017-2023 Free Software Foundation, Inc.
+## Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ## This file is part of GNU Emacs.
 
diff --git a/test/manual/noverlay/emacs-compat.h 
b/test/manual/noverlay/emacs-compat.h
index 16fa66e8ae4..b797f765dff 100644
--- a/test/manual/noverlay/emacs-compat.h
+++ b/test/manual/noverlay/emacs-compat.h
@@ -1,6 +1,6 @@
 /* Mock necessary parts of lisp.h.
 
-Copyright (C) 2017-2023 Free Software Foundation, Inc.
+Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/test/manual/noverlay/itree-tests.c 
b/test/manual/noverlay/itree-tests.c
index 0f1e4138954..4d380fc1d2c 100644
--- a/test/manual/noverlay/itree-tests.c
+++ b/test/manual/noverlay/itree-tests.c
@@ -1,6 +1,6 @@
 /* Test the interval data-structure in itree.c.
 
-Copyright (c) 2017-2023 Free Software Foundation, Inc.
+Copyright (c) 2017-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
diff --git a/test/manual/noverlay/overlay-perf.el 
b/test/manual/noverlay/overlay-perf.el
index 970b4541d9a..56cb72fc308 100644
--- a/test/manual/noverlay/overlay-perf.el
+++ b/test/manual/noverlay/overlay-perf.el
@@ -1,6 +1,6 @@
 ;; -*- lexical-binding:t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/manual/process-callout-tests.el 
b/test/manual/process-callout-tests.el
index a284dff50ad..4ec352e5018 100644
--- a/test/manual/process-callout-tests.el
+++ b/test/manual/process-callout-tests.el
@@ -1,6 +1,6 @@
 ;;; process-callout-tests.el --- Testing the process facilities -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/manual/redisplay-testsuite.el 
b/test/manual/redisplay-testsuite.el
index 837f7417582..6d1232999ca 100644
--- a/test/manual/redisplay-testsuite.el
+++ b/test/manual/redisplay-testsuite.el
@@ -1,6 +1,6 @@
 ;;; redisplay-testsuite.el --- Test suite for redisplay.  -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
 
 ;; Author: Chong Yidong <cyd@stupidchicken.com>
 ;; Keywords:       internal
diff --git a/test/manual/scroll-tests.el b/test/manual/scroll-tests.el
index b2cfeabfe64..431a4514b36 100644
--- a/test/manual/scroll-tests.el
+++ b/test/manual/scroll-tests.el
@@ -1,6 +1,6 @@
 ;;; scroll-tests.el --- tests for scrolling -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/misc/test-custom-deps.el b/test/misc/test-custom-deps.el
index 9e5ba01fc5b..d04af23dc19 100644
--- a/test/misc/test-custom-deps.el
+++ b/test/misc/test-custom-deps.el
@@ -1,6 +1,6 @@
 ;;; test-custom-deps.el --- Test custom deps  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/misc/test-custom-libs.el b/test/misc/test-custom-libs.el
index d255a87eeaf..0ecc64dd689 100644
--- a/test/misc/test-custom-libs.el
+++ b/test/misc/test-custom-libs.el
@@ -1,6 +1,6 @@
 ;;; test-custom-libs.el --- Test custom loads  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/misc/test-custom-noloads.el b/test/misc/test-custom-noloads.el
index 585831aa466..3d669c72f7f 100644
--- a/test/misc/test-custom-noloads.el
+++ b/test/misc/test-custom-noloads.el
@@ -1,6 +1,6 @@
 ;;; test-custom-noloads.el --- Test custom noloads  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/misc/test-custom-opts.el b/test/misc/test-custom-opts.el
index f37553382c4..a4c286eed8a 100644
--- a/test/misc/test-custom-opts.el
+++ b/test/misc/test-custom-opts.el
@@ -1,6 +1,6 @@
 ;;; test-custom-opts.el --- Test custom opts  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/alloc-tests.el b/test/src/alloc-tests.el
index 19330e4a79c..74990574677 100644
--- a/test/src/alloc-tests.el
+++ b/test/src/alloc-tests.el
@@ -1,6 +1,6 @@
 ;;; alloc-tests.el --- alloc tests -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Daniel Colascione <dancol@dancol.org>
 ;; Keywords:
diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el
index aa30533c6a0..bb897377d41 100644
--- a/test/src/buffer-tests.el
+++ b/test/src/buffer-tests.el
@@ -1,6 +1,6 @@
 ;;; buffer-tests.el --- tests for buffer.c functions -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/callint-tests.el b/test/src/callint-tests.el
index 4f7cceef619..6801ba7ce3b 100644
--- a/test/src/callint-tests.el
+++ b/test/src/callint-tests.el
@@ -1,6 +1,6 @@
 ;;; callint-tests.el --- unit tests for callint.c    -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
 
 ;; Author: Philipp Stephani <phst@google.com>
 
diff --git a/test/src/callproc-tests.el b/test/src/callproc-tests.el
index 8ee40a46c11..a8b5a4372d6 100644
--- a/test/src/callproc-tests.el
+++ b/test/src/callproc-tests.el
@@ -1,6 +1,6 @@
 ;;; callproc-tests.el --- callproc.c tests -*- lexical-binding: t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/casefiddle-tests.el b/test/src/casefiddle-tests.el
index 12984d898b9..0a456c094ab 100644
--- a/test/src/casefiddle-tests.el
+++ b/test/src/casefiddle-tests.el
@@ -1,6 +1,6 @@
 ;;; casefiddle-tests.el --- tests for casefiddle.c functions -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2015-2016, 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2016, 2018-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/character-tests.el b/test/src/character-tests.el
index 76026ffc3a9..ae466800ec3 100644
--- a/test/src/character-tests.el
+++ b/test/src/character-tests.el
@@ -1,6 +1,6 @@
 ;;; character-tests.el --- tests for character.c  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/charset-tests.el b/test/src/charset-tests.el
index 34788ecbc05..3a4490fd272 100644
--- a/test/src/charset-tests.el
+++ b/test/src/charset-tests.el
@@ -1,6 +1,6 @@
 ;;; charset-tests.el --- Tests for charset.c -*- lexical-binding: t -*-
 
-;; Copyright 2017-2023 Free Software Foundation, Inc.
+;; Copyright 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/chartab-tests.el b/test/src/chartab-tests.el
index 6433d3d09bb..3785f72135b 100644
--- a/test/src/chartab-tests.el
+++ b/test/src/chartab-tests.el
@@ -1,6 +1,6 @@
 ;;; chartab-tests.el --- Tests for char-tab.c -*- lexical-binding: t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Eli Zaretskii <eliz@gnu.org>
 
diff --git a/test/src/cmds-tests.el b/test/src/cmds-tests.el
index 70d3d09e9d5..38bb4e71d16 100644
--- a/test/src/cmds-tests.el
+++ b/test/src/cmds-tests.el
@@ -1,6 +1,6 @@
 ;;; cmds-tests.el --- Testing some Emacs commands -*- lexical-binding: t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Nicolas Richard <youngfrog@members.fsf.org>
 ;; Keywords:
diff --git a/test/src/coding-tests.el b/test/src/coding-tests.el
index b27907027ba..443a0f9c630 100644
--- a/test/src/coding-tests.el
+++ b/test/src/coding-tests.el
@@ -1,6 +1,6 @@
 ;;; coding-tests.el --- tests for text encoding and decoding -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Eli Zaretskii <eliz@gnu.org>
 ;; Author: Kenichi Handa <handa@gnu.org>
diff --git a/test/src/comp-resources/comp-test-funcs-dyn.el 
b/test/src/comp-resources/comp-test-funcs-dyn.el
index 8cd127f7e1b..5a8a84b6a7b 100644
--- a/test/src/comp-resources/comp-test-funcs-dyn.el
+++ b/test/src/comp-resources/comp-test-funcs-dyn.el
@@ -1,6 +1,6 @@
 ;;; comp-test-funcs-dyn.el --- compilation unit tested by comp-tests.el -*- 
lexical-binding: nil; -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrea Corallo <acorallo@gnu.org>
 
diff --git a/test/src/comp-resources/comp-test-funcs-dyn2.el 
b/test/src/comp-resources/comp-test-funcs-dyn2.el
index 3d70489d1ca..101674f74ce 100644
--- a/test/src/comp-resources/comp-test-funcs-dyn2.el
+++ b/test/src/comp-resources/comp-test-funcs-dyn2.el
@@ -1,6 +1,6 @@
 ;;; comp-test-funcs-dyn2.el -*- lexical-binding: nil; no-byte-compile: t; -*-
 
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
 
 ;; Author: Alan Mackenzie <acm@muc.de>
 
diff --git a/test/src/comp-resources/comp-test-funcs.el 
b/test/src/comp-resources/comp-test-funcs.el
index 85282e4dc97..4cee084e211 100644
--- a/test/src/comp-resources/comp-test-funcs.el
+++ b/test/src/comp-resources/comp-test-funcs.el
@@ -1,6 +1,6 @@
 ;;; comp-test-funcs.el --- compilation unit tested by comp-tests.el -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrea Corallo <acorallo@gnu.org>
 
@@ -543,6 +543,22 @@
    (if (comp-test-struct-p pkg) x)
    t))
 
+
+(cl-defstruct comp-test-time
+  unix)
+
+(defun comp-test-67239-00-f (a)
+  (cl-assert (stringp a)))
+
+(defsubst comp-test-67239-0-f (x _y)
+  (cl-etypecase x
+    (comp-test-time (error "foo"))
+    (string (comp-test-67239-00-f x))))
+
+(defun comp-test-67239-1-f ()
+  (let ((time (make-comp-test-time :unix (time-convert (current-time) 
'integer))))
+    (comp-test-67239-0-f "%F" time)))
+
 
 ;;;;;;;;;;;;;;;;;;;;
 ;; Tromey's tests ;;
diff --git a/test/src/comp-resources/comp-test-pure.el 
b/test/src/comp-resources/comp-test-pure.el
index cc5ba7edef7..84bb0287772 100644
--- a/test/src/comp-resources/comp-test-pure.el
+++ b/test/src/comp-resources/comp-test-pure.el
@@ -1,6 +1,6 @@
 ;;; comp-test-pure.el --- compilation unit tested by comp-tests.el -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrea Corallo <acorallo@gnu.org>
 
diff --git a/test/src/comp-tests.el b/test/src/comp-tests.el
index c2f0af51570..fbcb6ca9560 100644
--- a/test/src/comp-tests.el
+++ b/test/src/comp-tests.el
@@ -1,6 +1,6 @@
 ;;; comp-tests.el --- unit tests for src/comp.c      -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
 
 ;; Author: Andrea Corallo <acorallo@gnu.org>
 
@@ -28,6 +28,7 @@
 (require 'ert)
 (require 'ert-x)
 (require 'cl-lib)
+(require 'cl-seq)
 (require 'comp)
 (require 'comp-cstr)
 
@@ -582,6 +583,10 @@ dedicated byte-op code."
       (advice-remove #'delete-region f)
       (should (equal comp-test-primitive-redefine-args '(1 2))))))
 
+(comp-deftest 67239-1 ()
+  "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-11/msg00925.html>"
+  (should-not (comp-test-67239-1-f)))
+
 
 ;;;;;;;;;;;;;;;;;;;;;
 ;; Tromey's tests. ;;
@@ -899,14 +904,33 @@ Return a list of results."
     (should (subr-native-elisp-p (symbol-function 'comp-tests-fw-prop-1-f)))
     (should (= (comp-tests-fw-prop-1-f) 6))))
 
+(defun comp-tests--type-lists-equal (l1 l2)
+  (and (= (length l1) (length l2))
+       (cl-every #'comp-tests--types-equal l1 l2)))
+
+(defun comp-tests--types-equal (t1 t2)
+ "Whether the types T1 and T2 are equal."
+ (or (equal t1 t2)   ; for atoms, and optimization for the common case
+     (and (consp t1) (consp t2)
+          (eq (car t1) (car t2))
+          (cond ((memq (car t1) '(and or member))
+                 ;; Order or duplicates don't matter.
+                 (null (cl-set-exclusive-or (cdr t1) (cdr t2)
+                                            :test #'comp-tests--types-equal)))
+                ((eq (car t1) 'function)
+                 (and (comp-tests--type-lists-equal (nth 1 t1) (nth 1 t2))
+                      (comp-tests--types-equal (nth 2 t1) (nth 2 t2))))
+                (t (comp-tests--type-lists-equal (cdr t1) (cdr t2)))))))
+
 (defun comp-tests-check-ret-type-spec (func-form ret-type)
   (let ((lexical-binding t)
         (native-comp-speed 2)
         (f-name (cl-second func-form)))
     (eval func-form t)
     (native-compile f-name)
-    (should (equal (cl-third (subr-type (symbol-function f-name)))
-                   ret-type))))
+    (should (comp-tests--types-equal
+             (cl-third (subr-type (symbol-function f-name)))
+             ret-type))))
 
 (cl-eval-when (compile eval load)
   (cl-defstruct comp-foo a b)
diff --git a/test/src/data-tests.el b/test/src/data-tests.el
index 8167cccdd18..8af7e902109 100644
--- a/test/src/data-tests.el
+++ b/test/src/data-tests.el
@@ -1,6 +1,6 @@
 ;;; data-tests.el --- tests for src/data.c  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/decompress-tests.el b/test/src/decompress-tests.el
index 1052ecee5c1..f8fa1f2f140 100644
--- a/test/src/decompress-tests.el
+++ b/test/src/decompress-tests.el
@@ -1,6 +1,6 @@
 ;;; decompress-tests.el --- Test suite for decompress. -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; Author: Lars Ingebrigtsen <larsi@gnus.org>
 
diff --git a/test/src/doc-tests.el b/test/src/doc-tests.el
index 79cac8c3d64..b41a7ac5fb6 100644
--- a/test/src/doc-tests.el
+++ b/test/src/doc-tests.el
@@ -1,6 +1,6 @@
 ;;; doc-tests.el --- tests for doc.c functions  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el
index a3353cc25a6..b3b7da65ad3 100644
--- a/test/src/editfns-tests.el
+++ b/test/src/editfns-tests.el
@@ -1,6 +1,6 @@
 ;;; editfns-tests.el --- tests for editfns.c  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/emacs-module-resources/mod-test.c 
b/test/src/emacs-module-resources/mod-test.c
index 5dfa6ed4b85..3aafae1b896 100644
--- a/test/src/emacs-module-resources/mod-test.c
+++ b/test/src/emacs-module-resources/mod-test.c
@@ -1,6 +1,6 @@
 /* Test GNU Emacs modules.
 
-Copyright 2015-2023 Free Software Foundation, Inc.
+Copyright 2015-2024 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -33,9 +33,9 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #ifdef WINDOWSNT
 /* Cannot include <process.h> because of the local header by the same
    name, sigh.  */
-uintptr_t _beginthread (void (__cdecl *)(void *), unsigned, void *);
+uintptr_t _beginthread (void (__cdecl *) (void *), unsigned, void *);
 # if !defined __x86_64__
-#  define ALIGN_STACK __attribute__((force_align_arg_pointer))
+#  define ALIGN_STACK __attribute__ ((force_align_arg_pointer))
 # endif
 # include <windows.h>  /* for Sleep */
 #else  /* !WINDOWSNT */
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el
index 59af5d9a4a8..fd0647275a0 100644
--- a/test/src/emacs-module-tests.el
+++ b/test/src/emacs-module-tests.el
@@ -1,6 +1,6 @@
 ;;; emacs-module-tests.el --- Test GNU Emacs modules.  -*- lexical-binding: t; 
-*-
 
-;; Copyright 2015-2023 Free Software Foundation, Inc.
+;; Copyright 2015-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -114,15 +114,14 @@ changes."
 
 (ert-deftest mod-test-non-local-exit-signal-test ()
   (should-error (mod-test-signal))
-  (let (debugger-args backtrace)
+  (let (handler-err backtrace)
     (should-error
-     (let ((debugger (lambda (&rest args)
-                       (setq debugger-args args
-                             backtrace (with-output-to-string (backtrace)))
-                       (cl-incf num-nonmacro-input-events)))
-           (debug-on-signal t))
+     (handler-bind
+         ((error (lambda (err)
+                   (setq handler-err err
+                         backtrace (with-output-to-string (backtrace))))))
        (mod-test-signal)))
-    (should (equal debugger-args '(error (error . 56))))
+    (should (equal handler-err '(error . 56)))
     (should (string-match-p
              (rx bol "  mod-test-signal()" eol)
              backtrace))))
diff --git a/test/src/emacs-tests.el b/test/src/emacs-tests.el
index 0ea197d07f8..19c3793b93d 100644
--- a/test/src/emacs-tests.el
+++ b/test/src/emacs-tests.el
@@ -1,6 +1,6 @@
 ;;; emacs-tests.el --- unit tests for emacs.c -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/eval-tests.el b/test/src/eval-tests.el
index 4589763b2f5..e1c90feb09a 100644
--- a/test/src/eval-tests.el
+++ b/test/src/eval-tests.el
@@ -1,6 +1,6 @@
 ;;; eval-tests.el --- unit tests for src/eval.c      -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Philipp Stephani <phst@google.com>
 
@@ -282,4 +282,72 @@ expressions works for identifiers starting with period."
   (should-error (defvaralias 'eval-tests--my-c 'eval-tests--my-d)
                 :type 'cyclic-variable-indirection))
 
+(defvar eval-tests/global-var 'value)
+(defvar-local eval-tests/buffer-local-var 'value)
+(ert-deftest eval-tests/default-value ()
+  ;; `let' overrides the default value for global variables.
+  (should (default-boundp 'eval-tests/global-var))
+  (should (eq 'value (default-value 'eval-tests/global-var)))
+  (should (eq 'value eval-tests/global-var))
+  (let ((eval-tests/global-var 'bar))
+    (should (eq 'bar (default-value 'eval-tests/global-var)))
+    (should (eq 'bar eval-tests/global-var)))
+  ;; `let' overrides the default value everywhere, but leaves
+  ;; buffer-local values unchanged in current buffer and in the
+  ;; buffers where there is no explicitly set buffer-local value.
+  (should (default-boundp 'eval-tests/buffer-local-var))
+  (should (eq 'value (default-value 'eval-tests/buffer-local-var)))
+  (should (eq 'value eval-tests/buffer-local-var))
+  (with-temp-buffer
+    (let ((eval-tests/buffer-local-var 'bar))
+      (should (eq 'bar (default-value 'eval-tests/buffer-local-var)))
+      (should (eq 'bar eval-tests/buffer-local-var)))))
+
+(ert-deftest eval-tests--handler-bind ()
+  ;; A `handler-bind' has no effect if no error is signaled.
+  (should (equal (catch 'tag
+                   (handler-bind ((error (lambda (_err) (throw 'tag 'wow))))
+                     'noerror))
+                 'noerror))
+  ;; The handler is called from within the dynamic extent where the
+  ;; error is signaled, unlike `condition-case'.
+  (should (equal (catch 'tag
+                   (handler-bind ((error (lambda (_err) (throw 'tag 'err))))
+                     (list 'inner-catch
+                           (catch 'tag
+                             (user-error "hello")))))
+                 '(inner-catch err)))
+  ;; But inner condition handlers are temporarily muted.
+  (should (equal (condition-case nil
+                     (handler-bind
+                         ((error (lambda (_err)
+                                   (signal 'wrong-type-argument nil))))
+                       (list 'result
+                             (condition-case nil
+                                 (user-error "hello")
+                               (wrong-type-argument 'inner-handler))))
+                   (wrong-type-argument 'wrong-type-argument))
+                 'wrong-type-argument))
+  ;; Handlers do not apply to the code run within the handlers.
+  (should (equal (condition-case nil
+                     (handler-bind
+                         ((error (lambda (_err)
+                                   (signal 'wrong-type-argument nil)))
+                          (wrong-type-argument
+                           (lambda (_err) (user-error "wrong-type-argument"))))
+                       (user-error "hello"))
+                   (wrong-type-argument 'wrong-type-argument)
+                   (error 'plain-error))
+                 'wrong-type-argument)))
+
+(ert-deftest eval-tests--error-id ()
+  (let* (inner-error
+         (outer-error
+          (condition-case err
+              (handler-bind ((error (lambda (err) (setq inner-error err))))
+                (car 1))
+            (error err))))
+    (should (eq inner-error outer-error))))
+
+
 ;;; eval-tests.el ends here
diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el
index 62a9be546f9..81eef37b903 100644
--- a/test/src/fileio-tests.el
+++ b/test/src/fileio-tests.el
@@ -1,6 +1,6 @@
 ;;; fileio-tests.el --- unit tests for src/fileio.c      -*- lexical-binding: 
t; -*-
 
-;; Copyright 2017-2023 Free Software Foundation, Inc.
+;; Copyright 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/filelock-tests.el b/test/src/filelock-tests.el
index f4ae7192796..c644747a23e 100644
--- a/test/src/filelock-tests.el
+++ b/test/src/filelock-tests.el
@@ -1,6 +1,6 @@
 ;;; filelock-tests.el --- test file locking -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/floatfns-tests.el b/test/src/floatfns-tests.el
index 97c855a43fa..359d2890134 100644
--- a/test/src/floatfns-tests.el
+++ b/test/src/floatfns-tests.el
@@ -1,6 +1,6 @@
 ;;; floatfns-tests.el --- tests for floating point operations -*- 
lexical-binding: t -*-
 
-;; Copyright 2017-2023 Free Software Foundation, Inc.
+;; Copyright 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
index 9c09e4f0c33..7437c07f156 100644
--- a/test/src/fns-tests.el
+++ b/test/src/fns-tests.el
@@ -1,6 +1,6 @@
 ;;; fns-tests.el --- tests for src/fns.c  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -1097,6 +1097,16 @@
   (should (= (sxhash-equal (record 'a (make-string 10 ?a)))
             (sxhash-equal (record 'a (make-string 10 ?a))))))
 
+(ert-deftest fns--define-hash-table-test ()
+  ;; Check that we can have two differently-named tests using the
+  ;; same functions (bug#68668).
+  (define-hash-table-test 'fns-tests--1 'my-cmp 'my-hash)
+  (define-hash-table-test 'fns-tests--2 'my-cmp 'my-hash)
+  (let ((h1 (make-hash-table :test 'fns-tests--1))
+        (h2 (make-hash-table :test 'fns-tests--2)))
+    (should (eq (hash-table-test h1) 'fns-tests--1))
+    (should (eq (hash-table-test h2) 'fns-tests--2))))
+
 (ert-deftest test-secure-hash ()
   (should (equal (secure-hash 'md5    "foobar")
                  "3858f62230ac3c915f300c664312c63f"))
diff --git a/test/src/font-tests.el b/test/src/font-tests.el
index 2bd20be21dc..a1ea84de9f7 100644
--- a/test/src/font-tests.el
+++ b/test/src/font-tests.el
@@ -1,6 +1,6 @@
 ;;; font-tests.el --- Test suite for font-related functions. -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
 
 ;; Author: Chong Yidong <cyd@stupidchicken.com>
 ;; Keywords:       internal
diff --git a/test/src/image-tests.el b/test/src/image-tests.el
index 3eec2bb4c60..24e60fb100f 100644
--- a/test/src/image-tests.el
+++ b/test/src/image-tests.el
@@ -1,6 +1,6 @@
 ;;; image-tests.el --- Tests for image.c  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; Author: Stefan Kangas <stefankangas@gmail.com>
 
diff --git a/test/src/indent-tests.el b/test/src/indent-tests.el
index 9e111bf3476..a37ad1a3c3f 100644
--- a/test/src/indent-tests.el
+++ b/test/src/indent-tests.el
@@ -1,6 +1,6 @@
 ;;; indent-tests.el --- tests for src/indent.c  -*- lexical-binding:t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/inotify-tests.el b/test/src/inotify-tests.el
index cebf4421fd5..0c078627786 100644
--- a/test/src/inotify-tests.el
+++ b/test/src/inotify-tests.el
@@ -1,6 +1,6 @@
 ;;; inotify-tests.el --- Test suite for inotify. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
 ;; Keywords:       internal
diff --git a/test/src/json-tests.el b/test/src/json-tests.el
index 93e1273d7d6..dffc6291ca1 100644
--- a/test/src/json-tests.el
+++ b/test/src/json-tests.el
@@ -1,6 +1,6 @@
 ;;; json-tests.el --- unit tests for json.c          -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/keyboard-tests.el b/test/src/keyboard-tests.el
index bbb9c19e2e7..4cb141804b2 100644
--- a/test/src/keyboard-tests.el
+++ b/test/src/keyboard-tests.el
@@ -1,6 +1,6 @@
 ;;; keyboard-tests.el --- Tests for keyboard.c -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/keymap-tests.el b/test/src/keymap-tests.el
index 29220c95395..04b897045db 100644
--- a/test/src/keymap-tests.el
+++ b/test/src/keymap-tests.el
@@ -1,6 +1,6 @@
 ;;; keymap-tests.el --- Test suite for src/keymap.c -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Juanma Barranquero <lekktu@gmail.com>
 ;;         Stefan Kangas <stefankangas@gmail.com>
@@ -23,6 +23,7 @@
 ;;; Code:
 
 (require 'ert)
+(require 'cl-lib)
 
 (defun keymap-tests--make-keymap-test (fun)
   (should (eq (car (funcall fun)) 'keymap))
@@ -470,10 +471,18 @@ g .. h            foo
        ert-keymap-duplicate
        "a" #'next-line
        "a" #'previous-line))
-  (should-error
-   (define-keymap
-       "a" #'next-line
-       "a" #'previous-line)))
+  (let ((msg ""))
+    ;; FIXME: It would be nicer to use `current-message' rather than override
+    ;; `message', but `current-message' returns always nil in batch mode :-(
+    (cl-letf (((symbol-function 'message)
+               (lambda (fmt &rest args) (setq msg (apply #'format fmt args)))))
+      (should
+       (string-match "duplicate"
+                     (progn
+                       (define-keymap
+                         "a" #'next-line
+                         "a" #'previous-line)
+                       msg))))))
 
 (ert-deftest keymap-unset-test-remove-and-inheritance ()
   "Check various behaviors of keymap-unset.  (Bug#62207)"
diff --git a/test/src/lcms-tests.el b/test/src/lcms-tests.el
index e34542b1921..a279fb7098c 100644
--- a/test/src/lcms-tests.el
+++ b/test/src/lcms-tests.el
@@ -1,6 +1,6 @@
 ;;; lcms-tests.el --- tests for Little CMS interface -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; Maintainer: emacs-devel@gnu.org
 
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
index eae4893ee1b..4d7f8b71838 100644
--- a/test/src/lread-tests.el
+++ b/test/src/lread-tests.el
@@ -1,6 +1,6 @@
 ;;; lread-tests.el --- tests for lread.c -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; Author: Philipp Stephani <phst@google.com>
 
diff --git a/test/src/marker-tests.el b/test/src/marker-tests.el
index b766466a38a..9336436e53c 100644
--- a/test/src/marker-tests.el
+++ b/test/src/marker-tests.el
@@ -1,6 +1,6 @@
 ;;; marker-tests.el --- tests for marker.c functions -*- lexical-binding: t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/minibuf-tests.el b/test/src/minibuf-tests.el
index f096624cb27..14d160df25c 100644
--- a/test/src/minibuf-tests.el
+++ b/test/src/minibuf-tests.el
@@ -1,6 +1,6 @@
 ;;; minibuf-tests.el --- tests for minibuf.c functions -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/print-tests.el b/test/src/print-tests.el
index a67099c147f..ff3a6fe7483 100644
--- a/test/src/print-tests.el
+++ b/test/src/print-tests.el
@@ -1,6 +1,6 @@
 ;;; print-tests.el --- tests for src/print.c         -*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -367,13 +367,6 @@ otherwise, use a different charset."
       (remhash 1 h)
       (format "%S" h))))
 
-  (should
-   (string-match
-    "data ()"
-    (let ((h (make-hash-table)))
-      (let ((print-length 0))
-        (format "%S" h)))))
-
   (should
    (string-match
     "data (99 99)"
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index 711a27f1cfb..19b14f2d0cb 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -1,6 +1,6 @@
 ;;; process-tests.el --- Testing the process facilities -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/regex-emacs-tests.el b/test/src/regex-emacs-tests.el
index 615d905e140..171d794360e 100644
--- a/test/src/regex-emacs-tests.el
+++ b/test/src/regex-emacs-tests.el
@@ -1,6 +1,6 @@
 ;;; regex-emacs-tests.el --- tests for regex-emacs.c -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -912,7 +912,7 @@ This evaluates the TESTS test cases from glibc."
     ))
 
 (ert-deftest regexp-tests-zero-width-assertion-repetition ()
-  ;; Check compatibility behaviour with repetition operators after
+  ;; Check compatibility behavior with repetition operators after
   ;; certain zero-width assertions (bug#64128).
 
   ;; This function is just to hide ugly regexps from relint so that it
diff --git a/test/src/search-tests.el b/test/src/search-tests.el
index 32dc8a72a86..bab503f36bf 100644
--- a/test/src/search-tests.el
+++ b/test/src/search-tests.el
@@ -1,6 +1,6 @@
 ;;; search-tests.el --- tests for search.c functions -*- lexical-binding: t -*-
 
-;; Copyright (C) 2015-2016, 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2016, 2018-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/sqlite-tests.el b/test/src/sqlite-tests.el
index f7144c15887..a10dca9a0c9 100644
--- a/test/src/sqlite-tests.el
+++ b/test/src/sqlite-tests.el
@@ -1,6 +1,6 @@
 ;;; sqlite-tests.el --- Tests for sqlite.el  -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/syntax-tests.el b/test/src/syntax-tests.el
index 9e4740c17cc..f0f7cf28a3c 100644
--- a/test/src/syntax-tests.el
+++ b/test/src/syntax-tests.el
@@ -1,6 +1,6 @@
 ;;; syntax-tests.el --- tests for syntax.c functions -*- lexical-binding: t -*-
 
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/textprop-tests.el b/test/src/textprop-tests.el
index 12349a79497..d728b539955 100644
--- a/test/src/textprop-tests.el
+++ b/test/src/textprop-tests.el
@@ -1,6 +1,6 @@
 ;;; textprop-tests.el --- Test suite for text properties. -*- lexical-binding: 
t -*-
 
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
 
 ;; Author: Wolfgang Jenkner <wjenkner@inode.at>
 ;; Keywords: internal
diff --git a/test/src/thread-tests.el b/test/src/thread-tests.el
index cfa253fb48e..d9048dcf287 100644
--- a/test/src/thread-tests.el
+++ b/test/src/thread-tests.el
@@ -1,6 +1,6 @@
 ;;; thread-tests.el --- tests for threads. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/timefns-tests.el b/test/src/timefns-tests.el
index ca4ec308926..410efd0db84 100644
--- a/test/src/timefns-tests.el
+++ b/test/src/timefns-tests.el
@@ -1,6 +1,6 @@
 ;;; timefns-tests.el --- tests for timefns.c -*- lexical-binding: t -*-
 
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/treesit-tests.el b/test/src/treesit-tests.el
index 791e902bd0a..a89bf1298c0 100644
--- a/test/src/treesit-tests.el
+++ b/test/src/treesit-tests.el
@@ -1,6 +1,6 @@
 ;;; treesit-tests.el --- tests for src/treesit.c         -*- lexical-binding: 
t; -*-
 
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -1167,6 +1167,42 @@ This tests bug#60355."
    treesit--ert-defun-navigation-top-level-master
    'top-level))
 
+(ert-deftest treesit-search-subtree-forward-1 ()
+  "Test search subtree forward."
+  (skip-unless (treesit-language-available-p 'python))
+  (require 'python)
+  (python-ts-mode)
+  (insert "Temp(1, 2)")
+  (goto-char (point-min))
+  (pcase-let* ((`((,_ . ,call-node))
+                (treesit-query-capture (treesit-buffer-root-node)
+                                       '((call) @c)))
+               (node (treesit-search-subtree
+                      call-node
+                      (lambda (n) (equal (treesit-node-type n) "integer")))))
+
+    (should node)
+    (should (equal (treesit-node-text node) "1"))))
+
+(ert-deftest treesit-search-subtree-backward-1 ()
+  "Test search subtree with backward=t."
+  (skip-unless (treesit-language-available-p 'python))
+  (require 'python)
+  (python-ts-mode)
+  (insert "Temp(1, 2)")
+  (goto-char (point-min))
+  (pcase-let* ((`((,_ . ,call-node))
+                (treesit-query-capture (treesit-buffer-root-node)
+                                       '((call) @c)))
+               (node (treesit-search-subtree
+                      call-node
+                      (lambda (n) (equal (treesit-node-type n) "integer"))
+                      t)))
+
+    (should node)
+    (should (equal (treesit-node-text node) "2"))))
+
+
 ;; TODO
 ;; - Functions in treesit.el
 ;; - treesit-load-name-override-list
diff --git a/test/src/undo-tests.el b/test/src/undo-tests.el
index fd45a9101fa..b4888771e70 100644
--- a/test/src/undo-tests.el
+++ b/test/src/undo-tests.el
@@ -1,6 +1,6 @@
 ;;; undo-tests.el --- Tests of primitive-undo -*- lexical-binding: t -*-
 
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 
 ;; Author: Aaron S. Hawley <aaron.s.hawley@gmail.com>
 
diff --git a/test/src/xdisp-tests.el b/test/src/xdisp-tests.el
index dfd38a9d4c1..f2a2a72c658 100644
--- a/test/src/xdisp-tests.el
+++ b/test/src/xdisp-tests.el
@@ -1,6 +1,6 @@
 ;;; xdisp-tests.el --- tests for xdisp.c functions -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/xfaces-tests.el b/test/src/xfaces-tests.el
index d8707a0a08e..cdf6f30c356 100644
--- a/test/src/xfaces-tests.el
+++ b/test/src/xfaces-tests.el
@@ -1,6 +1,6 @@
 ;;; xfaces-tests.el --- tests for xfaces.c           -*- lexical-binding: t -*-
 
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
diff --git a/test/src/xml-tests.el b/test/src/xml-tests.el
index dfb897ba011..5aa8593fe07 100644
--- a/test/src/xml-tests.el
+++ b/test/src/xml-tests.el
@@ -1,6 +1,6 @@
 ;;; xml-tests.el --- Test suite for libxml parsing. -*- lexical-binding: t -*-
 
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
 
 ;; Author: Ulf Jasper <ulf.jasper@web.de>
 ;; Keywords:       internal



reply via email to

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