emacs-diffs
[Top][All Lists]
Advanced

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

feature/native-comp 15aedf3: Merge remote-tracking branch 'savannah/mast


From: Andrea Corallo
Subject: feature/native-comp 15aedf3: Merge remote-tracking branch 'savannah/master' into HEAD
Date: Wed, 5 Feb 2020 05:08:46 -0500 (EST)

branch: feature/native-comp
commit 15aedf3e3d7814aff980098f9290396222c0ff8d
Merge: ea56b58 b641c17
Author: Andrea Corallo <address@hidden>
Commit: Andrea Corallo <address@hidden>

    Merge remote-tracking branch 'savannah/master' into HEAD
---
 .gitlab-ci.yml                                 |    2 +-
 ChangeLog.3                                    |    2 +-
 INSTALL                                        |   36 -
 admin/MAINTAINERS                              |   10 +
 admin/authors.el                               |   27 +
 admin/merge-gnulib                             |    2 +-
 admin/notes/font-backend                       |   69 --
 admin/notes/unicode                            |   10 +-
 admin/nt/README-ftp-server                     |  277 -----
 admin/nt/dist-build/README-windows-binaries    |   88 +-
 admin/release-process                          |   12 +-
 admin/unidata/unidata-gen.el                   |  159 ++-
 build-aux/config.guess                         |    6 +-
 build-aux/config.sub                           |    6 +-
 configure.ac                                   |   85 +-
 doc/emacs/Makefile.in                          |    2 +-
 doc/emacs/ack.texi                             |   27 +-
 doc/emacs/anti.texi                            |  203 ++--
 doc/emacs/basic.texi                           |    6 +-
 doc/emacs/cmdargs.texi                         |    6 -
 doc/emacs/custom.texi                          |   55 +-
 doc/emacs/dired.texi                           |    4 +-
 doc/emacs/emacs.texi                           |   16 +-
 doc/emacs/files.texi                           |    1 +
 doc/emacs/fixit.texi                           |    6 +-
 doc/emacs/help.texi                            |    5 +
 doc/emacs/m-x.texi                             |    4 +
 doc/emacs/misc.texi                            |   14 +-
 doc/emacs/package.texi                         |   76 +-
 doc/emacs/trouble.texi                         |   11 +
 doc/lispintro/Makefile.in                      |    2 +-
 doc/lispintro/emacs-lisp-intro.texi            |    2 +-
 doc/lispref/Makefile.in                        |    2 +-
 doc/lispref/anti.texi                          |  342 ++----
 doc/lispref/edebug.texi                        |    5 +
 doc/lispref/elisp.texi                         |    2 +-
 doc/lispref/frames.texi                        |   40 +-
 doc/lispref/functions.texi                     |  196 ++--
 doc/lispref/internals.texi                     |   57 +-
 doc/lispref/keymaps.texi                       |    7 +-
 doc/lispref/modes.texi                         |   18 +-
 doc/lispref/numbers.texi                       |    4 +-
 doc/lispref/objects.texi                       |   40 +-
 doc/lispref/os.texi                            |    3 +-
 doc/lispref/processes.texi                     |   13 +-
 doc/lispref/streams.texi                       |    1 +
 doc/lispref/tips.texi                          |   27 +-
 doc/lispref/variables.texi                     |    3 +
 doc/lispref/windows.texi                       |    4 -
 doc/misc/Makefile.in                           |    2 +-
 doc/misc/calc.texi                             |   11 +-
 doc/misc/cc-mode.texi                          |   22 +-
 doc/misc/dired-x.texi                          |   41 +-
 doc/misc/ediff.texi                            |   37 +-
 doc/misc/efaq.texi                             |   39 +-
 doc/misc/gnus-coding.texi                      |   10 -
 doc/misc/gnus.texi                             |    8 +-
 doc/misc/idlwave.texi                          |    8 +-
 doc/misc/ido.texi                              |    2 +-
 doc/misc/org.texi                              |    7 +-
 doc/misc/reftex.texi                           |    9 +-
 doc/misc/sem-user.texi                         |    2 +-
 doc/misc/smtpmail.texi                         |   23 +-
 doc/misc/speedbar.texi                         |   10 +-
 doc/misc/tramp.texi                            |   85 +-
 doc/misc/trampver.texi                         |    4 +-
 doc/misc/viper.texi                            |    9 +-
 etc/NEWS                                       |  120 +-
 etc/NEWS.24                                    |   10 +-
 etc/NEWS.27                                    |  457 ++++----
 etc/PROBLEMS                                   |   89 ++
 etc/TODO                                       |   43 +-
 lib-src/emacsclient.c                          |   17 +-
 lib/gnulib.mk.in                               |   14 +-
 lib/inttypes.in.h                              |    2 +
 lib/putenv.c                                   |  194 ----
 lib/regex.c                                    |    2 +
 lib/regex_internal.h                           |   53 +-
 lib/stdlib.in.h                                |    7 +
 lib/unistd.in.h                                |    2 +-
 lisp/align.el                                  |    2 +
 lisp/allout.el                                 |  263 +----
 lisp/arc-mode.el                               |    3 +-
 lisp/autorevert.el                             |    6 +-
 lisp/bookmark.el                               |    2 +
 lisp/calc/calc.el                              |    4 +-
 lisp/calendar/iso8601.el                       |   17 +-
 lisp/calendar/lunar.el                         |   27 +-
 lisp/calendar/parse-time.el                    |   98 +-
 lisp/calendar/time-date.el                     |   17 +-
 lisp/calendar/timeclock.el                     |    2 +
 lisp/cedet/ede.el                              |    5 +-
 lisp/cedet/ede/cpp-root.el                     |   15 -
 lisp/cedet/ede/makefile-edit.el                |    3 +-
 lisp/cedet/ede/pconf.el                        |    5 +-
 lisp/cedet/mode-local.el                       |    2 +-
 lisp/cedet/semantic/imenu.el                   |    5 +-
 lisp/cedet/srecode/semantic.el                 |    2 +-
 lisp/cmuscheme.el                              |    2 +
 lisp/cus-edit.el                               |   20 +-
 lisp/cus-start.el                              |    2 +-
 lisp/custom.el                                 |    7 +-
 lisp/desktop.el                                |    7 +-
 lisp/dired-aux.el                              |   16 +-
 lisp/dired-x.el                                |    4 +-
 lisp/dired.el                                  |   37 +-
 lisp/disp-table.el                             |    2 +-
 lisp/emacs-lisp/bindat.el                      |    3 -
 lisp/emacs-lisp/byte-opt.el                    |   22 +-
 lisp/emacs-lisp/bytecomp.el                    |  159 +--
 lisp/emacs-lisp/cconv.el                       |   34 +-
 lisp/emacs-lisp/checkdoc.el                    |  118 +-
 lisp/emacs-lisp/cl-macs.el                     |    5 +-
 lisp/emacs-lisp/debug.el                       |  292 +++--
 lisp/emacs-lisp/edebug.el                      |   24 +-
 lisp/emacs-lisp/eieio-opt.el                   |    9 +-
 lisp/emacs-lisp/eieio-speedbar.el              |    6 +-
 lisp/emacs-lisp/lisp-mnt.el                    |   13 +-
 lisp/emacs-lisp/lisp-mode.el                   |    1 +
 lisp/emacs-lisp/package.el                     |   42 +-
 lisp/emacs-lisp/rx.el                          |    2 +-
 lisp/emacs-lisp/tabulated-list.el              |    8 +-
 lisp/emulation/viper-init.el                   |    2 +
 lisp/erc/erc-autoaway.el                       |    4 +-
 lisp/erc/erc-backend.el                        |    2 +-
 lisp/erc/erc-button.el                         |   15 +-
 lisp/erc/erc-capab.el                          |    2 +-
 lisp/erc/erc-compat.el                         |    4 +-
 lisp/erc/erc-dcc.el                            |    2 +-
 lisp/erc/erc-desktop-notifications.el          |   11 +-
 lisp/erc/erc-ezbounce.el                       |    2 +-
 lisp/erc/erc-fill.el                           |    4 +-
 lisp/erc/erc-goodies.el                        |    2 +-
 lisp/erc/erc-ibuffer.el                        |    3 +-
 lisp/erc/erc-identd.el                         |    2 +-
 lisp/erc/erc-imenu.el                          |    4 +-
 lisp/erc/erc-join.el                           |    4 +-
 lisp/erc/erc-lang.el                           |    4 +-
 lisp/erc/erc-list.el                           |    3 +-
 lisp/erc/erc-log.el                            |    3 +-
 lisp/erc/erc-match.el                          |    7 +-
 lisp/erc/erc-menu.el                           |    2 +-
 lisp/erc/erc-netsplit.el                       |    2 +-
 lisp/erc/erc-networks.el                       |    2 +-
 lisp/erc/erc-notify.el                         |    3 +-
 lisp/erc/erc-page.el                           |    2 +-
 lisp/erc/erc-pcomplete.el                      |    4 +-
 lisp/erc/erc-replace.el                        |    3 +-
 lisp/erc/erc-ring.el                           |    4 +-
 lisp/erc/erc-services.el                       |    3 +-
 lisp/erc/erc-sound.el                          |    3 +-
 lisp/erc/erc-speedbar.el                       |    8 +-
 lisp/erc/erc-spelling.el                       |    4 +-
 lisp/erc/erc-stamp.el                          |    4 +-
 lisp/erc/erc-track.el                          |    4 +-
 lisp/erc/erc-truncate.el                       |    3 +-
 lisp/erc/erc-xdcc.el                           |    2 +-
 lisp/erc/erc.el                                |    2 +-
 lisp/expand.el                                 |    8 +-
 lisp/ezimage.el                                |    2 +-
 lisp/ffap.el                                   |    2 +-
 lisp/filesets.el                               |    2 +-
 lisp/finder.el                                 |    7 -
 lisp/frame.el                                  |    3 +
 lisp/gnus/gnus-agent.el                        |    2 +-
 lisp/gnus/gnus-bookmark.el                     |    8 +-
 lisp/gnus/gnus-cloud.el                        |    8 +-
 lisp/gnus/gnus-draft.el                        |    2 +-
 lisp/gnus/gnus-group.el                        |   10 +-
 lisp/gnus/gnus-icalendar.el                    |    2 +-
 lisp/gnus/gnus-int.el                          |    2 +-
 lisp/gnus/gnus-msg.el                          |   11 +-
 lisp/gnus/gnus-srvr.el                         |    2 +-
 lisp/gnus/gnus-start.el                        |   18 +-
 lisp/gnus/gnus-sum.el                          |    4 +-
 lisp/gnus/gnus-util.el                         |    6 +-
 lisp/gnus/gnus.el                              |    4 +-
 lisp/gnus/mail-source.el                       |    4 +-
 lisp/gnus/message.el                           |    5 +-
 lisp/gnus/mm-archive.el                        |    3 +-
 lisp/gnus/mml-smime.el                         |   11 +-
 lisp/gnus/mml2015.el                           |    9 +-
 lisp/gnus/nnbabyl.el                           |    2 +-
 lisp/gnus/nndiary.el                           |   10 +-
 lisp/gnus/nndoc.el                             |    2 +-
 lisp/gnus/nndraft.el                           |    4 +-
 lisp/gnus/nneething.el                         |    2 +-
 lisp/gnus/nnfolder.el                          |    4 +-
 lisp/gnus/nnheader.el                          |    6 +-
 lisp/gnus/nnimap.el                            |    2 +-
 lisp/gnus/nnir.el                              |   12 +-
 lisp/gnus/nnmail.el                            |    6 +-
 lisp/gnus/nnmaildir.el                         |    6 +-
 lisp/gnus/nnmairix.el                          |    6 +-
 lisp/gnus/nnmbox.el                            |    2 +-
 lisp/gnus/nnmh.el                              |    2 +-
 lisp/gnus/nnml.el                              |   15 +-
 lisp/gnus/nnrss.el                             |    2 +-
 lisp/gnus/nntp.el                              |    2 +-
 lisp/gnus/nnvirtual.el                         |    2 +-
 lisp/help-fns.el                               |   97 ++
 lisp/hexl.el                                   |   11 +-
 lisp/ibuffer.el                                |    2 +
 lisp/icomplete.el                              |   17 +-
 lisp/ido.el                                    |   10 +-
 lisp/image-dired.el                            |   24 +-
 lisp/info.el                                   |   21 +-
 lisp/international/mule-cmds.el                |   96 +-
 lisp/international/titdic-cnv.el               |  236 ++--
 lisp/isearch.el                                |    7 +-
 lisp/ldefs-boot.el                             |  765 +++++++++----
 lisp/leim/quail/latin-ltx.el                   |   32 +-
 lisp/loadup.el                                 |    4 +-
 lisp/mail/rmail.el                             |    5 +-
 lisp/mail/rmailsum.el                          |    2 +-
 lisp/menu-bar.el                               |   45 +-
 lisp/mh-e/mh-show.el                           |   14 +-
 lisp/minibuffer.el                             |   19 +-
 lisp/msb.el                                    |    2 +
 lisp/net/dns.el                                |   16 +-
 lisp/net/nsm.el                                |   12 +-
 lisp/net/sasl-scram-sha256.el                  |   59 +
 lisp/net/sasl.el                               |    5 +-
 lisp/net/shr.el                                |    4 +-
 lisp/net/tramp-adb.el                          |  138 ++-
 lisp/net/tramp-archive.el                      |   21 +-
 lisp/net/tramp-cache.el                        |   38 +-
 lisp/net/tramp-cmds.el                         |    2 +-
 lisp/net/tramp-compat.el                       |   81 +-
 lisp/net/tramp-gvfs.el                         |  645 +++++++++--
 lisp/net/tramp-rclone.el                       |   19 +-
 lisp/net/tramp-sh.el                           |  286 +++--
 lisp/net/tramp-smb.el                          |   94 +-
 lisp/net/tramp-sudoedit.el                     |   63 +-
 lisp/net/tramp-uu.el                           |    5 -
 lisp/net/tramp.el                              |  446 ++++----
 lisp/net/trampver.el                           |   17 +-
 lisp/obsolete/cust-print.el                    |    5 +-
 lisp/obsolete/iswitchb.el                      |    2 +-
 lisp/obsolete/old-whitespace.el                |    8 +-
 lisp/obsolete/rcompile.el                      |    2 +-
 lisp/obsolete/sb-image.el                      |   46 +
 lisp/obsolete/vc-arch.el                       |    1 +
 lisp/obsolete/vi.el                            |    2 +-
 lisp/obsolete/vip.el                           |   14 +-
 lisp/org/ol.el                                 |    4 +-
 lisp/org/org-agenda.el                         |    1 -
 lisp/org/org-element.el                        |    2 +-
 lisp/org/org.el                                |    4 +-
 lisp/org/ox-odt.el                             |    2 +-
 lisp/progmodes/cc-cmds.el                      |   23 +-
 lisp/progmodes/cc-langs.el                     |    5 +-
 lisp/progmodes/cc-menus.el                     |   98 +-
 lisp/progmodes/cc-vars.el                      |   15 +-
 lisp/progmodes/cperl-mode.el                   |    2 +-
 lisp/progmodes/cwarn.el                        |    2 +
 lisp/progmodes/ebnf2ps.el                      |   21 +-
 lisp/progmodes/elisp-mode.el                   |    3 +-
 lisp/progmodes/etags.el                        |   23 +-
 lisp/progmodes/f90.el                          |   19 +-
 lisp/progmodes/flymake-proc.el                 |    2 +-
 lisp/progmodes/fortran.el                      |    2 +-
 lisp/progmodes/gdb-mi.el                       |   13 +-
 lisp/progmodes/grep.el                         |  111 +-
 lisp/progmodes/gud.el                          |    5 +-
 lisp/progmodes/idlwave.el                      |    3 +-
 lisp/progmodes/inf-lisp.el                     |    7 +-
 lisp/progmodes/meta-mode.el                    |    2 +
 lisp/progmodes/sh-script.el                    | 1454 +-----------------------
 lisp/progmodes/vhdl-mode.el                    |    2 +-
 lisp/progmodes/xref.el                         |   18 +-
 lisp/recentf.el                                |    2 +
 lisp/sb-image.el                               |  107 --
 lisp/shell.el                                  |    2 +-
 lisp/simple.el                                 |  101 +-
 lisp/so-long.el                                |    8 +-
 lisp/speedbar.el                               |   74 +-
 lisp/startup.el                                |   46 +-
 lisp/strokes.el                                |    2 +
 lisp/tab-bar.el                                |   48 +-
 lisp/tab-line.el                               |  105 +-
 lisp/textmodes/dns-mode.el                     |    1 +
 lisp/textmodes/ispell.el                       |   50 +-
 lisp/textmodes/paragraphs.el                   |    2 +-
 lisp/textmodes/reftex-vars.el                  |    2 +
 lisp/textmodes/reftex.el                       |    2 +-
 lisp/textmodes/table.el                        |    8 +-
 lisp/thread.el                                 |    2 -
 lisp/time-stamp.el                             |   23 +-
 lisp/url/url-vars.el                           |    2 +
 lisp/vc/ediff-init.el                          |    2 +
 lisp/vc/smerge-mode.el                         |    5 +-
 lisp/vc/vc-git.el                              |    3 +-
 lisp/wdired.el                                 |    2 +
 lisp/window.el                                 |   16 +-
 lisp/woman.el                                  |    2 +-
 lisp/x-dnd.el                                  |   57 +-
 m4/00gnulib.m4                                 |   79 +-
 m4/gnulib-common.m4                            |    3 +-
 m4/gnulib-comp.m4                              |   11 +-
 m4/largefile.m4                                |    4 +
 m4/putenv.m4                                   |   60 -
 m4/unistd_h.m4                                 |    3 +-
 m4/zzgnulib.m4                                 |   23 +
 nt/inc/ms-w32.h                                |    7 +-
 src/Makefile.in                                |    6 +-
 src/alloc.c                                    |  319 ++++--
 src/bytecode.c                                 |    8 +-
 src/callproc.c                                 |   37 +-
 src/coding.c                                   |    2 +
 src/data.c                                     |   66 +-
 src/deps.mk                                    |    3 -
 src/dired.c                                    |    4 +-
 src/dispnew.c                                  |   21 +-
 src/editfns.c                                  |    2 +-
 src/emacs-module.c                             |   66 +-
 src/emacs-module.h.in                          |   14 +-
 src/emacs.c                                    |   82 +-
 src/fileio.c                                   |   40 +-
 src/filelock.c                                 |    3 +-
 src/fns.c                                      |  124 +-
 src/font.c                                     |    1 -
 src/font.h                                     |    6 +-
 src/frame.c                                    |    2 +-
 src/frame.h                                    |    5 +-
 src/ftxfont.c                                  |  371 ------
 src/gtkutil.c                                  |    1 +
 src/image.c                                    |   16 +-
 src/json.c                                     |    1 -
 src/lisp.h                                     |   17 +-
 src/lread.c                                    |    6 +-
 src/mini-gmp.c                                 |  218 ++--
 src/mini-gmp.h                                 |    8 +-
 src/minibuf.c                                  |    8 +-
 src/module-env-28.h                            |    8 +
 src/nsfns.m                                    |   55 +-
 src/nsterm.h                                   |   29 +-
 src/nsterm.m                                   |  922 ++++++++-------
 src/pdumper.c                                  |    2 +-
 src/print.c                                    |   40 +-
 src/sysdep.c                                   |   36 +-
 src/systhread.c                                |   60 +-
 src/systhread.h                                |    5 +-
 src/term.c                                     |    8 +
 src/thread.c                                   |   10 +-
 src/thread.h                                   |    3 +-
 src/w32.c                                      |   21 +
 src/w32.h                                      |    1 +
 src/w32fns.c                                   |    3 +
 src/w32heap.c                                  |   10 +
 src/w32term.c                                  |    6 +-
 src/w32term.h                                  |    4 +
 src/window.c                                   |   21 +-
 src/window.h                                   |    1 -
 src/xdisp.c                                    |  115 +-
 src/xfns.c                                     |   10 +-
 src/xterm.c                                    |    4 +
 test/data/emacs-module/mod-test.c              |   54 +-
 test/lisp/auth-source-pass-tests.el            |    4 +
 test/lisp/autorevert-tests.el                  |    3 +-
 test/lisp/bookmark-tests.el                    |   75 +-
 test/lisp/calendar/iso8601-tests.el            |  154 +--
 test/lisp/ffap-tests.el                        |    2 +-
 test/lisp/filenotify-tests.el                  |   49 +-
 test/lisp/help-fns-tests.el                    |   47 +-
 test/lisp/ibuffer-tests.el                     |    2 +-
 test/lisp/international/ucs-normalize-tests.el |    2 +-
 test/lisp/net/sasl-scram-rfc-tests.el          |   26 +-
 test/lisp/net/tramp-archive-tests.el           |    2 +-
 test/lisp/net/tramp-tests.el                   |  398 ++++---
 test/lisp/progmodes/f90-tests.el               |   20 +
 test/lisp/shadowfile-tests.el                  |    1 -
 test/lisp/shell-tests.el                       |    7 +
 test/lisp/simple-tests.el                      |   58 +-
 test/lisp/subr-tests.el                        |   21 +
 test/lisp/textmodes/conf-mode-tests.el         |    2 +-
 test/src/alloc-tests.el                        |    7 +
 test/src/emacs-module-tests.el                 |   26 +-
 test/src/fns-tests.el                          |   16 +
 test/src/regex-emacs-tests.el                  |    4 +-
 380 files changed, 7425 insertions(+), 7537 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2b9114a..9a62137 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -32,7 +32,7 @@ variables:
 
 before_script:
   - apt update -qq
-  - DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends -y -qq 
-o=Dpkg::Use-Pty=0 libc-dev gcc make autoconf automake libncurses-dev 
gnutls-dev git
+  - DEBIAN_FRONTEND=noninteractive apt install --no-install-recommends -y -qq 
-o=Dpkg::Use-Pty=0 libc-dev gcc g++ make autoconf automake libncurses-dev 
gnutls-dev git
 
 stages:
   - test
diff --git a/ChangeLog.3 b/ChangeLog.3
index d2a1d51..9d171bf 100644
--- a/ChangeLog.3
+++ b/ChangeLog.3
@@ -1427,7 +1427,7 @@
 
        * lisp/startup.el (command-line): Allow XDG-style as well as old
        style paths.
-       * doc/startup.texi: Document the above change.
+       * doc/emacs/custom.texi: Document the above change.
 
 2019-04-11  Eli Zaretskii  <address@hidden>
 
diff --git a/INSTALL b/INSTALL
index 2d257f9..f1ceb2c 100644
--- a/INSTALL
+++ b/INSTALL
@@ -214,42 +214,6 @@ like 'apt-get build-dep emacs' (on older systems, replace 
'emacs' with
 eg 'emacs25').  On Red Hat-based systems, the corresponding command is
 'dnf builddep emacs' (on older systems, use 'yum-builddep' instead).
 
-* GNU/Linux source and debug packages
-
-Many GNU/Linux systems provide separate packages containing the
-sources and debug symbols of Emacs.  They are useful if you want to
-check the source code of Emacs primitive functions or debug Emacs on
-the C level.
-
-The names of the packages that you need vary according to the
-GNU/Linux distribution that you use.  On Debian-based systems, you can
-install a source package of Emacs with a command like 'apt-get source
-emacs' (on older systems, replace 'emacs' with eg 'emacs25').  The
-target directory for unpacking the source tree is the current
-directory.  On Red Hat-based systems, the corresponding command is
-'dnf install emacs-debugsource', with target directory /usr/src/debug
-(this requires to add the *-debuginfo repositories first, via 'dnf
-config-manager --set-enabled fedora-debuginfo updates-debuginfo').
-
-Once you have installed the source package, for example at
-/path/to/emacs-26.1, add the following line to your startup file:
-
-     (setq find-function-C-source-directory
-           "/path/to/emacs-26.1/src")
-
-The installation directory of the Emacs source package will contain
-the exact package name and version number Emacs is installed on your
-system.  If a new Emacs package is installed, the source package must
-be reinstalled as well, and the setting in your startup file must be
-updated.
-
-Emacs debugging symbols are distributed by a debug package.  It does
-not exist for every released Emacs package, this depends on the
-distribution.  On Debian-based systems, you can install a debug
-package of Emacs with a command like 'apt-get install emacs-dbg' (on
-older systems, replace 'emacs' with eg 'emacs25').  On Red Hat-based
-systems, the corresponding command is 'dnf debuginfo-install emacs'.
-
 
 DETAILED BUILDING AND INSTALLATION:
 
diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS
index 05faa58..f7ec181 100644
--- a/admin/MAINTAINERS
+++ b/admin/MAINTAINERS
@@ -126,6 +126,11 @@ Ulf Jasper
            lisp/calendar/icalendar.el
            test/lisp/calendar/icalendar-tests.el
 
+Amin Bandali
+       ERC
+           lisp/erc/*
+           doc/misc/erc.texi
+
 ==============================================================================
 2. Areas that someone is willing to maintain, although he would not
 necessarily mind if someone else was the official maintainer.
@@ -248,6 +253,11 @@ Alan Third
             lisp/term/ns-win.el
             doc/emacs/macos.texi
 
+Amin Bandali
+       Eshell
+           lisp/eshell/*
+           doc/misc/eshell.texi
+
 
 ;;; Local Variables:
 ;;;   coding: utf-8
diff --git a/admin/authors.el b/admin/authors.el
index cc0adb0..f8f7287 100644
--- a/admin/authors.el
+++ b/admin/authors.el
@@ -206,6 +206,7 @@ files.")
     ("Yoni Rabkin" "Yoni Rabkin Katzenell")
     ("Yoshinori Koseki" "KOSEKI Yoshinori" "小関 吉則")
     ("Yutaka NIIBE" "NIIBE Yutaka")
+    (nil "stardiviner")
     )
   "Alist of author aliases.
 
@@ -440,6 +441,24 @@ Changes to files matching one of the regexps in this list 
are not listed.")
     "nt/subdirs.el"
     "config.nt"
     "nextstep/WISHLIST"
+    ;; Removed, replaced by gitmerge.el
+    "admin/bzrmerge.el"
+    ;; Removed in commit f5090b91299
+    "lib/fdatasync.c"
+    ;; Removed as obsolete
+    "nt/README-ftp-server"
+    "admin/notes/font-backend"
+    "gnus-overrides.texi"
+    "CENSORSHIP"
+    "GNU"
+    "LINUX-GNU"
+    "THE-GNU-PROJECT"
+    "WHY-FREE"
+    "MORE.STUFF"
+    "notes/font-backend"
+    ;; ada-mode has been deleted, now in GNU ELPA
+    "ada-mode.texi"
+    "GNUS-NEWS"
     )
   "List of files and directories to ignore.
 Changes to files in this list are not listed.")
@@ -752,6 +771,9 @@ Changes to files in this list are not listed.")
     "org-mac-message.el" "org-mew.el" "org-w3m.el" "org-vm.el" "org-wl.el"
     "org-mks.el" "org-remember.el" "org-xoxo.el" "org-docbook.el"
     "org-freemind.el" "ox-jsinfo.el"
+    "org-irc.el" "org-rmail.el" "org-docview.el" "org-keys.el" "org-mhe.el"
+    "org-gnus.el" "org-bibtex.el" "org-bbdb.el" "org-info.el" "org-eshell.el"
+    "ob-keys.el"
     "org-exp-blocks.el"                     ; maybe this is ob-exp now? dunno
     "org-lparse.el"
     "org-special-blocks.el" "org-taskjuggler.el"
@@ -1076,6 +1098,11 @@ in the repository.")
     ("src/module.c" . "src/emacs-module.c")
     ;; gnulib
     ("lib/strftime.c" . "lib/nstrftime.c")
+    ("test/src/regex-tests.el" . "test/src/regex-emacs-tests.el")
+    ("test/lisp/emacs-lisp/cl-tests.el" . "test/lisp/obsolete/cl-tests.el")
+    ("lisp/net/starttls.el" . "lisp/obsolete/starttls.el")
+    ("url-ns.el" . "lisp/obsolete/url-ns.el")
+    ("gnus-news.texi" . "doc/misc/gnus.texi")
     )
   "Alist of files which have been renamed during their lifetime.
 Elements are (OLDNAME . NEWNAME).")
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 3dee0b7..48c81e6 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -38,7 +38,7 @@ GNULIB_MODULES='
   getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog
   ieee754-h ignore-value intprops largefile lstat
   manywarnings memmem-simple mempcpy memrchr minmax mkostemp mktime nstrftime
-  pathmax pipe2 pselect pthread_sigmask putenv
+  pathmax pipe2 pselect pthread_sigmask
   qcopy-acl readlink readlinkat regex
   sig2str socklen stat-time std-gnu11 stdalign stddef stdio
   stpcpy strnlen strtoimax symlink sys_stat sys_time
diff --git a/admin/notes/font-backend b/admin/notes/font-backend
deleted file mode 100644
index 7572182..0000000
--- a/admin/notes/font-backend
+++ /dev/null
@@ -1,69 +0,0 @@
-Copyright (C) 2002-2020 Free Software Foundation, Inc.
-See the end of the file for license conditions.
-
-
-New font handling mechanism with font backend method
-----------------------------------------------------
-
-The new files are:
-       font.h -- header providing font-backend related structures
-               (most important ones are "struct font" and "struct
-               font_driver"), macros, and etc.
-       font.c -- main font handling code.
-       xfont.c -- font-driver on X for X core fonts.
-       ftfont.c -- generic font-driver for FreeType fonts providing
-               device-independent methods of struct font_driver.
-       xftfont.c -- font-driver on X using Xft for FreeType fonts
-               utilizing methods provided by ftfont.c.
-       ftxfont.c -- font-driver on X directly using FreeType fonts
-               utilizing methods provided by ftfont.c.
-       w32font.c -- font driver on w32 using Windows native fonts,
-               corresponding to xfont.c
-       w32uniscribe.c -- font driver on w32, using the uniscribe API
-               to provide complex script support for opentype fonts on
-               Windows 2000 and later, or earlier versions of Windows
-               with uniscribe installed as an add-on.
-
-So we already have codes for X and w32.  For Mac it seems that we need
-these files:
-       atmfont.c -- font-driver on mac using ATM fonts, corresponding
-               to xfont.c
-As BDF fonts are currently used on w32, we may also implement these:
-       bdffont.c -- generic font-driver for BDF fonts, corresponding to
-               ftfont.c
-       bdfw32font.c -- font-driver on w32 using BDF fonts,
-               corresponding to ftxfont.c
-But, as FreeType already supports BDF fonts, if FreeType and
-Fontconfig are also available on w32, what we need may be:
-       ftw32font.c -- font-driver on w32 directly using FreeType fonts
-               utilizing methods provided by ftfont.c.
-
-It may be interesting if Emacs supports a frame buffer directly and
-has these font driver.
-       ftfbfont.c -- font-driver on FB for FreeType fonts.
-       bdffbfont.c -- font-driver on FB for BDF fonts.
-
-Note: The fontset related codes are not yet matured to work well with
-the font backend method.  So, for instance, even if you start Emacs
-as something like this:
-  % emacs -fn tahoma
-Non-ASCII Latin characters will not be displayed by the font "tahoma".
-In such a case, please try this:
-
-(set-fontset-font "fontset-default" 'latin '("tahoma" . "unicode-bmp"))
-
-
-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/>.
diff --git a/admin/notes/unicode b/admin/notes/unicode
index 6cb1b76..1e41859 100644
--- a/admin/notes/unicode
+++ b/admin/notes/unicode
@@ -256,11 +256,19 @@ nontrivial changes to the build process.
 
        etc/tutorials/TUTORIAL.ja
 
+ * iso-2022-7bit
+
+     This file contains multiple Chinese charsets, and converting it
+     to UTF-8 would lose the charset property and would change the
+     code's behavior.  Although this could be worked around by
+     propertizing the strings, that hasn't been done.
+
+       lisp/international/titdic-cnv.el
+
  * utf-8-emacs
 
      These files contain characters that cannot be encoded in UTF-8.
 
-       lisp/international/titdic-cnv.el
        lisp/language/ethio-util.el
        lisp/language/ethiopic.el
        lisp/language/ind-util.el
diff --git a/admin/nt/README-ftp-server b/admin/nt/README-ftp-server
deleted file mode 100644
index 6829151..0000000
--- a/admin/nt/README-ftp-server
+++ /dev/null
@@ -1,277 +0,0 @@
-Copyright (C) 2001-2020 Free Software Foundation, Inc.
-See the end of the file for license conditions.
-
-                     Precompiled Distributions of
-                          Emacs for Windows
-
-                           Version 24.3
-
-                           March 18, 2013
-
-  This directory contains precompiled distributions for GNU Emacs on
-  Windows (versions before Windows 95 and NT4 are not supported).
-  This port is a part of the standard GNU Emacs distribution from the
-  Free Software Foundation; the precompiled distributions are provided
-  here for convenience since the majority of Windows users are not
-  accustomed to compiling programs themselves.  Corresponding source
-  can be found in the parent directory in emacs-24.3.tar.gz.
-
-* IMPORTANT LEGAL REMINDER
-
-  If you want to redistribute any of the precompiled distributions of
-  Emacs, be careful to check the implications of the GPL.  For instance,
-  if you put the emacs-24.3-bin-i386.zip file from this directory on
-  an Internet site, you must arrange to distribute the source files of
-  the SAME version (i.e. ../emacs-24.3.tar.gz).
-
-  Making a link to our copy of the source is NOT sufficient, since we
-  might upgrade to a new version while you are still distributing the
-  old binaries.
-
-
-* Files in this directory
-
-  + emacs-24.3-bin-i386.zip
-    Windows binaries of Emacs-24.3, with all lisp code and documentation
-    included.
-
-    Download this file if you want a single installation package, and
-    are not interested in the C source code for Emacs. After
-    unpacking, you can optionally run the file bin/addpm.exe to have
-    Emacs add icons to the Start Menu.
-
-    If you need the C source code at a later date, it will be safe to
-    unpack the source distribution on top of this installation.
-
-  + libXpm-3.5.8-w32-src.zip
-    Source code required to compile libXpm-3.5.8 on Windows. Contains
-    a basic Makefile for compiling with mingw32 and a .def file for
-    generating a DLL with the appropriate exports in addition to the
-    source code to provide the subset of functionality Emacs uses from
-    libXpm. This corresponds to the libXpm.dll in emacs-24.3-bin-i386.zip.
-
-* Prerequisites for running Emacs on Windows 9X
-
-  Using Emacs in GUI mode on Windows 95/98/Me requires the UNICOWS.DLL
-  dynamic library, which provides MSLU, the Microsoft Unicode Layer
-  for Windows 9X.  You can freely download it from the Microsoft site.
-
-* Image support
-
-  Emacs 24.3 contains support for images, however for most image
-  formats supporting libraries are required.  This distribution has
-  been tested with the libraries that are distributed with GTK for
-  Windows (http://www.gtk.org/download/win32.php), and the libraries
-  found at http://gnuwin32.sourceforge.net/. The following image
-  formats are supported:
-
-      PBM/PGM/PPM: Supported natively by Emacs. This format is used for
-      the black and white versions of the toolbar icons.
-
-      XPM: a Windows port of the XPM library corresponding to the x.org
-      release of X11R7.3 is included with the binary distribution, but
-      can be replaced by other versions with the name xpm4.dll,
-      libxpm-nox4.dll or libxpm.dll.
-
-      PNG: requires the PNG reference library 1.4 or later, which will
-      be named libpng14.dll or libpng14-14.dll.  LibPNG requires zlib,
-      which should come from the same source as you got libpng.
-      Starting with Emacs 23.3, the precompiled Emacs binaries are
-      built with libpng 1.4.x and later, and are incompatible with
-      earlier versions of libpng DLLs.  So if you have libpng 1.2.x,
-      the PNG support will not work, and you will have to download
-      newer versions.
-
-      JPEG: requires the Independent JPEG Group's libjpeg 6b or later,
-      which will be called jpeg62.dll, libjpeg.dll, jpeg-62.dll or jpeg.dll.
-
-      TIFF: requires libTIFF 3.0 or later, which will be called libtiff3.dll
-      or libtiff.dll.
-
-      GIF: requires libungif or giflib 4.1 or later, which will be
-      called giflib4.dll, libungif4.dll or libungif.dll.
-
-      SVG: not compiled into the binary release, but available if you
-      compile Emacs yourself if you have development packages for all the
-      dependencies. Requires many libraries from GTK and Gnome
-      as well as the base librsvg library. Known to crash Emacs on many
-      sample images.
-
-* XML support
-
-  In order to support XML via libxml2 at runtime, a libxml2-enabled
-  Emacs must be able to find the relevant DLLs during startup; failure
-  to do so is not an error, but libxml2 features won't be available to
-  the running session.
-
-  You can get pre-built binaries (including any required DLL and the
-  header files) at http://sourceforge.net/projects/ezwinports/files/.
-
-* Distributions in .tar.gz and .zip format
-
-  Emacs is distributed primarily as source code in a large gzipped tar
-  file (*.tar.gz).  Because Emacs is quite large and therefore
-  difficult to download over unreliable connections, the Windows
-  binaries are provided in two combinations. The complete lisp source
-  plus executables (bin), and executables only (barebin) for unpacking
-  over the top of the source distribution.  Formerly, we used the same
-  .tar.gz format but since there are no longer legal problems with
-  .zip files, and the latest versions of Windows support these
-  natively, the Windows binaries of Emacs are now distributed as .zip
-  files.
-
-* Distributions for non-x86 platforms
-
-  Distributions for non-x86 platforms are no longer supplied. Older
-  platforms supported by Windows NT no longer seem to be in demand,
-  and Emacs is yet to be ported to 64 bit Windows platforms. If you
-  are willing to help port Emacs 24 to 64 bit versions of Windows,
-  your contribution will be welcome on the emacs-devel mailing list.
-
-* Unpacking distributions
-
-  Ports of GNU gzip and GNU tar for handling the source distribution file
-  format can be found in several places that distribute ports of GNU
-  programs, for example:
-
-    Cygwin:   http://www.cygwin.com/
-    GnuWin32: http://gnuwin32.sourceforge.net/
-
-  Many other popular file compression utilities for Windows are also
-  able to handle gzipped tar files. 7zip is one free Windows graphical
-  program that is able to handle many archive formats.
-
-  Open a command prompt (MSDOS) window.  Decide on a directory in which
-  to place Emacs.  Move the distribution to that directory, and then
-  unpack it as follows.
-
-  If you have the gzipped tar version, use gunzip to uncompress the tar
-  file on the fly, and pipe the output through tar with the "xvf" flags
-  to extract the files from the tar file:
-
-    % gunzip -c some.tar.gz | tar xvf -
-
-  You may see messages from tar about not being able to change the
-  modification time on directories, and from gunzip complaining about a
-  broken pipe.  These messages are harmless and you can ignore them.  On
-  Windows NT, unpacking tarballs this way leaves them in compressed
-  form, taking up less space on disk.  Unfortunately, on Windows 95 and
-  98, a large temporary file is created, so it is better to use the
-  djtarnt.exe program, which performs the equivalent operation in one
-  step:
-
-    % djtarnt -x some.tar.gz
-
-  You may be prompted to rename or overwrite directories when using
-  djtarnt: simply type return to continue (this is harmless).
-
-  Zip files can be unpacked using unzip.exe from info-zip.org
-  if you do not already have other tools to do this.
-
-    % unzip some.zip
-
-  The precompiled binaries can be unpacked using unzip.exe from info-zip.org
-  if you do not already have other tools to do this.
-
-    % unzip some.zip
-
-  Once you have unpacked a precompiled distribution of Emacs, it should
-  have the following subdirectories:
-
-       bin     etc     info    lisp    site-lisp
-
-
-* Unpacking with other tools
-
-  If you do use other utility programs to unpack the distribution, check
-  the following to be sure the distribution was not corrupted:
-
-  + Be sure to disable the CR/LF translation or the executables will
-    be unusable.  Older versions of WinZip would enable this
-    translation by default when unpacking .tar files.  If you are
-    using WinZip, disable it.  (I don't have WinZip myself, and I do
-    not know the specific commands necessary to disable it.)
-
-  + Check that filenames were not truncated to 8.3.  For example, there
-    should be a file lisp/abbrevlist.el; if this has been truncated to
-    abbrevli.el, your distribution has been corrupted while unpacking
-    and Emacs will not start.
-
-  + Check that filenames were not changed by your web-browser.  Some
-    proprietary web-browsers save .tar.gz files as .tar.tar. You might
-    like to consider switching to a Free modern browser if your browser
-    has this bug.
-
-  + I've also had reports that some older "gnuwin32" port of tar
-    corrupts the executables.  Use the latest version from the gnuwin32
-    site or another port of tar instead.
-
-  If you believe you have unpacked the distributions correctly and are
-  still encountering problems, see the section on Further Information
-  below.
-
-
-* Compiling from source
-
-  If you would like to compile Emacs from source, download the source
-  distribution, unpack it in the same manner as a precompiled
-  distribution, and look in the file nt/INSTALL for detailed
-  directions.  It is recommended to use GCC 2.95 or later with MinGW
-  support to compile the source.  The port of GCC included in Cygwin
-  is supported, but check the nt/INSTALL file if you have trouble
-  since some builds of GNU make aren't supported.
-
-
-* Further information
-
-  The Emacs on MS Windows FAQ is distributed with Emacs (info
-  manual "efaq-w32"), and at
-
-       https://www.gnu.org/software/emacs/manual/efaq-w32.html
-
-  In addition to the FAQ, there is a mailing list for discussing issues
-  related to the Windows port of Emacs.  For information about the
-  list, see this Web page:
-
-       https://lists.gnu.org/mailman/listinfo/help-emacs-windows
-
-  To ask questions on the mailing list, send email to
-  address@hidden.  (You don't need to subscribe for that.)
-  To subscribe to the list or unsubscribe from it, fill the form you
-  find at https://mail.gnu.org/mailman/listinfo/help-emacs-windows as
-  explained there.
-
-  Another valuable source of information and help which should not be
-  overlooked is the various Usenet news groups dedicated to Emacs.
-  These are particularly good for help with general issues which aren't
-  specific to the Windows port of Emacs.  The main news groups to use
-  for seeking help are:
-
-       gnu.emacs.help
-       comp.emacs
-
-  There are also fairly regular postings and announcements of new or
-  updated Emacs packages on this group:
-
-       gnu.emacs.sources
-
-  Enjoy!
-
-  Most of this README was contributed by former maintainers Andrew Innes
-  (address@hidden) and Jason Rumney (address@hidden).
-
-
-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/.
diff --git a/admin/nt/dist-build/README-windows-binaries 
b/admin/nt/dist-build/README-windows-binaries
index 39a5871..c8fb579 100644
--- a/admin/nt/dist-build/README-windows-binaries
+++ b/admin/nt/dist-build/README-windows-binaries
@@ -1,24 +1,58 @@
+Copyright (C) 2001-2020 Free Software Foundation, Inc.
+See the end of the file for license conditions.
+
+                     Precompiled Distributions of
+                          Emacs for Windows
+
+                           Jan 1, 2020
+
+  This directory contains precompiled distributions for GNU Emacs on
+  Windows
+
+IMPORTANT LEGAL REMINDER
+========================
+
+If you want to redistribute any of the precompiled distributions of
+Emacs, be careful to check the implications of the GPL.  For instance,
+if you put the compiled file from this directory on an Internet site,
+you must arrange to distribute the source files of the SAME version.
+
+Making a link to our copy of the source is NOT sufficient, since we
+might upgrade to a new version while you are still distributing the
+old binaries.
+
+
 Windows Binaries
 ================
 
-Currently, we provide four different binary packages for Emacs, which
+Currently, we provide six different binary packages for Emacs, which
 are:
 
+emacs-$VERSION-x86_64-installer.exe
+
+Contains a 64-bit build of Emacs with dependencies as an installer
+package.  Mostly, this is the best one to install.
+
 emacs-$VERSION-x86_64.zip
 
-Contains a 64-bit build of Emacs with dependencies. Mostly, this is
-the best one to install.
+Contains a 64-bit build of Emacs with dependencies.  This contains the
+same files as the installer but as a zip file which some users may
+prefer.
 
 emacs-$VERSION-x86_64-no-deps.zip
 
-Contains a 64-bit build of Emacs without any dependencies. This may be
+Contains a 64-bit build of Emacs without any dependencies.  This may be
 useful if you wish to install where the dependencies are already
 available, or if you want the small possible Emacs.
 
+emacs-$VERSION-i686-installer.exe
+
+Contains a 32-bit build of Emacs with dependencies as an installer
+package.  This is useful for running on a 32-bit machine.
+
 emacs-$VERSION-i686.zip
 
-Contains a 32-bit build of Emacs with dependencies. This is useful for
-running on a 32-bit machine.
+Contains a 32-bit build of Emacs with dependencies.
 
 emacs-$VERSION-i686-no-deps.zip
 
@@ -27,7 +61,7 @@ Contains a 32-bit build of Emacs without dependencies
 In addition, we provide the following files which will not be useful
 for most end-users.
 
-emacs-27-x86_64-deps.zip
+emacs-$VERSION-x86_64-deps.zip
 
 The dependencies. Unzipping this file on top of
 emacs-$VERSION-x86_64-no-deps.zip should result in the same install as
@@ -39,7 +73,39 @@ The 32-bit version of the dependencies.
 
 emacs-27-deps-mingw-w64-src.zip
 
-The source for the dependencies. Source for Emacs itself is available
-in the main distribution tarball. These dependencies were produced
-from an updated msys2 at the point of the first pre-test. It is not
-intended that these will be updated after that point.
\ No newline at end of file
+The source for the dependencies.  Source for Emacs itself is available
+in the main distribution tarball.  These dependencies were produced
+from an updated msys2 at the point of the first pre-test.  It is not
+intended that these will be updated after that point.
+
+Source for Emacs itself is found in the directory above.
+
+Snapshots
+=========
+
+We also distribute "snapshots" of Emacs built at points throughout the
+development cycle, for those interested in following this cycle.  They
+are not recommended for normal users.
+
+The files follow the same naming convention, but also include a date
+(and sometimes information about their branch).  The Emacs source at
+the time of these builds is also distributed.
+
+
+LICENSE
+======
+
+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/.
diff --git a/admin/release-process b/admin/release-process
index 504b702..b3dfad5 100644
--- a/admin/release-process
+++ b/admin/release-process
@@ -46,18 +46,22 @@ See admin/gitmerge.el.
 Emacs uses the "blocking" feature of Debbugs for bugs that need to be
 addressed in the next release.
 
-Currently, bug#21966 is the tracking bug for release of 25.2 and
-bug#24655 is the tracking bug for release 26.1.  Say bug#123 needs
-to be fixed for Emacs 26.1.  Send a message to address@hidden
+Currently, bug#39200 is the tracking bug for release of 27.1 and
+bug#39202 is the tracking bug for release 28.1.  Say bug#123 needs
+to be fixed for Emacs 27.1.  Send a message to address@hidden
 that says:
 
-   block 24655 by 123
+   block 39200 by 123
 
 Change "block" to "unblock" to remove a bug from the list.  Closed
 bugs are not listed as blockers, so you do not need to explicitly
 unblock one that has been closed.  You may need to force an update of
 the tracking bug with ctrl-f5/shift-reload to see the latest version.
 
+If you use the debbugs package from GNU ELPA, you can apply the
+following form to see all bugs which block a given release:
+
+  (debbugs-gnu-emacs-release-blocking-reports "27.1")
 
 * TO BE DONE SHORTLY BEFORE RELEASE
 
diff --git a/admin/unidata/unidata-gen.el b/admin/unidata/unidata-gen.el
index 71959d6..73453cb 100644
--- a/admin/unidata/unidata-gen.el
+++ b/admin/unidata/unidata-gen.el
@@ -1,4 +1,4 @@
-;; unidata-gen.el -- Create files containing character property data.
+;; unidata-gen.el -- Create files containing character property data  -*- 
lexical-binding:t -*-
 
 ;; Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
@@ -349,13 +349,10 @@ Property value is a symbol `o' (Open), `c' (Close), or 
`n' (None)."
       (n o c)))))
 
 ;; Functions to access the above data.
-(defsubst unidata-prop-prop (proplist) (nth 0 proplist))
-(defsubst unidata-prop-index (proplist) (nth 1 proplist))
-(defsubst unidata-prop-generator (proplist) (nth 2 proplist))
-(defsubst unidata-prop-docstring (proplist) (nth 3 proplist))
-(defsubst unidata-prop-describer (proplist) (nth 4 proplist))
-(defsubst unidata-prop-default (proplist) (nth 5 proplist))
-(defsubst unidata-prop-val-list (proplist) (nth 6 proplist))
+(cl-defstruct (unidata-prop
+               (:type list)
+               (:constructor nil))
+  prop index generator docstring describer default val-list)
 
 
 ;; SIMPLE TABLE
@@ -383,11 +380,11 @@ Property value is a symbol `o' (Open), `c' (Close), or 
`n' (None)."
 ;;   3rd: 0 (corresponding to uniprop_encode_character in chartab.c)
 ;;   4th to 5th: nil
 
-(defun unidata-gen-table-character (prop prop-idx &rest ignore)
+(defun unidata-gen-table-character (prop prop-idx &rest _ignore)
   (let ((table (make-char-table 'char-code-property-table))
        (vec (make-vector 128 0))
        (tail unidata-list)
-       elt range val idx slot)
+       elt range val)
     (if (functionp prop-idx)
        (setq tail (funcall prop-idx)
              prop-idx 1))
@@ -395,9 +392,9 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
       (setq elt (car tail) tail (cdr tail))
       (setq range (car elt)
            val (nth prop-idx elt))
-      (if (= (length val) 0)
-         (setq val nil)
-       (setq val (string-to-number val 16)))
+      (setq val (if (= (length val) 0)
+                   nil
+                 (string-to-number val 16)))
       (if (consp range)
          (if val
              (set-char-table-range table range val))
@@ -419,8 +416,7 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
                  (setq first-index last-index)))
            (setq tail (cdr tail)))
          (when first-index
-           (let ((str (string 1 first-index))
-                 c)
+           (let ((str (string 1 first-index)))
              (while (<= first-index last-index)
                (setq str (format "%s%c"  str (or (aref vec first-index) 0))
                      first-index (1+ first-index)))
@@ -502,7 +498,7 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
        ;;     bidi.c:bidi_get_type and bidi.c:bidi_get_category.
        (bidi-warning "\
 ** Found new bidi-class `%s', please update bidi.c and dispextern.h")
-       tail elt range val val-code idx slot
+       tail elt range val val-code
        prev-range-data)
     (setq val-list (cons nil (copy-sequence val-list)))
     (setq tail val-list val-code 0)
@@ -510,9 +506,9 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
     (while tail
       (setcar tail (cons (car tail) val-code))
       (setq tail (cdr tail) val-code (1+ val-code)))
-    (if (consp default-value)
-       (setq default-value (copy-sequence default-value))
-      (setq default-value (list default-value)))
+    (setq default-value (if (consp default-value)
+                           (copy-sequence default-value)
+                         (list default-value)))
     (setcar default-value
            (unidata-encode-val val-list (car default-value)))
     (set-char-table-range table t (car default-value))
@@ -602,17 +598,17 @@ Property value is a symbol `o' (Open), `c' (Close), or 
`n' (None)."
          (if (= count 128)
              (if val
                  (set-char-table-range table (cons start limit) val-code))
-           (if (= val-code 0)
-               (set-char-table-range table (cons start limit) str)
-             (if (> count 2)
-                 (setq str (concat str (string val-code (+ count 128))))
-               (if (= count 2)
-                   (setq str (concat str (string val-code val-code)))
-                 (setq str (concat str (string val-code)))))
-             (set-char-table-range table (cons start limit) str))))))
+           (set-char-table-range table (cons start limit)
+                                 (if (= val-code 0)
+                                     str
+                                   (concat str (if (> count 2)
+                                                   (string val-code (+ count 
128))
+                                                 (if (= count 2)
+                                                     (string val-code val-code)
+                                                   (string val-code))))))))))
 
     (set-char-table-extra-slot table 0 prop)
-    (set-char-table-extra-slot table 4 (vconcat (mapcar 'car val-list)))
+    (set-char-table-extra-slot table 4 (vconcat (mapcar #'car val-list)))
     table))
 
 (defun unidata-gen-table-symbol (prop index default-value val-list)
@@ -679,8 +675,7 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
   (let ((beg 0)
        (end 0)
        (len1 (length l1))
-       (len2 (length l2))
-       result)
+       (len2 (length l2)))
     (when (< len1 16)
       (while (and l1 (eq (car l1) (car l2)))
        (setq beg (1+ beg)
@@ -688,13 +683,13 @@ Property value is a symbol `o' (Open), `c' (Close), or 
`n' (None)."
       (while (and (< end len1) (< end len2)
                  (eq (nth (- len1 end 1) l1) (nth (- len2 end 1) l2)))
        (setq end (1+ end))))
-    (if (= (+ beg end) 0)
-       (setq result (list -1))
-      (setq result (list (+ (* beg 16) (+ beg (- len1 end))))))
-    (while (< end len2)
-      (setcdr result (cons (nth (- len2 end 1) l2) (cdr result)))
-      (setq end (1+ end)))
-    result))
+    (let ((result (list (if (= (+ beg end) 0)
+                           -1
+                         (+ (* beg 16) (+ beg (- len1 end)))))))
+      (while (< end len2)
+        (push (nth (- len2 end 1) l2) (cdr result))
+        (setq end (1+ end)))
+      result)))
 
 ;; Return a compressed form of the vector VEC.  Each element of VEC is
 ;; a list of symbols of which names can be concatenated to form a
@@ -703,7 +698,7 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
 ;; elements is usually small.
 
 (defun unidata-word-list-compress (vec)
-  (let (last-elt last-idx diff-head tail elt val)
+  (let (last-elt last-idx diff-head elt val)
     (dotimes (i 128)
       (setq elt (aref vec i))
       (when elt
@@ -768,7 +763,7 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
             (vec (make-vector 128 nil))
             (idx 0)
             (case-fold-search nil)
-            c word-list tail-list last-list word diff-head)
+            c word-list tail-list last-list diff-head)
        (while (< i len)
          (setq c (aref val i))
          (if (< c 3)
@@ -784,7 +779,7 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
                          (setq diff-head
                                (prog1 (aref val i) (setq i (1+ i)))))
                      (setq tail-list (nthcdr (% diff-head 16) last-list))
-                     (dotimes (i (/ diff-head 16))
+                     (dotimes (_ (/ diff-head 16))
                        (setq word-list (nconc word-list (list (car l)))
                              l (cdr l))))))
            (setq word-list
@@ -808,7 +803,7 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
                          (setcdr tail (cons elt (cdr tail)))
                          (setcar tail " ")))
                    (setq tail (cddr tail)))
-                 (setq name (apply 'concat name))))
+                 (setq name (apply #'concat name))))
            (aset table c name)
            (if (= c char)
                (setq val name))))
@@ -872,7 +867,7 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
             (vec (make-vector 128 nil))
             (idx 0)
             (case-fold-search nil)
-            c word-list tail-list last-list word diff-head)
+            c word-list tail-list last-list diff-head)
        (while (< i len)
          (setq c (aref val i))
          (if (< c 3)
@@ -888,7 +883,7 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
                          (setq diff-head
                                (prog1 (aref val i) (setq i (1+ i)))))
                      (setq tail-list (nthcdr (% diff-head 16) last-list))
-                     (dotimes (i (/ diff-head 16))
+                     (dotimes (_ (/ diff-head 16))
                        (setq word-list (nconc word-list (list (car l)))
                              l (cdr l))))))
            (setq word-list
@@ -945,7 +940,7 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
        (word-list (list nil))
        word-table
        block-list block-word-table block-end
-       tail elt range val idx slot)
+       tail elt range val idx)
     (setq tail unidata-list)
     (setq block-end -1)
     (while tail
@@ -984,9 +979,7 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' 
(None)."
                  (push (list val range) block-list))))
        (let* ((start (ash (ash range -7) 7))
               (limit (+ start 127))
-              (first tail)
-              (vec (make-vector 128 nil))
-              c name len)
+              (vec (make-vector 128 nil)))
          (if (<= start block-end)
              ;; START overlap with the previous block.
              (aset table range (nth prop-idx elt))
@@ -1037,10 +1030,10 @@ Property value is a symbol `o' (Open), `c' (Close), or 
`n' (None)."
                               (cdr (assq elt word-list))))
                  (setcar tail (string code))
                  (setq tail (cdr tail)))
-               (aset vec i (mapconcat 'identity (aref vec i) "")))))
+               (aset vec i (mapconcat #'identity (aref vec i) "")))))
          (set-char-table-range
           table (cons idx (+ idx 127))
-          (mapconcat 'identity vec "")))))
+          (mapconcat #'identity vec "")))))
 
     (setq block-word-table (make-vector (length block-list) nil))
     (setq idx 0)
@@ -1086,19 +1079,18 @@ Property value is a symbol `o' (Open), `c' (Close), or 
`n' (None)."
     (or (byte-code-function-p (symbol-function fun))
        (byte-compile fun))))
 
-(defun unidata-gen-table-name (prop index &rest ignore)
+(defun unidata-gen-table-name (prop index &rest _ignore)
   (let* ((table (unidata-gen-table-word-list prop index 'unidata-split-name))
         (word-tables (char-table-extra-slot table 4)))
     (unidata--ensure-compiled 'unidata-get-name 'unidata-put-name)
     (set-char-table-extra-slot table 1 (symbol-function 'unidata-get-name))
     (set-char-table-extra-slot table 2 (symbol-function 'unidata-put-name))
 
-    (if (eq prop 'name)
-       (set-char-table-extra-slot table 4
+    (set-char-table-extra-slot table 4
+                              (if (eq prop 'name)
                                   (vector (car word-tables)
                                           (cdr word-tables)
-                                          unidata-name-jamo-name-table))
-      (set-char-table-extra-slot table 4
+                                          unidata-name-jamo-name-table)
                                 (vector (car word-tables))))
     table))
 
@@ -1107,24 +1099,25 @@ Property value is a symbol `o' (Open), `c' (Close), or 
`n' (None)."
       str
     (let ((len (length str))
          (l nil)
-         (idx 0)
-         c)
+         (idx 0))
       (if (= len 0)
          nil
        (dotimes (i len)
-         (setq c (aref str i))
-         (if (= c 32)
-             (setq l (if (= (aref str idx) ?<)
-                         (cons (intern (substring str (1+ idx) (1- i))) l)
-                       (cons (string-to-number (substring str idx i) 16) l))
-                   idx (1+ i))))
-       (if (= (aref str idx) ?<)
-           (setq l (cons (intern (substring str (1+ idx) (1- len))) l))
-         (setq l (cons (string-to-number (substring str idx len) 16) l)))
+         (let ((c (aref str i)))
+           (when (= c ?\s)
+             (push (if (= (aref str idx) ?<)
+                       (intern (substring str (1+ idx) (1- i)))
+                     (string-to-number (substring str idx i) 16))
+                   l)
+             (setq idx (1+ i)))))
+       (push (if (= (aref str idx) ?<)
+                 (intern (substring str (1+ idx) (1- len)))
+               (string-to-number (substring str idx len) 16))
+             l)
        (nreverse l)))))
 
 
-(defun unidata-gen-table-decomposition (prop index &rest ignore)
+(defun unidata-gen-table-decomposition (prop index &rest _ignore)
   (let* ((table (unidata-gen-table-word-list prop index 
'unidata-split-decomposition))
         (word-tables (char-table-extra-slot table 4)))
     (unidata--ensure-compiled 'unidata-get-decomposition
@@ -1167,7 +1160,7 @@ Property value is a symbol `o' (Open), `c' (Close), or 
`n' (None)."
         (forward-line)))
     result))
 
-(defun unidata-gen-table-special-casing (prop prop-idx &rest ignore)
+(defun unidata-gen-table-special-casing (prop prop-idx &rest _ignore)
   (let ((table (make-char-table 'char-code-property-table)))
     (set-char-table-extra-slot table 0 prop)
     (mapc (lambda (entry)
@@ -1175,7 +1168,7 @@ Property value is a symbol `o' (Open), `c' (Close), or 
`n' (None)."
               ;; If character maps to a single character, the mapping is 
already
               ;; covered by regular casing property.  Don’t store those.
               (when (/= (length v) 1)
-                (set-char-table-range table ch (apply 'string v)))))
+                (set-char-table-range table ch (apply #'string v)))))
           (or unidata-gen-table-special-casing--cache
               (setq unidata-gen-table-special-casing--cache
                     (unidata-gen-table-special-casing--do-load))))
@@ -1353,7 +1346,7 @@ Property value is a symbol `o' (Open), `c' (Close), or 
`n' (None)."
         ;; unidata-gen-table-special-casing--do-load and there is no other file
         ;; to compare those values with.  This is why we’re skipping the check
         ;; for special casing properties.
-        (unless (eq generator 'unidata-gen-table-special-casing)
+        (unless (eq generator #'unidata-gen-table-special-casing)
           (setq table (progn
                         (message "Generating %S table..." prop)
                         (funcall generator prop index default-value val-list))
@@ -1369,19 +1362,21 @@ Property value is a symbol `o' (Open), `c' (Close), or 
`n' (None)."
                   (and (stringp val1)
                        (= (length val1) 0)
                        (setq val1 nil))
-                  (if val1
-                      (cond ((eq generator 'unidata-gen-table-symbol)
-                             (setq val1 (intern val1)))
-                            ((eq generator 'unidata-gen-table-integer)
-                             (setq val1 (string-to-number val1)))
-                            ((eq generator 'unidata-gen-table-character)
-                             (setq val1 (string-to-number val1 16)))
-                            ((eq generator 'unidata-gen-table-decomposition)
-                             (setq val1 (unidata-split-decomposition val1))))
-                    (cond ((eq prop 'decomposition)
-                           (setq val1 (list char)))
-                          ((eq prop 'bracket-type)
-                           (setq val1 'n))))
+                  (setq val1
+                        (if val1
+                            (cond ((eq generator #'unidata-gen-table-symbol)
+                                   (intern val1))
+                                  ((eq generator #'unidata-gen-table-integer)
+                                   (string-to-number val1))
+                                  ((eq generator #'unidata-gen-table-character)
+                                   (string-to-number val1 16))
+                                  ((eq generator 
#'unidata-gen-table-decomposition)
+                                   (unidata-split-decomposition val1))
+                                  (t val1))
+                          (cond ((eq prop 'decomposition)
+                                 (list char))
+                                ((eq prop 'bracket-type)
+                                 'n))))
                   (setq val2 (aref table char))
                   (when decoder
                     (setq val2 (funcall decoder char val2 table)))
diff --git a/build-aux/config.guess b/build-aux/config.guess
index 95b16c7..45001cf 100755
--- a/build-aux/config.guess
+++ b/build-aux/config.guess
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright 1992-2019 Free Software Foundation, Inc.
+#   Copyright 1992-2020 Free Software Foundation, Inc.
 
-timestamp='2019-12-21'
+timestamp='2020-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
@@ -50,7 +50,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright 1992-2019 Free Software Foundation, Inc.
+Copyright 1992-2020 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
diff --git a/build-aux/config.sub b/build-aux/config.sub
index 0f2234c..f02d43a 100755
--- a/build-aux/config.sub
+++ b/build-aux/config.sub
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright 1992-2019 Free Software Foundation, Inc.
+#   Copyright 1992-2020 Free Software Foundation, Inc.
 
-timestamp='2019-06-30'
+timestamp='2020-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
@@ -67,7 +67,7 @@ Report bugs and patches to <address@hidden>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright 1992-2019 Free Software Foundation, Inc.
+Copyright 1992-2020 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
diff --git a/configure.ac b/configure.ac
index 9c8a6e3..e406ae4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -430,7 +430,7 @@ OPTION_DEFAULT_ON([png],[don't compile with PNG image 
support])
 OPTION_DEFAULT_ON([rsvg],[don't compile with SVG image support])
 OPTION_DEFAULT_ON([lcms2],[don't compile with Little CMS support])
 OPTION_DEFAULT_ON([libsystemd],[don't compile with libsystemd support])
-OPTION_DEFAULT_OFF([cairo],[compile with Cairo drawing])
+OPTION_DEFAULT_ON([cairo],[don't compile with Cairo drawing])
 OPTION_DEFAULT_ON([xml2],[don't compile with XML parsing support])
 OPTION_DEFAULT_OFF([imagemagick],[compile with ImageMagick image support])
 OPTION_DEFAULT_ON([json], [don't compile with native JSON support])
@@ -461,7 +461,7 @@ OPTION_DEFAULT_ON([gsettings],[don't compile with GSettings 
support])
 OPTION_DEFAULT_ON([selinux],[don't compile with SELinux support])
 OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support])
 OPTION_DEFAULT_ON([zlib],[don't compile with zlib decompression support])
-OPTION_DEFAULT_ON([modules],[compile with dynamic modules support])
+OPTION_DEFAULT_ON([modules],[don't compile with dynamic modules support])
 OPTION_DEFAULT_ON([threads],[don't compile with elisp threading support])
 OPTION_DEFAULT_OFF([nativecomp],[don't compile with emacs lisp native compiler 
support])
 
@@ -883,11 +883,6 @@ for func in $ac_func_list; do
   test $func = pthread_sigmask || AS_VAR_APPEND([funcs], [" $func"])
 done
 ac_func_list=$funcs
-# Use the system putenv even if it lacks GNU features, as we don't need them,
-# and the gnulib replacement runs afoul of a FreeBSD 10.1 bug; see Bug#19874.
-AC_CHECK_FUNCS_ONCE([putenv])
-AC_DEFUN([gl_FUNC_PUTENV],
-  [test "$ac_cv_func_putenv" = yes || REPLACE_PUTENV=1])
 # Emacs does not use the wchar or wctype-h modules.
 AC_DEFUN([gt_TYPE_WINT_T],
   [GNULIB_OVERRIDES_WINT_T=0
@@ -1509,6 +1504,7 @@ case "$opsys" in
    UNEXEC_OBJ=unexelf.o
    ;;
 esac
+AC_SUBST(UNEXEC_OBJ)
 
 LD_SWITCH_SYSTEM=
 test "$with_unexec" = no || case "$opsys" in
@@ -1562,8 +1558,6 @@ C_SWITCH_MACHINE=
 test $with_unexec = yes &&
 case $canonical in
  alpha*)
-  AC_CHECK_DECL([__ELF__])
-  if test "$ac_cv_have_decl___ELF__" = "yes"; then
     ## With ELF, make sure that all common symbols get allocated to in the
     ## data section.  Otherwise, the dump of temacs may miss variables in
     ## the shared library that have been initialized.  For example, with
@@ -1574,18 +1568,10 @@ case $canonical in
     else
       AC_MSG_ERROR([Non-GCC compilers are not supported.])
     fi
-  else
-      dnl This was the unexalpha.c case.  Removed in 24.1, 2010-07-24,
-      dnl albeit under the mistaken assumption that said file
-      dnl was no longer used.
-      AC_MSG_ERROR([Non-ELF systems are not supported since Emacs 24.1.])
-  fi
   ;;
 esac
 AC_SUBST(C_SWITCH_MACHINE)
 
-AC_SUBST(UNEXEC_OBJ)
-
 C_SWITCH_SYSTEM=
 ## Some programs in src produce warnings saying certain subprograms
 ## are too complex and need a MAXMEM value greater than 2000 for
@@ -1768,7 +1754,7 @@ AC_CHECK_HEADERS_ONCE(
   sys/sysinfo.h
   coff.h pty.h
   sys/resource.h
-  sys/utsname.h pwd.h utmp.h util.h sys/prctl.h)
+  sys/utsname.h pwd.h utmp.h util.h)
 
 AC_CACHE_CHECK([for ADDR_NO_RANDOMIZE],
   [emacs_cv_personality_addr_no_randomize],
@@ -2051,7 +2037,7 @@ NS_OBJ=
 NS_OBJC_OBJ=
 if test "${HAVE_NS}" = yes; then
   if test "$with_toolkit_scroll_bars" = "no"; then
-    AC_MSG_ERROR([Non-toolkit scroll bars are not implemented for Nextstep.])
+    AC_MSG_WARN([Non-toolkit scroll bars are not implemented for Nextstep.])
   fi
 
   window_system=nextstep
@@ -3310,14 +3296,13 @@ if test "${HAVE_X11}" = "yes"; then
     EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE)
     if test $HAVE_CAIRO = yes; then
       AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.])
+      CFLAGS="$CFLAGS $CAIRO_CFLAGS"
+      LIBS="$LIBS $CAIRO_LIBS"
+      AC_SUBST(CAIRO_CFLAGS)
+      AC_SUBST(CAIRO_LIBS)
     else
-      AC_MSG_ERROR([cairo requested but not found.])
+      AC_MSG_WARN([cairo requested but not found.])
     fi
-
-    CFLAGS="$CFLAGS $CAIRO_CFLAGS"
-    LIBS="$LIBS $CAIRO_LIBS"
-    AC_SUBST(CAIRO_CFLAGS)
-    AC_SUBST(CAIRO_LIBS)
   fi
 fi
 
@@ -3383,8 +3368,6 @@ if test "${HAVE_X11}" = "yes"; then
       fi                          # "$HAVE_XFT" != no
     fi                            # "x${with_xft}" != "xno"
 
-    ## We used to allow building with FreeType and without Xft.
-    ## However, the ftx font backend driver is not in good shape.
     if test "$HAVE_XFT" != "yes"; then
        dnl For the "Does Emacs use" message at the end.
        HAVE_XFT=no
@@ -4217,13 +4200,36 @@ pthread_sigmask strsignal setitimer timer_getoverrun \
 sendto recvfrom getsockname getifaddrs freeifaddrs \
 gai_strerror sync \
 getpwent endpwent getgrent endgrent \
-cfmakeraw cfsetspeed __executable_start log2 prctl)
+cfmakeraw cfsetspeed __executable_start log2 pthread_setname_np)
 LIBS=$OLD_LIBS
 
+if test "$ac_cv_func_pthread_setname_np" = "yes"; then
+  AC_CACHE_CHECK(
+   [whether pthread_setname_np takes a single argument],
+   [emacs_cv_pthread_setname_np_1arg],
+   [AC_COMPILE_IFELSE(
+     [AC_LANG_PROGRAM(
+       [[#include <pthread.h>]],
+       [[pthread_setname_np ("a");]])],
+     [emacs_cv_pthread_setname_np_1arg=yes],
+     [emacs_cv_pthread_setname_np_1arg=no])])
+  if test "$emacs_cv_pthread_setname_np_1arg" = "yes"; then
+    AC_DEFINE(
+      HAVE_PTHREAD_SETNAME_NP_1ARG, 1,
+      [Define to 1 if pthread_setname_np takes a single argument.])
+  fi
+fi
+
 dnl No need to check for posix_memalign if aligned_alloc works.
 AC_CHECK_FUNCS([aligned_alloc posix_memalign], [break])
 AC_CHECK_DECLS([aligned_alloc], [], [], [[#include <stdlib.h>]])
 
+case $with_unexec,$canonical in
+  yes,alpha*)
+    AC_CHECK_DECL([__ELF__], [],
+      [AC_MSG_ERROR([Non-ELF systems are not supported on this platform.])]);;
+esac
+
 # Dump loading
 AC_CHECK_FUNCS([posix_madvise])
 
@@ -5292,9 +5298,9 @@ if test "${HAVE_X_WINDOWS}" = "yes" ; then
   if test "$HAVE_CAIRO" = "yes"; then
     FONT_OBJ="$FONT_OBJ ftfont.o ftcrfont.o"
   elif test "$HAVE_XFT" = "yes"; then
-    FONT_OBJ="$FONT_OBJ ftfont.o xftfont.o ftxfont.o"
+    FONT_OBJ="$FONT_OBJ ftfont.o xftfont.o"
   elif test "$HAVE_FREETYPE" = "yes"; then
-    FONT_OBJ="$FONT_OBJ ftfont.o ftxfont.o"
+    FONT_OBJ="$FONT_OBJ ftfont.o"
   fi
 fi
 if test "${HAVE_HARFBUZZ}" = "yes" ; then
@@ -5772,9 +5778,9 @@ case $opsys,$emacs_uname_r in
     AC_MSG_WARN([[building Emacs on Cygwin 1.5 is not supported.]])
            echo
           ;;
-  cygwin,3.0.[[0-7]]'('*)
+  cygwin,3.0.[[0-7]]'('* | cygwin,3.1.[[0-2]]'('*)
     AC_DEFINE([HAVE_CYGWIN_O_PATH_BUG], 1,
-      [Define to 1 if opening a FIFO with O_PATH causes a hang.]);;
+      [Define to 1 if opening a FIFO, socket, or symlink with O_PATH is 
buggy.]);;
 esac
 
 # Remove any trailing slashes in these variables.
@@ -5911,6 +5917,21 @@ you can continue to support by using '$0 --with-pop'.])
   esac
 fi
 
+if test "${HAVE_XFT}" = yes; then
+  AC_MSG_WARN([This configuration uses libXft, which has a number of
+    font rendering issues, and is being considered for removal in the
+    next release of Emacs.  Please consider using Cairo graphics +
+    HarfBuzz text shaping instead (they are auto-detected if the
+    relevant development headers are installed).])
+fi
+
+if test "${HAVE_CAIRO}" = "yes" && test "${HAVE_HARFBUZZ}" = no; then
+  AC_MSG_WARN([This configuration uses the Cairo graphics library,
+    but not the HarfBuzz font shaping library.  We recommend the use
+    of HarfBuzz when using Cairo, please install HarfBuzz development
+    packages.])
+fi
+
 # Let plain 'make' work.
 test "$MAKE" = make || test -f makefile || cat >makefile <<EOF
 .POSIX:
diff --git a/doc/emacs/Makefile.in b/doc/emacs/Makefile.in
index cbda862..53b7d07 100644
--- a/doc/emacs/Makefile.in
+++ b/doc/emacs/Makefile.in
@@ -246,7 +246,7 @@ install-ps: ps
          ${GZIP_PROG} -9n "$(DESTDIR)$(psdir)/$${file}"; \
        done
 
-## Top-level Makefile installs the info pages.
+## Top-level Makefile installs the Info manuals.
 install-doc: install-dvi install-html install-pdf install-ps
 
 
diff --git a/doc/emacs/ack.texi b/doc/emacs/ack.texi
index e8d0a4b..c622488 100644
--- a/doc/emacs/ack.texi
+++ b/doc/emacs/ack.texi
@@ -236,6 +236,12 @@ Andrew Cohen wrote @file{spam-wash.el}, to decode and 
clean email before
 it is analyzed for spam.
 
 @item
+Daniel Colascione wrote the portable dumping code in @file{pdumper.c}
+and elsewhere.  He also implemented double-buffering for X-based GUI
+frames, and the original support for loading shared-object modules
+into Emacs.
+
+@item
 Theresa O'Connor wrote @file{json.el}, a file for parsing and
 generating JSON files.
 
@@ -503,6 +509,10 @@ Tassilo Horn wrote DocView mode, allowing viewing of PDF, 
PostScript and
 DVI documents.
 
 @item
+Khaled Hosny, Yamamoto Mitsuharu, and Eli Zaretskii implemented
+text shaping with HarfBuzz for Emacs.
+
+@item
 Joakim Hove wrote @file{html2text.el}, a html to plain text converter.
 
 @item
@@ -702,7 +712,9 @@ files.
 Juri Linkov wrote @file{misearch.el}, extending isearch to multi-buffer
 searches; the code in @file{files-x.el} for handling file- and
 directory-local variables; and the @code{info-finder} feature that
-creates a virtual Info manual of package keywords.
+creates a virtual Info manual of package keywords.  He also
+implemented the Tab Bar and window tab-lines, and added numerous
+enhancements and improvements in I-search.
 
 @item
 Leo Liu wrote @file{pcmpl-x.el}, providing completion for
@@ -818,6 +830,11 @@ major modes by inheriting key bindings and commands from 
existing major
 modes.
 
 @item
+Jimmy Aguilar Mena wrote the code to support the @code{:extend} face
+attribute, and also implemented the optional
+@code{display-fill-column-indicator} feature.
+
+@item
 Will Mengarini wrote @file{repeat.el}, a command to repeat the preceding
 command with its arguments.
 
@@ -1084,6 +1101,10 @@ Kevin Ryde wrote @file{info-xref.el}, a library for 
checking
 references in Info files.
 
 @item
+Phil Sainty wrote @file{so-long.el}, a set of features for easier
+editing of files with very long lines.
+
+@item
 James B. Salem and Brewster Kahle wrote @file{completion.el}, providing
 dynamic word completion.
 
@@ -1235,6 +1256,10 @@ Tibor Šimko and Milan Zamazal wrote @file{slovak.el}, 
support for
 editing text in Slovak language.
 
 @item
+João Távora wrote many improvements for @file{flymake.el}, an
+on-the-fly syntax-checking package.
+
+@item
 Luc Teirlinck wrote @file{help-at-pt.el}, providing local help through
 the keyboard.
 
diff --git a/doc/emacs/anti.texi b/doc/emacs/anti.texi
index 6cf573e..d1e67e6 100644
--- a/doc/emacs/anti.texi
+++ b/doc/emacs/anti.texi
@@ -4,103 +4,113 @@
 @c See file emacs.texi for copying conditions.
 
 @node Antinews
-@appendix Emacs 25 Antinews
+@appendix Emacs 26 Antinews
 @c Update the emacs.texi Antinews menu entry with the above version number.
 
   For those users who live backwards in time, here is information
-about downgrading to Emacs version 25.3.  We hope you will enjoy the
+about downgrading to Emacs version 26.3.  We hope you will enjoy the
 greater simplicity that results from the absence of many @w{Emacs
 @value{EMACSVER}} features.
 
 @itemize @bullet
 @item
-Emacs no longer defaults to requiring the GnuTLS library when you
-build it.  Those who want the TLS functionality built-in will have to
-explicitly request it at build time---or forever hold their peace.  We
-decided that having the TLS functionality doesn't justify annoying
-users or package builders with error messages about libgnutls absence.
-We also decided that if you do build with GnuTLS, we will allow
-versions of the library older than 2.12.2, as that version will become
-less and less available/popular as you move farther back in time.
+Emacs no longer uses @acronym{GMP}, the GNU Multiple Precision
+library, and doesn't support Lisp integers greater than
+@code{most-positive-fixnum} or smaller than
+@code{most-negative-fixnum}.  We now have only one kind of a Lisp
+integer.  This simplifies many Lisp programs that use integers, and
+makes integer calculations always fast.  If you want larger values,
+use Lisp floats, as Emacs has done since day one.
 
 @item
-For similar reasons, we've reverted back to building our own version
-of @command{movemail} that retrieves POP3 mail as clear text via
-insecure channels.  As you move back in time, the availability of
-secure alternatives to POP3 will diminish, and we are only keen to
-support that.  We've also removed the @option{--with-mailutils}
-configure-time option, as it no longer makes sense for the observable
-past.
+Emacs no longer supports HarfBuzz as the engine for shaping complex
+text.  As you move back in time, we will gradually shed off all traces
+of support for complex text shaping, and this is one step in that
+direction.
 
 @item
-We have removed support for @command{systemd} and similar services: we
-no longer provide a user init file for enabling Emacs support via
-those services, and we removed from the Emacs server the
-socket-launching support important for Emacs client operation under
-these services.  Again, these services will lose popularity as you
-move back in time, so the code supporting them will be just dead code,
-bloating Emacs unnecessarily.
+We have removed support for building with the Jansson library, and
+consequently the native support for JSON parsing is gone.  The
+importance of JSON decreases as we go back in time, so for now using
+the Lisp code for handling it should be good enough; in one of the
+past Emacs versions, we intend to remove even that, as useless bloat.
+
+The library for supporting JSONRPC applications was removed for the
+same reason.
 
 @item
-Reproducible builds of Emacs are no longer supported, as past
-development will make that unnecessary.
+The ``portable dumper'' feature is gone.  We are once again using the
+field-proven ``unexec'' way of dumping Emacs.  With that, the hope for
+being able to re-dump your customized Emacs session is also gone: why
+would anyone want to record their random customization experiments on
+disk, and restore them the next time they start Emacs?  And true
+Emacsers don't restart their Emacs sessions anyway.
 
 @item
-The @option{--fg-daemon} is gone, leaving only @option{--daemon}.  No
-need to procrastinate on the dilemma whether you do or do not want the
-new shiny ``headless Emacs'' thingy.  Hail, simplicity!
+We dropped the support for @acronym{XDG}-style configuration
+directories and the @env{XDG_CONFIG_HOME} environment variable.
+There's once again only one place where Emacs looks for its init
+files: the @file{~/.emacs.d} directory, with the @file{~/.emacs} file
+as fallback.  We think this will go a long way towards preventing
+confusion among users who for some reason have @env{XDG_CONFIG_HOME}
+set, thus risking to have their init files randomly spread between two
+places.  In one of the past Emacs versions, we intend to further
+simplify this, removing the @file{~/.emacs.d} place and leaving only
+@file{~/.emacs}; stay tuned.
+
+For similar reasons, we've removed the ``early init'' file.  You can
+now again use all the tricks you want to initialize variables like
+@code{package-user-dir} and @code{package-load-list} just in time for
+the packages to load.
+
+@command{emacsclient} no longer supports @acronym{XDG}-style directory
+trees, either.
 
 @item
-As text terminals supporting true color will lose ground as you move
-back in time, we've removed support for 24-bit colors on text
-terminals.  If you want colors on a text terminal, you should be fine
-with just 8 of them.  (Truth being told, we think text terminals
-should be monochrome, but you will have to keep downgrading to older
-Emacs versions to have that feature back.)
+TLS connections are back to their lenient security settings.  We
+decided that too tight security settings are an annoyance for users,
+and make little sense considering the world-wide tendency to have
+fewer and fewer network security problems as we move back in time
+(those issues will be completely gone when networks disappear in some
+distant past).
 
 @item
-Emacs 25.3 no longer supports magic signatures of the form
-@samp{#!/usr/bin/env @var{interpreter}} in scripts.  Moving back in
-time means you are getting closer to the ideal of the original Unix
-design where all the interpreters lived in a single directory
-@file{/bin}, so this fancy feature is simply becoming unnecessary
-ballast.
+The @code{server-after-make-frame-hook} hook was deleted, in
+preparation for removing the entire daemon business in some past Emacs
+version.  You will be glad to learn that setting up the GUI
+customizations of your sessions is now once again as easy as it ever
+was, with just the @code{after-make-frame-functions} to use.
 
 @item
-The double-buffering feature of Emacs display on X has been removed.
-We decided that its complexity and a few random surprising
-side-effects aren't justified by the gains, even though those gains
-were hailed in some quarters.  Yes, Emacs 25.3 will flicker in some
-use cases, but we are sure Emacs users will be able to suck it, as
-they have been doing for years.  Since this feature is gone, we've
-also removed the @code{inhibit-double-buffering} frame parameter,
-which is now unnecessary.
+The @code{flex} completion style was removed.  We feel that it
+unnecessarily complicates the Emacs user experience, and therefore
+will continue to remove other tricky completion styles, until in some
+past Emacs version we get to a single original style Emacs pioneered
+decades ago.  Long live simplicity; down with complications!
 
 @item
-Non-breaking hyphens and ASCII characters displayed instead of
-unsupported quote characters are now again displayed using the
-@code{escape-glyph} face.  We think having a single face instead of 3
-different ones will make Emacs customization a much simpler job for
-users.  For the same reason, we've removed the
-@code{header-line-highlight} face, leaving just @code{highlight} for
-any element of the Emacs display besides the mode line.
+The optional display of the fill-column indicator is no longer
+supported.  With the display sizes becoming smaller and smaller as you
+move back in time, we feel that the display itself will always show
+you where to fill or wrap your text, and do this much more easily and
+reliably than any such display indicator.
 
 @item
-You can no longer disable attempts of recovery from fatal exceptions
-such as C stack overflows and fatal signals.  Since the recovery
-included in Emacs is reliable enough, we decided there was no reason
-to put your edits in danger of becoming lost when these situations
-happen.  The variables @code{attempt-stack-overflow-recovery} and
-@code{attempt-orderly-shutdown-on-fatal-signal} are therefore removed.
+We removed the features that made visiting large files easier.  Thus,
+Emacs will no longer suggest visiting a large file literally, nor
+offer the @code{so-long} mode to deal with overly-long lines.  We
+decided that this simplification is worthwhile, given that the general
+tendency of having very large files is becoming a rarity as we move
+back in time.
 
 @item
-The @code{list-timers} command was removed, as we decided timers are
-not a user-level feature, and therefore users should not be allowed to
-mess with them.  Ask an Emacs Lisp guru near you for help if you have
-a runaway timer in your session.  (Of course, as you move back in
-time, such runaway timers will become less and less frequent, and
-actually timers might start shutting down automatically, as they
-cannot cope with time reversal.)
+We have removed the feature that displayed echo-area messages without
+hiding content of the active minibuffer.  This should prevent user
+confusion from having two unrelated pieces of text staring at them,
+with no clear separation between them.  Users with good memories (and
+Emacs users are all expected to be of that kind) will have no trouble
+keeping the minibuffer text in their minds, and typing the responses
+without actually seeing the prompts.
 
 @item
 Horizontal scrolling using the mouse or touchpad has been removed.  In
@@ -110,14 +120,20 @@ horizontal scrolling is the first step towards its 
complete removal in
 prior Emacs versions.
 
 @item
-We have found the @option{--tramp} option of @command{emacsclient} too
-risky and too complicated, so we removed it to simplify the client
-code and its usage.
+The @code{main-thread} variable and @code{list-threads} were removed,
+and @code{thread-join} no longer returns the result of the finished
+thread.  We intend to remove the support for Lisp threads in some past
+Emacs version, so we continue removing the associated complexities and
+features as we go back in time.
 
 @item
-The @code{display-raw-bytes-as-hex} variable is gone, so raw bytes can
-only be displayed as octal escapes.  Emacs users should be able to
-convert from octal to any other base in their sleep!
+Tab bar and window tab-lines were removed.  This should make the Emacs
+display simpler and less cluttered, and help those users who disable
+menu bar and tool bar in their GUI sessions.  The fashion to provide
+tabs in every GUI application out there is gaining less and less
+popularity as we move back in time, and will completely disappear at
+some past point; removing the tabs from Emacs is the step in that
+direction.
 
 @item
 Displaying line numbers for a buffer is only possibly using add-on
@@ -129,42 +145,15 @@ Consequently, @code{display-line-numbers-mode} was 
removed.
 
 @item
 On our permanent quest for simplifying Emacs, we've removed the
-support for passing command-line arguments and options to Emacs via
-the @option{--alternate-editor} option of @command{emacsclient} and
-@env{ALTERNATE_EDITOR} environment variable.  There's only one True
-Emacs---the one that comes up when invoked as @kbd{emacs}, no need for
-all those fancy options!
-
-@item
-The complication known as ``single-line horizontal scrolling'' is no
-longer with you in Emacs 25.3.  This feature was a bow to ``other
-editors''; instead, let those other editors bow to Emacs by hscrolling
-the entire window at all times.  Repeat after me: ``The Emacs way is
-the Only Way!''
-
-@item
-The fancy case conversions of non-ASCII characters used in several
-locales, like Turkish and Greek, are removed, leaving the relations
-between upper and lower letter-case simple again, as they were in
-7-bit ASCII.  Likewise with ligatures that turn into multiple
-characters when their letter-case changes---gone.
-
-@item
-Enchant is no longer supported by @code{ispell-buffer} and similar
-spell-checking commands.  As Enchant will gradually disappear while
-you move back in time, its support will become unnecessary anyway.
-
-@item
-Tramp lost its support for Google Drive repositories.  Cloud storage
-is on its way to extinction as you move back in time, thus making this
-feature redundant.
+support for changing the font size by turning the mouse wheel.
 
 @item
 Several commands, deemed to be unnecessary complications, have been
-removed.  Examples include @code{replace-buffer-contents} and
-@code{apropos-local-variable}.
+removed.  Examples include @code{make-empty-file},
+@code{font-lock-refontify}, @code{xref-find-definitions-at-mouse},
+@code{make-frame-on-monitor}, and @code{diff-buffers}.
 
 @item
 To keep up with decreasing computer memory capacity and disk space, many
-other functions and files have been eliminated in Emacs 25.3.
+other functions and files have been eliminated in Emacs 26.3.
 @end itemize
diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi
index ac953e1..abb385f 100644
--- a/doc/emacs/basic.texi
+++ b/doc/emacs/basic.texi
@@ -117,9 +117,9 @@ which is Unicode code-point U+2018 @sc{left single 
quotation mark},
 sometimes called a left single ``curved quote'' or ``curly quote''.
 Similarly, @kbd{C-x 8 ]}, @kbd{C-x 8 @{} and @kbd{C-x 8 @}} insert the
 curved quotes @t{’}, @t{“} and @t{”}, respectively.  Also, a working
-Alt key acts like @kbd{C-x 8}; e.g., @kbd{A-[} acts like @kbd{C-x 8 [}
-and inserts @t{‘}.  To see which characters have @kbd{C-x 8}
-shorthands, type @kbd{C-x 8 C-h}.
+@key{Alt} key acts like @kbd{C-x 8} (unless followed by @key{RET});
+e.g., @kbd{A-[} acts like @kbd{C-x 8 [} and inserts @t{‘}.  To see
+which characters have @kbd{C-x 8} shorthands, type @kbd{C-x 8 C-h}.
 
   Alternatively, you can use the command @kbd{C-x 8 @key{RET}}
 (@code{insert-char}).  This prompts for the Unicode name or code-point
diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi
index d3fda28..9303b0b 100644
--- a/doc/emacs/cmdargs.texi
+++ b/doc/emacs/cmdargs.texi
@@ -565,12 +565,6 @@ is found there.
 @item HOSTNAME
 @vindex HOSTNAME@r{, environment variable}
 The name of the machine that Emacs is running on.
-@c complete.el is obsolete since 24.1.
-@ignore
-@item INCPATH
-A colon-separated list of directories.  Used by the @code{complete} package
-to search for files.
-@end ignore
 @item INFOPATH
 @vindex INFOPATH@r{, environment variable}
 A colon-separated list of directories in which to search for Info files.
diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi
index 1958a86..f39ce40 100644
--- a/doc/emacs/custom.texi
+++ b/doc/emacs/custom.texi
@@ -1930,10 +1930,12 @@ commonly used, Emacs supports three other modifier 
keys.  These are
 called @key{Super}, @key{Hyper}, and @key{Alt}.  Few terminals provide
 ways to use these modifiers; the key labeled @key{Alt} on most
 keyboards usually issues the @key{Meta} modifier, not @key{Alt}.  The
-standard key bindings in Emacs do not include any characters with
-these modifiers.  However, you can customize Emacs to assign meanings
-to them.  The modifier bits are labeled as @samp{s-}, @samp{H-} and
-@samp{A-} respectively.
+standard key bindings in Emacs do not include any characters with the
+@key{Super} and @key{Hyper} modifiers, and only a small number of
+standard key bindings use @key{Alt}.  However, you can customize Emacs
+to assign meanings to key bindings that use these modifiers.  The
+modifier bits are labeled as @samp{s-}, @samp{H-} and @samp{A-}
+respectively.
 
   Even if your keyboard lacks these additional modifier keys, you can
 enter it using @kbd{C-x @@}: @kbd{C-x @@ h} adds the Hyper flag to
@@ -2655,26 +2657,37 @@ library.  @xref{Hooks}.
 
   Emacs normally finds your init file in a location under your home
 directory.  @xref{Init File}.  By default this location is
-@file{~/.config/emacs/init.el} where @file{~/} stands for your home directory.
+@file{~/.emacs.d/init.el} where @file{~/} stands for your home directory.
 This default can be overridden as described below.
 
-  If @env{XDG_CONFIG_HOME} is set in your environment, its
-value replaces @file{~/.config} in the name of the default
-init file.
-
-  If the default init file's parent directory does not exist but the
-directory @file{~/.emacs.d} does exist, Emacs looks for your init file
+Emacs looks for your init file
 using the filenames @file{~/.emacs.el}, @file{~/.emacs}, or
 @file{~/.emacs.d/init.el}; you can choose to use any one of these
 names.  (Note that only the locations directly in your home directory
-have a leading dot in the location's basename.)  Although this is
-backward-compatible with older Emacs versions, modern POSIX platforms
-prefer putting your initialization files under @file{~/.config} so
-that troubleshooting a problem that might be due to a bad init file,
-or archiving a collection of init files, can be done by renaming that
-directory.  To help older Emacs versions find configuration files in
-their current default locations, you can execute the following
-Emacs Lisp code:
+have a leading dot in the location's basename.)
+
+Emacs can also look in an XDG-compatible location for @file{init.el},
+the default is the directory @file{~/.config/emacs}.  This can be
+overriden by setting @env{XDG_CONFIG_HOME} in your environment, its
+value replaces @file{~/.config} in the name of the default XDG init
+file.  However @file{~/.emacs.d} and @file{~/.emacs} are always
+preferred if they exist, which means that you must delete or rename
+them in order to use the XDG location.
+
+Note also that if neither the XDG location nor @file{~/.emacs.d}
+exist, then Emacs will create @file{~/.emacs.d} (and therefore use it
+during subsequent invocations).
+
+Emacs will set @code{user-emacs-directory} to the directory it decides
+to use.
+
+Although this is backward-compatible with older Emacs versions, modern
+POSIX platforms prefer putting your initialization files under
+@file{~/.config} so that troubleshooting a problem that might be due
+to a bad init file, or archiving a collection of init files, can be
+done by renaming that directory.  To help older Emacs versions find
+configuration files in their current default locations, you can
+execute the following Emacs Lisp code:
 
 @example
 (make-symbolic-link ".config/emacs" "~/.emacs.d")
@@ -2694,7 +2707,7 @@ otherwise, it looks up the home directory corresponding 
to that user
 name in the system's data base of users.
 
   For brevity the rest of the Emacs documentation generally uses just
-the current default location @file{~/.config/emacs/init.el} for the
+the current default location @file{~/.emacs.d/init.el} for the
 init file.
 @c  LocalWords:  backtab
 
@@ -2740,7 +2753,7 @@ Type @kbd{C-q}, followed by the key you want to bind, to 
insert @var{char}.
 @xref{Init File}.  However, it is sometimes desirable
 to have customizations that take effect during Emacs startup earlier than the
 normal init file is processed.  Such customizations can be put in the early
-init file, @file{~/.config/emacs.d/early-init.el} or 
@file{~/.emacs.d/early-init.el}.  This file is loaded before the
+init file, @file{~/.config/emacs/early-init.el} or 
@file{~/.emacs.d/early-init.el}.  This file is loaded before the
 package system and GUI is initialized, so in it you can customize variables
 that affect frame appearance as well as the package initialization process,
 such as @code{package-enable-at-startup}, @code{package-load-list}, and
diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi
index 5a64425..fba4389 100644
--- a/doc/emacs/dired.texi
+++ b/doc/emacs/dired.texi
@@ -720,8 +720,8 @@ should create non-existent directories in @var{new}.
 Dired automatically changes the visited file name of buffers associated
 with renamed files so that they refer to the new names.
 
-@vindex dired-vc-rename
-If the value of the variable @code{dired-vc-rename} is non-@code{nil},
+@vindex dired-vc-rename-file
+If the value of the variable @code{dired-vc-rename-file} is non-@code{nil},
 files are renamed using the commands of the underlying VCS, via
 @code{vc-rename-file} (@pxref{VC Delete/Rename}).
 
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi
index 1368f3e..c3cb37e 100644
--- a/doc/emacs/emacs.texi
+++ b/doc/emacs/emacs.texi
@@ -219,7 +219,7 @@ Appendices
 * GNU Free Documentation License:: The license for this documentation.
 * Emacs Invocation::    Hairy startup options.
 * X Resources::         X resources for customizing Emacs.
-* Antinews::            Information about Emacs version 25.
+* Antinews::            Information about Emacs version 26.
 * Mac OS / GNUstep::     Using Emacs under macOS and GNUstep.
 * Microsoft Windows::   Using Emacs on Microsoft Windows and MS-DOS.
 * Manifesto::           What's GNU?  Gnu's Not Unix!
@@ -1099,6 +1099,7 @@ Hyperlinking and Navigation Features
 Emacs Lisp Packages
 
 * Package Menu::         Buffer for viewing and managing packages.
+* Package Statuses::     Which statuses a package can have.
 * Package Installation:: Options for package installation.
 * Package Files::        Where packages are installed.
 
@@ -1404,6 +1405,7 @@ Berry, Anna M. Bigatti, Ray Blaak, Martin Blais, Jim 
Blandy, Johan
 Bockgård, Jan Böcker, Joel Boehland, Lennart Borgman, Per Bothner,
 Terrence Brannon, Frank Bresz, Peter Breton, Emmanuel Briot, Kevin
 Broadey, Vincent Broman, Michael Brouwer, David M. Brown, Ken Brown, Stefan 
Bruda,
+Daniel Colascione,
 Georges Brun-Cottan, Joe Buehler, Scott Byer, Włodek Bzyl, Tino Calancha,
 Bill Carpenter, Per Cederqvist, Hans Chalupsky, Chris Chase, Bob
 Chassell, Andrew Choi, Chong Yidong, Sacha Chua, Stewart Clamen, James
@@ -1429,7 +1431,7 @@ Guillaume, Dmitry Gutov, Doug Gwyn, Bruno Haible, 
Ken'ichi Handa, Lars Hansen, C
 Hanson, Jesper Harder, Alexandru Harsanyi, K. Shane Hartman, John
 Heidemann, Jon K. Hellan, Magnus Henoch, Markus Heritsch, Dirk
 Herrmann, Karl Heuer, Manabu Higashida, Konrad Hinsen, Anders Holst,
-Jeffrey C. Honig, Tassilo Horn, Kurt Hornik, Tom Houlder, Joakim
+Jeffrey C. Honig, Tassilo Horn, Kurt Hornik, Khaled Hosny, Tom Houlder, Joakim
 Hove, Denis Howe, Lars Ingebrigtsen, Andrew Innes, Seiichiro Inoue,
 Philip Jackson, Martyn Jago, Pavel Janik, Paul Jarc, Ulf Jasper,
 Thorsten Jolitz, Michael K. Johnson, Kyle Jones, Terry Jones, Simon
@@ -1449,7 +1451,7 @@ Lüdecke, Greg McGary, Roland McGrath, Michael McNamara, 
Alan Mackenzie,
 Christopher J. Madsen, Neil M. Mager, Artur Malabarba, Ken Manheimer, Bill 
Mann,
 Brian Marick, Simon Marshall, Bengt Martensson, Charlie Martin,
 Yukihiro Matsumoto, Tomohiro Matsuyama, David Maus, Thomas May, Will 
Mengarini, David
-Megginson, Stefan Merten, Ben A. Mesander, Wayne Mesard, Brad
+Megginson, Jimmy Aguilar Mena, Stefan Merten, Ben A. Mesander, Wayne Mesard, 
Brad
 Miller, Lawrence Mitchell, Richard Mlynarik, Gerd Möllmann, Dani Moncayo, 
Stefan
 Monnier, Keith Moore, Jan Moringen, Morioka Tomohiko, Glenn Morris,
 Don Morrison, Diane Murray, Riccardo Murri, Sen Nagata, Erik Naggum,
@@ -1468,7 +1470,7 @@ Reitter, Alex Rezinsky, Rob Riepel, Lara Rios, Adrian 
Robert, Nick
 Roberts, Roland B. Roberts, John Robinson, Denis B. Roegel, Danny
 Roozendaal, Sebastian Rose, William Rosenblatt, Markus Rost, Guillermo
 J. Rozas, Martin Rudalics, Ivar Rummelhoff, Jason Rumney, Wolfgang
-Rupprecht, Benjamin Rutt, Kevin Ryde, James B. Salem, Masahiko Sato,
+Rupprecht, Benjamin Rutt, Kevin Ryde, Phil Sainty, James B. Salem, Masahiko 
Sato,
 Timo Savola, Jorgen Schäfer, Holger Schauer, William Schelter, Ralph
 Schleicher, Gregor Schmid, Michael Schmidt, Ronald S. Schnell,
 Philippe Schnoebelen, Jan Schormann, Alex Schroeder, Stefan Schoef,
@@ -1481,9 +1483,9 @@ South, Andre Spiegel, Michael Staats, Thomas Steffen, Ulf 
Stegemann,
 Reiner Steib, Sam Steingold, Ake Stenhoff, Philipp Stephani, Peter Stephenson, 
Ken
 Stevens, Andy Stewart, Jonathan Stigelman, Martin Stjernholm, Kim F.
 Storm, Steve Strassmann, Christopher Suckling, Olaf Sylvester, Naoto
-Takahashi, Steven Tamm, Jan Tatarik, Luc Teirlinck, Jean-Philippe Theberge, 
Jens
-T. Berger Thielemann, Spencer Thomas, Jim Thompson, Toru Tomabechi,
-David O'Toole, Markus Triska, Tom Tromey, Eli
+Takahashi, Steven Tamm, Jan Tatarik, João Távora, Luc Teirlinck,
+Jean-Philippe Theberge, Jens T.@: Berger Thielemann, Spencer Thomas,
+Jim Thompson, Toru Tomabechi, David O'Toole, Markus Triska, Tom Tromey, Eli
 Tziperman, Daiki Ueno, Masanobu Umeda, Rajesh Vaidheeswarran, Neil
 W. Van Dyke, Didier Verna, Joakim Verona, Ulrik Vieth, Geoffrey
 Voelker, Johan Vromans, Inge Wallin, John Paul Wallington, Colin
diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi
index 0af3ac2..a89b16b 100644
--- a/doc/emacs/files.texi
+++ b/doc/emacs/files.texi
@@ -1079,6 +1079,7 @@ want to make permanent.  Instead, auto-saving is done in 
a different
 file called the @dfn{auto-save file}, and the visited file is changed
 only when you request saving explicitly (such as with @kbd{C-x C-s}).
 
+@cindex @file{#}, in auto-save file names
   Normally, the auto-save file name is made by appending @samp{#} to the
 front and rear of the visited file name.  Thus, a buffer visiting file
 @file{foo.c} is auto-saved in a file @file{#foo.c#}.  Most buffers that
diff --git a/doc/emacs/fixit.texi b/doc/emacs/fixit.texi
index 171a9bc..3665faf 100644
--- a/doc/emacs/fixit.texi
+++ b/doc/emacs/fixit.texi
@@ -122,14 +122,14 @@ setting the variables @code{undo-limit}, 
@code{undo-strong-limit}, and
   The variable @code{undo-limit} sets a soft limit: Emacs keeps undo
 data for enough commands to reach this size, and perhaps exceed it,
 but does not keep data for any earlier commands beyond that.  Its
-default value is 80000.  The variable @code{undo-strong-limit} sets a
+default value is 160000.  The variable @code{undo-strong-limit} sets a
 stricter limit: any previous command (though not the most recent one)
 that pushes the size past this amount is forgotten.  The default value
-of @code{undo-strong-limit} is 120000.
+of @code{undo-strong-limit} is 240000.
 
   Regardless of the values of those variables, the most recent change
 is never discarded unless it gets bigger than @code{undo-outer-limit}
-(normally 12,000,000).  At that point, Emacs discards the undo data and
+(normally 24,000,000).  At that point, Emacs discards the undo data and
 warns you about it.  This is the only situation in which you cannot
 undo the last command.  If this happens, you can increase the value of
 @code{undo-outer-limit} to make it even less likely to happen in the
diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi
index fce6720..49c53c5 100644
--- a/doc/emacs/help.texi
+++ b/doc/emacs/help.texi
@@ -601,6 +601,11 @@ is @key{ESC}, because @kbd{@key{ESC} C-h} is actually 
@kbd{C-M-h},
 which marks a defun.  However, @w{@kbd{@key{ESC} @key{F1}}} and
 @w{@kbd{@key{ESC} ?}} work fine.)
 
+@findex describe-keymap
+Finally, @kbd{M-x describe-keymap} prompts for the name of a keymap,
+with completion, and displays a listing of all key bindings in that
+keymap.
+
 @node Help Files
 @section Help Files
 
diff --git a/doc/emacs/m-x.texi b/doc/emacs/m-x.texi
index fc2d2d8..b18c334 100644
--- a/doc/emacs/m-x.texi
+++ b/doc/emacs/m-x.texi
@@ -72,6 +72,10 @@ number, in which case Emacs will show the binding for that 
many
 seconds before removing it from display.  The default behavior is to
 display the binding for 2 seconds.
 
+Additionally, when @code{suggest-key-bindings} is non-@code{nil}, the
+completion list of @kbd{M-x} shows equivalent key bindings for all
+commands that have them.
+
 @vindex extended-command-suggest-shorter
   Commands that don't have key bindings, can still be invoked after
 typing less than their full name at the @samp{M-x} prompt.  Emacs
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index ab3318c..6b95b12 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -826,12 +826,14 @@ the output buffer.  But if you change the value of the 
variable
 inserted into a buffer of that name.
 
 @vindex shell-command-dont-erase-buffer
-  By default, the output buffer is erased between shell commands.
-If you change the value of the variable
-@code{shell-command-dont-erase-buffer} to a non-@code{nil} value,
-the output buffer is not erased.  This variable also controls where to
-set the point in the output buffer after the command completes; see the
-documentation of the variable for details.
+  By default, the output buffer is erased between shell commands, except
+when the output goes to the current buffer.  If you change the value
+of the option @code{shell-command-dont-erase-buffer} to @code{erase},
+then the output buffer is always erased.  Any other non-@code{nil}
+value prevents to erase the output buffer.
+
+This option also controls where to set the point in the output buffer
+after the command completes; see the documentation of the option for details.
 
 @node Interactive Shell
 @subsection Interactive Subshell
diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi
index cca602e..1cac7f9 100644
--- a/doc/emacs/package.texi
+++ b/doc/emacs/package.texi
@@ -32,6 +32,7 @@ Manual}.
 
 @menu
 * Package Menu::         Buffer for viewing and managing packages.
+* Package Statuses::     Which statuses a package can have.
 * Package Installation:: Options for package installation.
 * Package Files::        Where packages are installed.
 @end menu
@@ -57,19 +58,12 @@ The package's version number (e.g., @samp{11.86}).
 The package's status---normally one of @samp{available} (can be
 downloaded from the package archive), @samp{installed},
 @c @samp{unsigned} (installed, but not signed; @pxref{Package Signing}),
-or @samp{built-in} (included in Emacs by default).  The status
-@samp{external} means the package is not built-in and not from the
-directory specified by @code{package-user-dir} (@pxref{Package
-Files}).  External packages are treated much like built-in: they
-cannot be deleted through the package menu, and are not considered for
-upgrading.
-
-The status can also be @samp{new}.  This is equivalent to
-@samp{available}, except that it means the package became newly
-available on the package archive after your last invocation of
-@kbd{M-x list-packages}.  In other instances, a package may have the
-status @samp{held}, @samp{disabled}, or @samp{obsolete}.
-@xref{Package Installation}.
+or @samp{built-in} (included in Emacs by default).
+@xref{Package Statuses}.
+
+@item
+Which package archive this package is from, if you have more than one
+package archive enabled.
 
 @item
 A short description of the package.
@@ -139,7 +133,7 @@ current line by an @kbd{i} or @kbd{d} command
 Mark all package with a newer available version for upgrading
 (@code{package-menu-mark-upgrades}).  This places an installation mark
 on the new available versions, and a deletion mark on the old
-installed versions.
+installed versions (marked with status @samp{obsolete}).
 
 @item x
 @kindex x @r{(Package Menu)}
@@ -195,6 +189,60 @@ from lower-priority archives 
(@code{package-menu-toggle-hiding}).
 For example, you can install a package by typing @kbd{i} on the line
 listing that package, followed by @kbd{x}.
 
+@node Package Statuses
+@section Package Statuses
+@cindex package status
+
+A package can have one of the following statuses:
+
+@table @samp
+@item available
+The package is not installed, but can be downloaded and installed from
+the package archive.
+
+@item avail-obso
+The package is available for installation, but a newer version is also
+available.  Packages with this status are hidden by default.
+
+@item built-in
+The package is included in Emacs by default.  It cannot be deleted
+through the package menu, and is not considered for upgrading.
+
+@item dependency
+The package was installed automatically to satisfy a dependency of
+another package.
+
+@item disabled
+The package has been disabled using the @code{package-load-list}
+variable.
+
+@item external
+The package is not built-in and not from the directory specified by
+@code{package-user-dir} (@pxref{Package Files}).  External packages
+are treated much like @samp{built-in} packages and cannot be deleted.
+
+@item held
+The package is held, @xref{Package Installation}.
+
+@item incompat
+The package cannot be installed for some reason, for example because
+it depends on uninstallable packages.
+
+@item installed
+The package is installed.
+
+@item new
+Equivalent to @samp{available}, except that the package became newly
+available on the package archive after your last invocation of
+@kbd{M-x list-packages}.
+
+@item obsolete
+The package is an outdated installed version; in addition to this
+version of the package, a newer version is also installed.
+
+@c @samp{unsigned} (installed, but not signed; @pxref{Package Signing}),
+@end table
+
 @node Package Installation
 @section Package Installation
 
diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi
index 9cbcf20..33f67f2 100644
--- a/doc/emacs/trouble.texi
+++ b/doc/emacs/trouble.texi
@@ -1299,6 +1299,17 @@ emacs-devel mailing list}.
 @end ifhtml
 You can ask for suggested projects or suggest your own ideas.
 
+If you have a feature request or a suggestion for how to improve
+Emacs, the best place to send it is to
+@ifnothtml
+@email{bug-gnu-emacs@@gnu.org}
+@end ifnothtml
+@ifhtml
+@url{https://lists.gnu.org/mailman/listinfo/bug-gnu-emacs, bug-gnu-emacs}
+@end ifhtml
+.  Please explain as clearly as possible what change you would like to
+see, and why and how you think it would improve Emacs.
+
 If you have already written an improvement, please tell us about it.  If
 you have not yet started work, it is useful to contact
 @ifnothtml
diff --git a/doc/lispintro/Makefile.in b/doc/lispintro/Makefile.in
index 3b668f5..7a2b6f0 100644
--- a/doc/lispintro/Makefile.in
+++ b/doc/lispintro/Makefile.in
@@ -145,7 +145,7 @@ install-ps: ps
          ${GZIP_PROG} -9n "$(DESTDIR)$(psdir)/$${file}"; \
        done
 
-## Top-level Makefile installs the info pages.
+## Top-level Makefile installs the Info manuals.
 install-doc: install-dvi install-html install-pdf install-ps
 
 
diff --git a/doc/lispintro/emacs-lisp-intro.texi 
b/doc/lispintro/emacs-lisp-intro.texi
index 87152f4..a6f4b68 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -929,7 +929,7 @@ GNU Emacs Lisp is largely inspired by Maclisp, which was 
written at MIT
 in the 1960s.  It is somewhat inspired by Common Lisp, which became a
 standard in the 1980s.  However, Emacs Lisp is much simpler than Common
 Lisp.  (The standard Emacs distribution contains an optional extensions
-file, @file{cl.el}, that adds many Common Lisp features to Emacs Lisp.)
+file, @file{cl-lib.el}, that adds many Common Lisp features to Emacs Lisp.)
 
 @node Note for Novices
 @unnumberedsec A Note for Novices
diff --git a/doc/lispref/Makefile.in b/doc/lispref/Makefile.in
index 1705852..bd65009 100644
--- a/doc/lispref/Makefile.in
+++ b/doc/lispref/Makefile.in
@@ -206,7 +206,7 @@ install-ps: ps
          ${GZIP_PROG} -9n "$(DESTDIR)$(psdir)/$${file}"; \
        done
 
-## Top-level Makefile installs the info pages.
+## Top-level Makefile installs the Info manuals.
 install-doc: install-dvi install-html install-pdf install-ps
 
 
diff --git a/doc/lispref/anti.texi b/doc/lispref/anti.texi
index 5421d77..a134e88 100644
--- a/doc/lispref/anti.texi
+++ b/doc/lispref/anti.texi
@@ -6,276 +6,184 @@
 @c This node must have no pointers.
 
 @node Antinews
-@appendix Emacs 25 Antinews
+@appendix Emacs 26 Antinews
 @c Update the elisp.texi Antinews menu entry with the above version number.
 
 For those users who live backwards in time, here is information about
-downgrading to Emacs version 25.3.  We hope you will enjoy the greater
+downgrading to Emacs version 26.3.  We hope you will enjoy the greater
 simplicity that results from the absence of many @w{Emacs
 @value{EMACSVER}} features.
 
-@section Old Lisp Features in Emacs 25
-
 @itemize @bullet
 @item
-The concurrency features have been removed.  Even in its limited
-``mostly cooperative'' form, with only one Lisp thread running at any
-given time, it made Emacs significantly more complex for Lisp programs
-that need to work correctly in the presence of additional threads.
-
-@item
-Handling of file attributes has been simplified by discarding the
-accessor functions, such as @code{file-attribute-type} and
-@code{file-attribute-modification-time}.  Real Lisp programmers always
-access the individual attributes by their ordinal numbers, and can
-recite those numbers in their sleep.
-
-@item
-The networking code is back at its pristine simplicity, as we deleted
-the use of asynchronous DNS resolution, connection, and TLS
-negotiation for TLS streams.  You no longer need to consider the
-resulting complexity and interesting race conditions when you write
-Lisp programs that use network communications.  As a direct
-consequence, the @code{:complete-negotiation} parameter of
-@code{gnutls-boot} has become unnecessary, and was removed---just one
-example of how removal of asynchronicity simplifies Emacs.
-
-@item
-We've removed the @file{puny.el} library, so Web sites with
-non-@acronym{ASCII} URLs are no longer easily accessible.  But such
-sites become more and more rare as you move back in time, so having a
-specialized library for their support was deemed an unnecessary
-maintenance burden.
-
-@item
-The time conversion functions @code{current-time-string},
-@code{current-time-zone}, @code{decode-time},
-@code{format-time-string}, and @code{set-time-zone-rule} no longer
-accept integer offsets as time zone rules, to make it more of a
-challenge to convert foreign timestamps.  Also,
-@code{format-time-string} no longer converts @samp{%q} to the calendar
-quarter, as that is something you can easily do for yourself.
-
-@item
-Field numbers like @samp{%2$} in format specifiers are no longer
-available.  We decided that their use makes code reading and
-comprehension much harder, and that having them is unjustified in the
-past where similar features in popular C libraries will also be gone.
-
-@item
-Since the built-in capability to display line numbers has been removed
-(@pxref{Antinews,,, emacs, The GNU Emacs Manual}), we've also deleted
-the @code{line-number-display-width} function and the support for the
-@code{display-line-numbers-disable} property, as Lisp programs that do
-their own display layout decisions no longer need to cater to this
-tricky feature.
-
-@item
-Regular expressions have been simplified by removing support for
-Unicode character properties in the @code{[:blank:]} regexp class.  As
-result, this class will match only spaces and tabs.  Once again, this
-is in line with diminishing importance of Unicode as you move back in
-time.
-
-@item
-For similar reasons, we removed the function @code{char-from-name}.
-It should be easy enough to access the full list of Unicode characters
-returned by @code{ucs-names} instead, for as long as Unicode support
-in Emacs exists (which shouldn't be too long).
-
-@item
-Various functions that accept file names as arguments, such as
-@code{file-attributes}, @code{file-symlink-p}, and
-@code{make-symbolic-link} gained back the special support for file
-names quoted with @samp{/:}, and they now interpret @samp{~} in
-symlink targets as you'd expect: to mean your home directory.  The
-confusing differences between the operation of these functions in
-interactive and non-interactive invocations has been removed.
-
-@item
-Several functions that create or rename their files now treat their
-destination specially if it happens to be a directory, even when its
-name does not appear to be that of a directory.  For example,
-@code{(rename-file "A" "B")} no longer renames @file{A} to @file{B} if
-@file{B} happens to be a directory.  This is so that dealing with
-files becomes more of an adventure.
+Lisp objects are again implemented on the C level as integer types,
+not as pointers.  This might be a small step for Emacs Lisp users, but
+it's a giant leap for the Emacs developers who work on the C level,
+since it is now again easy to print Lisp object in the debugger in the
+decimal format, which is so much easier for debugging.  It also makes
+calling Emacs functions from the debugger easier, and allows us to
+freely mix integers and Lisp objects in the C code.
 
 @item
-The @code{format} function now returns new strings in more cases, to
-place more stress on the Emacs memory manager and thereby test Emacs
-better.
+The test suite was removed from the distribution tarball.  We believe
+that tests need seldom if ever be run, certainly not by the end
+users.  Removing the tests from the tarball makes it much smaller,
+which is important since disk space becomes more and more at premium
+as you move back in time.
 
 @item
-The function @file{assoc} has been simplified by removing its third
-optional argument.  It now always uses @code{equal} for comparison.
-Likewise, @code{alist-get} always uses @code{assq}, and @code{map-get}
-and @code{map-put} always use @code{eql} for their comparisons.
+Dynamic module support is disabled by default.  This both makes Emacs
+smaller (a worthy goal by itself), and removes the complications and
+additional complexity related with installing module support files and
+letting random shared objects an opportunity to be loaded into Emacs
+and mess with it.
 
 @item
-Numeric comparisons and the functions @code{format},
-@code{make-hash-table}, @code{min}, @code{max} and @code{logb} now
-occasionally round values internally to make their results less
-predictable.
+You now must activate any installed packages only after loading your
+init files.  That requires an explicit call to
+@code{package-initialize} in your init file, which is a Good Thing, as
+it makes you think seriously where and indeed whether you'd like your
+packages to become available to your sessions.  Simplicity should
+tramp convenience!
 
 @item
-The functions @code{ffloor}, @code{fceiling}l, @code{ftruncate} and
-@code{fround} now accept integer arguments.  Conversely, functions
-like @code{decode-char} that accept floating-point integers now accept
-arguments that are not integers.  In both cases the results are
-amusingly nonsensical sometimes.
+To reduce the amount of code in Emacs related to unimportant features,
+we've removed native rotation and resizing of images.  You will have
+to build Emacs with ImageMagick if you want to resize or rotate images
+inside Emacs.  We don't expect anyone to miss that.
 
 @item
-GnuTLS cryptographic functions are no longer available in Emacs.  We
-have decided that the needs for such functionality are deteriorating,
-and their cumbersome interfaces make them hard to use.
+We've re-enabled color fonts usage by the XFT font back-end.  We
+consider the availability of these fonts more important than a random
+crash here and there, especially since the use of these fonts for
+displaying Emoji will become less and less important as we travel back
+in time, and will completely disappear in some past Emacs version.
 
 @item
-We have removed support for records of user-defined types, and
-@code{cl-defstruct} no longer uses records.  This removes the
-potential for quite a few places where existing and past code could be
-broken by records.
+The function @code{network-interface-list} can now return only IPv4
+addresses.  We consider the complexity introduced by IPv6 to be too
+much to be justified, and on the other hand its removal is the step in
+the right direction, given that IPv6 is expected to be completely
+removed as we move back in time.
 
 @item
-You can again use @code{string-as-unibyte},
-@code{string-make-multibyte}, and other similar functions, without
-being annoyed by messages about their deprecation.  This is in
-preparation for removal of multibyte text from Emacs in the distant
-past.
+The limit on repetitions in regular expressions was reduced to
+@ifnottex
+2**15 @minus{} 1.
+@end ifnottex
+@tex
+@math{2^{15}-1}.
+@end tex
+We envision that regular expressions will become more and more simple
+as we move towards the distant past.
 
 @item
-The @code{string-version-lessp} function has been removed, to
-encourage programmers to use their own idiosyncratic methods to
-determine whether one version string precedes another.
+To simplify code and reduce complexity, we removed the capability of
+searching programs on remote hosts in @code{executable-find}.  If you
+really need this feature (why would you?), you can always write your
+own shell script and run it on the remote.
 
 @item
-The function @code{read-color} no longer displays color names using
-each color as the background.  We have determined that this surprises
-users and produces funny inconsistent results on color-challenged
-terminals.
+The @code{:extend} face attribute is no longer available; all faces
+have their background color extended by default past end of line.
+This should significantly simplify face management and remove
+unnecessary code bloat, as well as make faces significantly simpler to
+understand and use.
 
 @item
-Support for 24-bit color on text terminals has been dropped, since
-it wasn't needed long ago.
+The predicates @code{display-blink-cursor-p} and
+@code{display-symbol-keys-p} were deleted.  They are rarely if ever
+needed, and can easily be substituted by appropriate calls to old and
+proven APIs like @code{display-graphic-p}.  As an additional bonus,
+writing Lisp programs that depend on this functionality will make sure
+the programmer understands better what exactly is the required
+features of the display terminal.
 
 @item
-We removed the function @code{file-name-case-insensitive-p}, as
-testing for the OS symbol should be enough for the observable past to
-come, and learning to use yet another API is a burden.
+Relative directories in the value of the @env{HOME} environment
+variable are once again interpreted relative to the
+@code{default-directory} of the current buffer.  This is much simpler,
+and also allows @env{HOME} to resolve to a different place in
+different buffers, which allows some interesting applications.
 
-@item
-The function @code{read-multiple-choice} is also gone, in recognition
-of the fact that nothing makes Emacs Lisp hackers rejoice more than
-the need to sit down and write yet another interactive
-question-and-answer function, and make it optimal for each specific
-case.
-
-@item
-The function @code{add-variable-watcher} and the corresponding
-debugger command @code{debug-on-variable-change} have been removed.
-They make debugging more complicated, while examining the value of a
-variable at each stop point is easy enough to cover the same use
-cases.  Let simplicity rule!
-
-@item
-The function @code{mapcan} is gone; use @code{mapcar} instead, and
-process the resulting list as you see fit.
-
-@item
-Low-level list functions like @code{length} and @code{member} can now
-loop indefinitely when given cyclic lists, causing Emacs to freeze.
-This can help these functions run a tiny bit faster in the usual case
-where the input is not cyclic.
-
-@item
-The @code{write-region} function no longer propagates its
-@var{lockname} argument to file name handlers.
-
-@item
-You can once again write a Lisp program that returns funny random
-values from @code{file-attributes} by having another process alter the
-filesystem while Emacs is accessing the file.  This can give rise to
-some interesting applications in the near past.
-
-@item
-The functions @code{file-attributes}, @code{file-symlink-p}, and
-@code{make-symbolic-link} now quietly mutate the target of a local
-symbolic link in some cases, to make it more of a challenge to deal
-with arbitrary symlinks in Emacs code.
-
-@item
-The error @code{file-missing} has been removed; operations now lump
-such errors into the @code{file-error} category instead.
-
-@item
-The function @code{delete-directory} now signals an error if operating
-recursively and some other process deletes the directory before this
-function gets to it.
-
-@item
-The @code{dutch} input method now attempts to support Turkish too,
-albeit incorrectly.  Also, it converts @samp{IJ} and @samp{ij} to
-special characters instead of leaving them alone.
-
-@item
-Non-breaking hyphens and approximations to quotes are now displayed
-just with the @code{escape-glyph} face instead of having faces of
-their own.  This is simpler and gives the user amusing puzzles to
-solve when viewing text containing these characters.
+For the same reasons, @code{file-name-absolute-p} now again considers
+@file{~foo} an absolute file name, even if there's no known user
+@samp{foo}.  This means a Lisp program which uses such file names will
+always work the same on any system, regardless of its known users.
 
 @item
-The user option @code{electric-quote-context-sensitive} and the
-variable @code{electric-quote-inhibit-functions}, so that electric
-quoting is simpler and more likely to do the wrong thing.
+File-related primitives like @code{file-attributes},
+@code{file-modes}, @code{file-newer-than-file-p}, and some others once
+again return @code{nil} when the underlying low-level APIs fail,
+instead of signaling an error.  We decided that functions which signal
+errors require more complex code from Lisp programs which use them,
+and found this complexity unjustified when returning @code{nil} will
+do.
 
 @item
-The user option @code{text-quoting-style} has been removed, and is now
-just a variable.
+Similarly, old-style backquotes no longer signal errors; they generate
+warnings instead.  You can remove error handling from programs that
+use backquotes.
 
 @item
-We have removed the functions @code{file-name-quote},
-@code{file-name-unquote}, and @code{file-name-quoted-p}.  Writing code
-that checks whether a file name is already quoted is easy, and doubly
-quoting a file name should not produce any problems for well-written
-Lisp code.
+Formatting floating-point numbers has been sped up by letting the
+underlying implementation produce unpredictable values, instead of
+signaling errors when the number is too large to format correctly.  We
+believe the Emacs Lisp programmers should always know what they are
+doing when they deal with floating-point values.
 
 @item
-Frame parameters like @code{z-group}, @code{min-width},
-@code{parent-frame}, @code{delete-before}, etc. have been removed.
-Emacs should not replace your window-manager, certainly not as
-window-managers become less and less capable.
+The function @code{read-char-from-minibuffer} was deleted.  We decided
+that @code{read-char} should be enough for any Lisp program that needs
+to ask the user for a single-character input, in recognition of the
+fact that nothing makes Emacs Lisp hackers rejoice more than the need
+to sit down and write yet another interactive question-and-answer
+function, and make it optimal for each specific case.  Consequently,
+no history is provided for such responses (why would someone want
+history of single-key strokes, anyway?).
 
 @item
-We decided that the format of mode line and header line should be
-customizable only based on buffers; the @code{mode-line-format} and
-@code{header-line-format} window parameters have been removed.
+The function @code{ngettext} was deleted.  Non-English languages will
+become less and less widespread, let alone useful, as you move back in
+time, so we took this small step in that direction, and simplified
+Emacs as a nice bonus.
 
 @item
-Emacs now normally builds a limited @command{movemail} substitute that
-retrieves POP3 email only via insecure channels, and the
-configure-time option @option{--with-mailutils} has been removed.
-This simplifies Emacs setup when security is not important.
+Focus-change notifications on text-mode frames are no longer
+recognized or supported.  You can now safely disregard the possibility
+of receiving such notifications on TTY frames.  This is one small step
+on the long road of removing all non-character input events Emacs
+supports on TTY frames.
 
 @item
-The configure-time option @option{--enable-gcc-warnings=warn-only}
-has been removed, so that build-time warnings are always fatal now.
+Face specifications in @code{face-remapping-alist} now have to be
+buffer-specific, without any differences between windows showing the
+same buffers.  This allowed us to remove a lot of unneeded code bloat
+from Emacs, and make the face handling much simpler.
 
 @item
-The configure-time option @option{--disable-build-details} has been
-removed.  This way, Emacs builds are unique and irreproducible.
+The @samp{%o} and @samp{%x} formats now always produce unsigned
+values, as you'd expect.  This allows you to reveal the underlying
+machine representation, which is different on each architecture,
+something we consider a valuable feature.
 
 @item
-The variable @code{emacs-version} now includes the build number
-instead of storing it separately in @code{emacs-build-number}.
+We no longer highlight in @code{font-lock-warning-face} symbols with
+confusable quote characters, such as U+2018.  Detecting them
+needed  non-trivial amount of code, and we firmly believe that Lisp
+programmers always know what they are doing, and don't need to be
+annoyed with typefaces that stand out and distract.
 
 @item
-Emacs has been ported to IRIX.
+The function @code{file-system-info} was dropped on Posix platforms,
+since you can always invoke @command{df} instead and parse its
+output.
 
 @item
-Several options and variables have been removed to simplify Emacs and
-potentially make it less reliable.  These include the
-@option{--module-assertions} option, the
-@code{attempt-stack-overflow-recovery} variable, and the
-@code{attempt-orderly-shutdown-on-fatal-signal} variable.
+The functions that implement the @samp{base64url} encoding were
+removed, as they can always be emulated by suitable tweaking of the
+normal base-64 encoding.  No need to bloat Emacs and force Lisp
+programmers learn more interfaces on this account.
 
 @item
 As part of the ongoing quest for simplicity, many other functions and
diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi
index 8be8307..cfef5c1 100644
--- a/doc/lispref/edebug.texi
+++ b/doc/lispref/edebug.texi
@@ -1362,6 +1362,11 @@ while matching the remainder of the specifications at 
this level.  This
 is primarily used to generate more specific syntax error messages.  See
 @ref{Backtracking}, for more details.  Also see the @code{let} example.
 
+@item &error
+@code{&error} should be followed by a string, an error message, in the
+edebug-spec; it aborts the instrumentation, displaying the message in
+the minibuffer.
+
 @item @var{other-symbol}
 @cindex indirect specifications
 Any other symbol in a specification list may be a predicate or an
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index c157079..cfd96f7 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -233,7 +233,7 @@ To view this manual in other formats, click
 
 Appendices
 
-* Antinews::                Info for users downgrading to Emacs 25.
+* Antinews::                Info for users downgrading to Emacs 26.
 * GNU Free Documentation License:: The license for this documentation.
 * GPL::                     Conditions for copying and changing GNU Emacs.
 * Tips::                    Advice and coding conventions for Emacs Lisp.
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 05038c6..2bb505c 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -2192,10 +2192,11 @@ it and see if it works.)
 @vindex ns-appearance@r{, a frame parameter}
 @item ns-appearance
 Only available on macOS, if set to @code{dark} draw this frame's
-window-system window using the ``vibrant dark'' theme, otherwise use
-the system default.  The ``vibrant dark'' theme can be used to set the
-toolbar and scrollbars to a dark appearance when using an Emacs theme
-with a dark background.
+window-system window using the ``vibrant dark'' theme, and if set to
+@code{light} use the ``aqua'' theme, otherwise use the system default.
+The ``vibrant dark'' theme can be used to set the toolbar and
+scrollbars to a dark appearance when using an Emacs theme with a dark
+background.
 
 @vindex ns-transparent-titlebar@r{, a frame parameter}
 @item ns-transparent-titlebar
@@ -2294,20 +2295,23 @@ variable do not take effect immediately, only when you 
specify the
 @item font-backend
 A list of symbols, specifying the @dfn{font backends} to use for
 drawing characters on the frame, in order of priority.  In Emacs built
-without Cairo drawing on X, there are currently three available font
-backends: @code{x} (the X core font driver), @code{xft} (the Xft font
-driver), and @code{xfthb} (the Xft font driver with HarfBuzz text
-shaping).  If built with the Cairo drawing, there are also three
-available font backends on X: @code{x}, @code{ftcr} (the FreeType font
-driver on Cairo), and @code{ftcrhb} (the FreeType font driver on Cairo
-with HarfBuzz text shaping).  On MS-Windows, there are currently three
-available font backends: @code{gdi} (the core MS-Windows font driver),
-@code{uniscribe} (font driver for OTF and TTF fonts with text shaping
-by the Uniscribe engine), and @code{harfbuzz} (font driver for OTF and
-TTF fonts with HarfBuzz text shaping) (@pxref{Windows Fonts,,, emacs,
-The GNU Emacs Manual}).  On other systems, there is only one available
-font backend, so it does not make sense to modify this frame
-parameter.
+without Cairo drawing on X, there are currently three potentially
+available font backends: @code{x} (the X core font driver), @code{xft}
+(the Xft font driver), and @code{xfthb} (the Xft font driver with
+HarfBuzz text shaping).  If built with Cairo drawing, there are also
+three potentially available font backends on X: @code{x}, @code{ftcr}
+(the FreeType font driver on Cairo), and @code{ftcrhb} (the FreeType
+font driver on Cairo with HarfBuzz text shaping).  When Emacs is built
+with HarfBuzz, the default font driver is @code{ftcrhb}, although use
+of the @code{ftcr} driver is still possible, but not recommended.  On
+MS-Windows, there are currently three available font backends:
+@code{gdi} (the core MS-Windows font driver), @code{uniscribe} (font
+driver for OTF and TTF fonts with text shaping by the Uniscribe
+engine), and @code{harfbuzz} (font driver for OTF and TTF fonts with
+HarfBuzz text shaping) (@pxref{Windows Fonts,,, emacs, The GNU Emacs
+Manual}).  The @code{harfbuzz} driver is similarly recommended.  On
+other systems, there is only one available font backend, so it does
+not make sense to modify this frame parameter.
 
 @vindex background-mode@r{, a frame parameter}
 @item background-mode
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index 8e3e6ae..5cf67ba 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -576,8 +576,9 @@ naming conventions, which are being phased out.
 @cindex defining a function
 
   We usually give a name to a function when it is first created.  This
-is called @dfn{defining a function}, and it is done with the
-@code{defun} macro.
+is called @dfn{defining a function}, and we usually do it with the
+@code{defun} macro.  This section also describes other ways to define
+a function.
 
 @defmac defun name args [doc] [declare] [interactive] body@dots{}
 @code{defun} is the usual way to define new Lisp functions.  It
@@ -682,95 +683,8 @@ definition will have no effect on them.
 and tells the Lisp compiler to perform inline expansion on it.
 @xref{Inline Functions}.
 
-  Alternatively, you can define a function by providing the code which
-will inline it as a compiler macro.  The following macros make this
-possible.
-
-@c FIXME: Can define-inline use the interactive spec?
-@defmac define-inline name args [doc] [declare] body@dots{}
-Define a function @var{name} by providing code that does its inlining,
-as a compiler macro.  The function will accept the argument list
-@var{args} and will have the specified @var{body}.
-
-If present, @var{doc} should be the function's documentation string
-(@pxref{Function Documentation}); @var{declare}, if present, should be
-a @code{declare} form (@pxref{Declare Form}) specifying the function's
-metadata.
-@end defmac
-
-Functions defined via @code{define-inline} have several advantages
-with respect to macros defined by @code{defsubst} or @code{defmacro}:
-
-@itemize @minus
-@item
-They can be passed to @code{mapcar} (@pxref{Mapping Functions}).
-
-@item
-They are more efficient.
-
-@item
-They can be used as @dfn{place forms} to store values
-(@pxref{Generalized Variables}).
-
-@item
-They behave in a more predictable way than @code{cl-defsubst}
-(@pxref{Argument Lists,,, cl, Common Lisp Extensions for GNU Emacs
-Lisp}).
-@end itemize
-
-Like @code{defmacro}, a function inlined with @code{define-inline}
-inherits the scoping rules, either dynamic or lexical, from the call
-site.  @xref{Variable Scoping}.
-
-The following macros should be used in the body of a function defined
-by @code{define-inline}.
-
-@defmac inline-quote expression
-Quote @var{expression} for @code{define-inline}.  This is similar to
-the backquote (@pxref{Backquote}), but quotes code and accepts only
-@code{,}, not @code{,@@}.
-@end defmac
-
-@defmac inline-letevals (bindings@dots{}) body@dots{}
-This is similar to @code{let} (@pxref{Local Variables}): it sets up
-local variables as specified by @var{bindings}, and then evaluates
-@var{body} with those bindings in effect.  Each element of
-@var{bindings} should be either a symbol or a list of the form
-@w{@code{(@var{var} @var{expr})}}; the result is to evaluate
-@var{expr} and bind @var{var} to the result.  The tail of
-@var{bindings} can be either @code{nil} or a symbol which should hold
-a list of arguments, in which case each argument is evaluated, and the
-symbol is bound to the resulting list.
-@end defmac
-
-@defmac inline-const-p expression
-Return non-@code{nil} if the value of @var{expression} is already
-known.
-@end defmac
-
-@defmac inline-const-val expression
-Return the value of @var{expression}.
-@end defmac
-
-@defmac inline-error format &rest args
-Signal an error, formatting @var{args} according to @var{format}.
-@end defmac
-
-Here's an example of using @code{define-inline}:
-
-@lisp
-(define-inline myaccessor (obj)
-  (inline-letevals (obj)
-    (inline-quote (if (foo-p ,obj) (aref (cdr ,obj) 3) (aref ,obj 2)))))
-@end lisp
-
-@noindent
-This is equivalent to
-
-@lisp
-(defsubst myaccessor (obj)
-  (if (foo-p obj) (aref (cdr obj) 3) (aref obj 2)))
-@end lisp
+  To undefine a function name, use @code{fmakunbound}.
+@xref{Function Cells}.
 
 @node Calling Functions
 @section Calling Functions
@@ -2155,8 +2069,12 @@ this:
   An @dfn{inline function} is a function that works just like an
 ordinary function, except for one thing: when you byte-compile a call
 to the function (@pxref{Byte Compilation}), the function's definition
-is expanded into the caller.  To define an inline function, use
-@code{defsubst} instead of @code{defun}.
+is expanded into the caller.
+
+  The simple way to define an inline function, is to write
+@code{defsubst} instead of @code{defun}.  The rest of the definition
+looks just the same, but using @code{defsubst} says to make it inline
+for byte compilation.
 
 @defmac defsubst name args [doc] [declare] [interactive] body@dots{}
 This macro defines an inline function.  Its syntax is exactly the same
@@ -2194,9 +2112,95 @@ argument of an inline function is evaluated exactly 
once, you needn't
 worry about how many times the body uses the arguments, as you do for
 macros.
 
-  As an alternative to @code{defsubst}, you can use
-@code{define-inline} to define functions via their exhaustive compiler
-macro.  @xref{Defining Functions, define-inline}.
+  Alternatively, you can define a function by providing the code which
+will inline it as a compiler macro.  The following macros make this
+possible.
+
+@c FIXME: Can define-inline use the interactive spec?
+@defmac define-inline name args [doc] [declare] body@dots{}
+Define a function @var{name} by providing code that does its inlining,
+as a compiler macro.  The function will accept the argument list
+@var{args} and will have the specified @var{body}.
+
+If present, @var{doc} should be the function's documentation string
+(@pxref{Function Documentation}); @var{declare}, if present, should be
+a @code{declare} form (@pxref{Declare Form}) specifying the function's
+metadata.
+@end defmac
+
+Functions defined via @code{define-inline} have several advantages
+with respect to macros defined by @code{defsubst} or @code{defmacro}:
+
+@itemize @minus
+@item
+They can be passed to @code{mapcar} (@pxref{Mapping Functions}).
+
+@item
+They are more efficient.
+
+@item
+They can be used as @dfn{place forms} to store values
+(@pxref{Generalized Variables}).
+
+@item
+They behave in a more predictable way than @code{cl-defsubst}
+(@pxref{Argument Lists,,, cl, Common Lisp Extensions for GNU Emacs
+Lisp}).
+@end itemize
+
+Like @code{defmacro}, a function inlined with @code{define-inline}
+inherits the scoping rules, either dynamic or lexical, from the call
+site.  @xref{Variable Scoping}.
+
+The following macros should be used in the body of a function defined
+by @code{define-inline}.
+
+@defmac inline-quote expression
+Quote @var{expression} for @code{define-inline}.  This is similar to
+the backquote (@pxref{Backquote}), but quotes code and accepts only
+@code{,}, not @code{,@@}.
+@end defmac
+
+@defmac inline-letevals (bindings@dots{}) body@dots{}
+This is similar to @code{let} (@pxref{Local Variables}): it sets up
+local variables as specified by @var{bindings}, and then evaluates
+@var{body} with those bindings in effect.  Each element of
+@var{bindings} should be either a symbol or a list of the form
+@w{@code{(@var{var} @var{expr})}}; the result is to evaluate
+@var{expr} and bind @var{var} to the result.  The tail of
+@var{bindings} can be either @code{nil} or a symbol which should hold
+a list of arguments, in which case each argument is evaluated, and the
+symbol is bound to the resulting list.
+@end defmac
+
+@defmac inline-const-p expression
+Return non-@code{nil} if the value of @var{expression} is already
+known.
+@end defmac
+
+@defmac inline-const-val expression
+Return the value of @var{expression}.
+@end defmac
+
+@defmac inline-error format &rest args
+Signal an error, formatting @var{args} according to @var{format}.
+@end defmac
+
+Here's an example of using @code{define-inline}:
+
+@lisp
+(define-inline myaccessor (obj)
+  (inline-letevals (obj)
+    (inline-quote (if (foo-p ,obj) (aref (cdr ,obj) 3) (aref ,obj 2)))))
+@end lisp
+
+@noindent
+This is equivalent to
+
+@lisp
+(defsubst myaccessor (obj)
+  (if (foo-p obj) (aref (cdr obj) 3) (aref obj 2)))
+@end lisp
 
 @node Declare Form
 @section The @code{declare} Form
diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi
index d95a3e4..442f6d1 100644
--- a/doc/lispref/internals.texi
+++ b/doc/lispref/internals.texi
@@ -1416,7 +1416,7 @@ other words, if a module function wants to call Lisp 
functions or
 Emacs primitives, convert @code{emacs_value} objects to and from C
 datatypes (@pxref{Module Values}), or interact with Emacs in any other
 way, some call from Emacs to @code{emacs_module_init} or to a module
-function must be in the callstack.  Module function may not interact
+function must be in the call stack.  Module function may not interact
 with Emacs while garbage collection is running; @pxref{Garbage
 Collection}.  They may only interact with Emacs from Lisp interpreter
 threads (including the main thread) created by Emacs; @pxref{Threads}.
@@ -1447,6 +1447,54 @@ The Lisp package which goes with your module could then 
load the
 module using the @code{load} primitive (@pxref{Dynamic Modules}) when
 the package is loaded into Emacs.
 
+@anchor{Module Function Finalizers}
+If you want to run some code when a module function object (i.e., an
+object returned by @code{make_function}) is garbage-collected, you can
+install a @dfn{function finalizer}.  Function finalizers are available
+since Emacs 28.  For example, if you have passed some heap-allocated
+structure to the @var{data} argument of @code{make_function}, you can
+use the finalizer to deallocate the structure.  @xref{Basic
+Allocation,,,libc}, and @pxref{Freeing after Malloc,,,libc}.  The
+finalizer function has the following signature:
+
+@example
+void finalizer (void *@var{data})
+@end example
+
+Here, @var{data} receives the value passed to @var{data} when calling
+@code{make_function}.  Note that the finalizer can't interact with
+Emacs in any way.
+
+Directly after calling @code{make_function}, the newly-created
+function doesn't have a finalizer.  Use @code{set_function_finalizer}
+to add one, if desired.
+
+@deftypefun void emacs_finalizer (void *@var{ptr})
+The header @file{emacs-module.h} provides the type
+@code{emacs_finalizer} as a type alias for an Emacs finalizer
+function.
+@end deftypefun
+
+@deftypefun emacs_finalizer get_function_finalizer (emacs_env *@var{env}, 
emacs_value @var{arg})
+This function, which is available since Emacs 28, returns the function
+finalizer associated with the module function represented by
+@var{arg}.  @var{arg} must refer to a module function, that is, an
+object returned by @code{make_function}.  If no finalizer is
+associated with the function, @code{NULL} is returned.
+@end deftypefun
+
+@deftypefun void set_function_finalizer (emacs_env *@var{env}, emacs_value 
@var{arg}, emacs_finalizer @var{fin})
+This function, which is available since Emacs 28, sets the function
+finalizer associated with the module function represented by @var{arg}
+to @var{fin}.  @var{arg} must refer to a module function, that is, an
+object returned by @code{make_function}.  @var{fin} can either be
+@code{NULL} to clear @var{arg}'s function finalizer, or a pointer to a
+function to be called when the object represented by @var{arg} is
+garbage-collected.  At most one function finalizer can be set per
+function; if @var{arg} already has a finalizer, it is replaced by
+@var{fin}.
+@end deftypefun
+
 @node Module Values
 @subsection Conversion Between Lisp and Module Values
 @cindex module values, conversion
@@ -1865,11 +1913,8 @@ represented by @var{arg} to be @var{fin}.  If @var{fin} 
is a
 finalizer.
 @end deftypefn
 
-@deftypefun void emacs_finalizer (void *@var{ptr})
-The header @file{emacs-module.h} provides the type
-@code{emacs_finalizer} as a type alias for an Emacs finalizer
-function.
-@end deftypefun
+Note that the @code{emacs_finalizer} type works for both user pointer
+an module function finalizers.  @xref{Module Function Finalizers}.
 
 @node Module Misc
 @subsection Miscellaneous Convenience Functions for Modules
diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi
index 259efea..4d51313 100644
--- a/doc/lispref/keymaps.texi
+++ b/doc/lispref/keymaps.texi
@@ -1846,8 +1846,11 @@ local map.
 @cindex scanning keymaps
 @cindex keymaps, scanning
 
-  This section describes functions used to scan all the current keymaps
-for the sake of printing help information.
+  This section describes functions used to scan all the current
+keymaps for the sake of printing help information.  To display the
+bindings in a particular keymap, you can use the
+@code{describe-keymap} command (@pxref{Misc Help, , Other Help
+Commands, emacs, The GNU Emacs Manual})
 
 @defun accessible-keymaps keymap &optional prefix
 This function returns a list of all the keymaps that can be reached (via
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 7354eb1..f380f16 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -135,13 +135,26 @@ non-@code{nil} value, it returns that value; otherwise it 
returns
 @node Setting Hooks
 @subsection Setting Hooks
 
-  Here's an example that uses a mode hook to turn on Auto Fill mode when
-in Lisp Interaction mode:
+  Here's an example that adds a function to a mode hook to turn
+on Auto Fill mode when in Lisp Interaction mode:
 
 @example
 (add-hook 'lisp-interaction-mode-hook 'auto-fill-mode)
 @end example
 
+  The value of a hook variable should be a list of functions.  You can
+manipulate that list using the normal Lisp facilities, but the modular
+way is to use the functions @code{add-hook} and @code{remove-hook},
+defined below.  They take care to handle some unusual situations and
+avoid problems.
+
+  It works to put a @code{lambda}-expression function on a hook, but
+we recommend avoiding this because it can lead to confusion.  If you
+add the same @code{lambda}-expression a second time but write it
+slightly differently, you will get two equivalent but distinct
+functions on the hook.  If you then remove one of them, the other will
+still be on it.
+
 @defun add-hook hook function &optional depth local
 This function is the handy way to add function @var{function} to hook
 variable @var{hook}.  You can use it for abnormal hooks as well as for
@@ -2660,6 +2673,7 @@ Setting this variable makes it buffer-local in the 
current buffer.
 @node Font Lock Mode
 @section Font Lock Mode
 @cindex Font Lock mode
+@cindex syntax highlighting and coloring
 
   @dfn{Font Lock mode} is a buffer-local minor mode that automatically
 attaches @code{face} properties to certain parts of the buffer based on
diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi
index e952980..c8941ea 100644
--- a/doc/lispref/numbers.texi
+++ b/doc/lispref/numbers.texi
@@ -39,8 +39,8 @@ numbers have a fixed amount of precision.
   Under the hood, though, there are two kinds of integers: smaller
 ones, called @dfn{fixnums}, and larger ones, called @dfn{bignums}.
 Some functions in Emacs accept only fixnums.  Also, while fixnums can
-always be compared for numeric equality with @code{eq}, bignums
-require more-heavyweight equality predicates like @code{eql}.
+be compared for numeric equality with @code{eq}, bignums require
+more-heavyweight equality predicates like @code{eql} and @code{=}.
 
   The range of values for bignums is limited by the amount of main
 memory, by machine characteristics such as the size of the word used
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 4be2eb6..855dff2 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -266,8 +266,8 @@ but many machines provide a wider range.
   Bignums can have arbitrary precision.  Operations that overflow a
 fixnum will return a bignum instead.
 
-  Fixnums can be compared with @code{eq}, but bignums require
-@code{eql} or @code{=}.  To test whether an integer is a fixnum or a
+  All numbers can be compared with @code{eql} or @code{=}; fixnums can
+also be compared with @code{eq}.  To test whether an integer is a fixnum or a
 bignum, you can compare it to @code{most-negative-fixnum} and
 @code{most-positive-fixnum}, or you can use the convenience predicates
 @code{fixnump} and @code{bignump} on any object.
@@ -2167,17 +2167,20 @@ appropriate chapter describing the data type.
 This function returns @code{t} if @var{object1} and @var{object2} are
 the same object, and @code{nil} otherwise.
 
-If @var{object1} and @var{object2} are fixnums with the same value,
-they are considered to be the same object (i.e., @code{eq} returns
-@code{t}).  If @var{object1} and @var{object2} are symbols with the
+If @var{object1} and @var{object2} are symbols with the
 same name, they are normally the same object---but see @ref{Creating
-Symbols} for exceptions.  For other types (e.g., lists, vectors,
+Symbols} for exceptions.  For other non-numeric types (e.g., lists, vectors,
 strings), two arguments with the same contents or elements are not
 necessarily @code{eq} to each other: they are @code{eq} only if they
 are the same object, meaning that a change in the contents of one will
 be reflected by the same change in the contents of the other.
-For other types of objects whose contents cannot be changed (e.g.,
-bignums and floats), two arguments with the same contents might or might not be
+
+If @var{object1} and @var{object2} are numbers with differing types or values,
+then they cannot be the same object and @code{eq} returns @code{nil}.
+If they are fixnums with the same value,
+then they are the same object and @code{eq} returns @code{t}.
+If they were computed separately but happen to have the same value
+and the same non-fixnum numeric type, then they might or might not be
 the same object, and @code{eq} returns @code{t} or @code{nil}
 depending on whether the Lisp interpreter created one object or two.
 
@@ -2188,26 +2191,25 @@ depending on whether the Lisp interpreter created one 
object or two.
 @end group
 
 @group
-(eq 456 456)
+(eq ?A ?A)
      @result{} t
 @end group
 
 @group
 (eq 3.0 3.0)
      @result{} t @r{or} nil
-;; @r{The result is implementation-dependent.}
+;; @r{Equal floats may or may not be the same object.}
 @end group
 
 @group
-(eq "asdf" "asdf")
+(eq (make-string 3 ?A) (make-string 3 ?A))
      @result{} nil
 @end group
 
 @group
-(eq "" "")
-     @result{} t
-;; @r{This exception occurs because Emacs Lisp}
-;; @r{makes just one multibyte empty string, to save space.}
+(eq "asdf" "asdf")
+     @result{} t @r{or} nil
+;; @r{Equal string constants or may not be the same object.}
 @end group
 
 @group
@@ -2336,8 +2338,12 @@ same sequence of character codes and all these codes are 
in the range
 @end group
 @end example
 
-However, two distinct buffers are never considered @code{equal}, even if
-their textual contents are the same.
+The @code{equal} function recursively compares the contents of objects
+if they are integers, strings, markers, vectors, bool-vectors,
+byte-code function objects, char-tables, records, or font objects.
+Other objects are considered @code{equal} only if they are @code{eq}.
+For example, two distinct buffers are never considered @code{equal},
+even if their textual contents are the same.
 @end defun
 
   For @code{equal}, equality is defined recursively; for example, given
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index 201ca18..a034ccd 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1689,7 +1689,8 @@ following form:
 @noindent
 The format of this list is the same as what @code{decode-time} accepts
 (@pxref{Time Conversion}), and is described in more detail there.  Any
-element that cannot be determined from the input will be set to
+@code{dst} element that cannot be determined from the input is set to
+@minus{}1, and any other unknown element is set to
 @code{nil}.  The argument @var{string} should resemble an RFC 822 (or later) or
 ISO 8601 string, like ``Fri, 25 Mar 2016 16:24:56 +0100'' or
 ``1998-09-12T12:21:54-0200'', but this function will attempt to parse
diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index 6970f71..f515213 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -2426,18 +2426,15 @@ server is stopped; a non-@code{nil} value means yes.
 @cindex encrypted network connections
 @cindex @acronym{TLS} network connections
 @cindex @acronym{STARTTLS} network connections
-Emacs can create encrypted network connections, using either built-in
-or external support.  The built-in support uses the GnuTLS
-Transport Layer Security Library; see
+Emacs can create encrypted network connections, using the built-in
+support for the GnuTLS Transport Layer Security Library; see
 @uref{https://www.gnu.org/software/gnutls/, the GnuTLS project page}.
 If your Emacs was compiled with GnuTLS support, the function
 @code{gnutls-available-p} is defined and returns non-@code{nil}.  For
 more details, @pxref{Top,, Overview, emacs-gnutls, The Emacs-GnuTLS manual}.
-The external support uses the @file{starttls.el} library, which
-requires a helper utility such as @command{gnutls-cli} to be installed
-on the system.  The @code{open-network-stream} function can
-transparently handle the details of creating encrypted connections for
-you, using whatever support is available.
+The @code{open-network-stream} function can transparently handle the
+details of creating encrypted connections for you, using whatever
+support is available.
 
 @defun open-network-stream name buffer host service &rest parameters
 This function opens a TCP connection, with optional encryption, and
diff --git a/doc/lispref/streams.texi b/doc/lispref/streams.texi
index 6d0b4b0..d40ec8d 100644
--- a/doc/lispref/streams.texi
+++ b/doc/lispref/streams.texi
@@ -716,6 +716,7 @@ For example, if the current buffer name is @samp{foo},
 returns @code{"The buffer is foo"}.
 @end defmac
 
+@cindex pretty-printer
 @defun pp object &optional stream
 This function outputs @var{object} to @var{stream}, just like
 @code{prin1}, but does it in a prettier way.  That is, it'll
diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi
index 4395069..0610f80 100644
--- a/doc/lispref/tips.texi
+++ b/doc/lispref/tips.texi
@@ -803,18 +803,6 @@ starting the sentence with lower-case ``t'', which could 
be somewhat
 distracting.
 
 @item
-If a line in a documentation string begins with an open-parenthesis,
-write a backslash before the open-parenthesis, like this:
-
-@example
-The argument FOO can be either a number
-\(a buffer position) or a string (a file name).
-@end example
-
-This prevents the open-parenthesis from being treated as the start of a
-defun (@pxref{Defuns,, Defuns, emacs, The GNU Emacs Manual}).
-
-@item
 Write documentation strings in the active voice, not the passive, and in
 the present tense, not the future.  For instance, use ``Return a list
 containing A and B.@:'' instead of ``A list containing A and B will be
@@ -849,6 +837,21 @@ The documentation string for a variable that is a 
yes-or-no flag should
 start with words such as ``Non-nil means'', to make it clear that
 all non-@code{nil} values are equivalent and indicate explicitly what
 @code{nil} and non-@code{nil} mean.
+
+@item
+If a line in a documentation string begins with an open-parenthesis,
+consider writing a backslash before the open-parenthesis, like this:
+
+@example
+The argument FOO can be either a number
+\(a buffer position) or a string (a file name).
+@end example
+
+This avoids a bug in Emacs versions older than 27.1, where the
+@samp{(} was treated as the start of a defun
+(@pxref{Defuns,, Defuns, emacs, The GNU Emacs Manual}).
+If you do not anticipate anyone editing your code with older Emacs
+versions, there is no need for this work-around.
 @end itemize
 
 @node Comment Tips
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index 1ec97e2..1e35775 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -1187,6 +1187,9 @@ When evaluating Emacs Lisp code directly using an 
@code{eval} call,
 lexical binding is enabled if the @var{lexical} argument to
 @code{eval} is non-@code{nil}.  @xref{Eval}.
 
+Lexical binding is also enabled in Lisp Interaction and IELM
+mode, used in the @file{*scratch*} and @file{*ielm*} buffers.
+
 @cindex special variables
   Even when lexical binding is enabled, certain variables will
 continue to be dynamically bound.  These are called @dfn{special
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index c9301c9..d0791d4 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -5915,10 +5915,6 @@ This function compares two window configurations as 
regards the
 structure of windows, but ignores the values of point and the
 saved scrolling positions---it can return @code{t} even if those
 aspects differ.
-
-The function @code{equal} can also compare two window configurations; it
-regards configurations as unequal if they differ in any respect, even a
-saved point.
 @end defun
 
 @defun window-configuration-frame config
diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in
index 0a26a26..7f536ad 100644
--- a/doc/misc/Makefile.in
+++ b/doc/misc/Makefile.in
@@ -267,7 +267,7 @@ install-ps: ps
          ${GZIP_PROG} -9n "$(DESTDIR)$(psdir)/$${file}"; \
        done
 
-## Top-level Makefile installs the info pages.
+## Top-level Makefile installs the Info manuals.
 install-doc: install-dvi install-html install-pdf install-ps
 
 
diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi
index a89a92d..a31f232 100644
--- a/doc/misc/calc.texi
+++ b/doc/misc/calc.texi
@@ -35164,16 +35164,7 @@ which are called at various times.  Calc defines a 
number of hooks
 that help you to customize it in various ways.  Calc uses the Lisp
 function @code{run-hooks} to invoke the hooks shown below.  Several
 other customization-related variables are also described here.
-
-@defvar calc-load-hook
-This hook is called at the end of @file{calc.el}, after the file has
-been loaded, before any functions in it have been called, but after
-@code{calc-mode-map} and similar variables have been set up.
-@end defvar
-
-@defvar calc-ext-load-hook
-This hook is called at the end of @file{calc-ext.el}.
-@end defvar
+To run code after Calc has loaded, use @code{with-eval-after-load}.
 
 @defvar calc-start-hook
 This hook is called as the last step in a @kbd{M-x calc} command.
diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi
index 2c49a90..544ff85 100644
--- a/doc/misc/cc-mode.texi
+++ b/doc/misc/cc-mode.texi
@@ -7095,22 +7095,24 @@ constitute noise macros.
 @vindex noise-macro-names @r{(c-)}
 This variable is a list of names of noise macros which never have
 parenthesized arguments.  Each element is a string, and must be a
-valid identifier.  An element in @code{c-noise-macro-names} must not
-also be in @code{c-noise-macro-with-parens-names}.  Such an element is
-treated as whitespace by @ccmode{}.
+valid identifier.  Alternatively, the variable may be a regular
+expression which matches the names of such macros.  Such a noise macro
+is treated as whitespace by @ccmode{}.  It must not also be in, or be
+matched by @code{c-noise-macro-with-parens-names}.
 @end defopt
 
 @defopt c-noise-macro-with-parens-names
 @vindex noise-macro-with-parens-names @r{(c-)}
 This variable is a list of names of noise macros which optionally have
 arguments in parentheses.  Each element of the list is a string, and
-must be a valid identifier.  An element in
-@code{c-noise-macro-with-parens-names} must not also be in
-@code{c-noise-macro-names}.  For performance reasons, such an element,
-together with the optional parenthesized arguments, is specially
-handled, but it is only handled when used in declaration
-contexts@footnote{If this restriction causes your project
-difficulties, please get in touch with @email{bug-cc-mode@@gnu.org}.}.
+must be a valid identifier.  Alternatively, the variable may be a
+regular expression which matches the names of such macros.  Such a
+noise macro must not also be in, or be matched by
+@code{c-noise-macro-names}.  For performance reasons, such a noise
+macro, including any parenthesized arguments, is specially handled,
+but it is only handled when used in declaration contexts@footnote{If
+this restriction causes your project difficulties, please get in touch
+with @email{bug-cc-mode@@gnu.org}.}.
 
 The two compiler directives @code{__attribute__} and @code{__declspec}
 have traditionally been handled specially in @ccmode{}; for example
diff --git a/doc/misc/dired-x.texi b/doc/misc/dired-x.texi
index 5965da1..d749780 100644
--- a/doc/misc/dired-x.texi
+++ b/doc/misc/dired-x.texi
@@ -185,13 +185,12 @@ In your @file{~/.emacs} file, or in the system-wide 
initialization file
 @file{default.el} in the @file{site-lisp} directory, put
 
 @example
-(add-hook 'dired-load-hook
-          (lambda ()
-            (load "dired-x")
-            ;; Set dired-x global variables here.  For example:
-            ;; (setq dired-guess-shell-gnutar "gtar")
-            ;; (setq dired-x-hands-off-my-keys nil)
-            ))
+(with-eval-after-load 'dired
+  (require 'dired-x)
+  ;; Set dired-x global variables here.  For example:
+  ;; (setq dired-guess-shell-gnutar "gtar")
+  ;; (setq dired-x-hands-off-my-keys nil)
+  ))
 (add-hook 'dired-mode-hook
           (lambda ()
             ;; Set dired-x buffer-local variables here.  For example:
@@ -242,12 +241,10 @@ If you choose to have @file{dired-x.el} bind 
@code{dired-x-find-file} over
 or call @code{dired-x-bind-find-file} after changing the value.
 
 @example
-(add-hook 'dired-load-hook
-          (lambda ()
-            ;; Bind dired-x-find-file.
-            (setq dired-x-hands-off-my-keys nil)
-            (load "dired-x")
-            ))
+(with-eval-after-load 'dired
+  ;; Bind dired-x-find-file.
+  (setq dired-x-hands-off-my-keys nil)
+  (require 'dired-x))
 @end example
 
 @node Omitting Files in Dired
@@ -294,8 +291,8 @@ Marked files are never omitted.
 @end table
 
 @noindent
-In order to make Dired Omit work you first need to load @file{dired-x.el}
-inside @code{dired-load-hook} (@pxref{Installation}) and then evaluate
+In order to make Dired Omit work you need to load @file{dired-x}
+after loading @file{dired} (@pxref{Installation}) and then evaluate
 @code{(dired-omit-mode 1)} in some way (@pxref{Omitting Variables}).
 
 @ifnottex
@@ -410,7 +407,7 @@ The default value is @kbd{C-o}.
 @item
 @cindex RCS files, how to omit them in Dired
 @cindex omitting RCS files in Dired
-If you wish to avoid seeing RCS files and the @file{RCS} directory, then put
+If you wish to avoid seeing RCS files and the @file{RCS} directory, then use
 
 @example
 (setq dired-omit-files
@@ -418,7 +415,7 @@ If you wish to avoid seeing RCS files and the @file{RCS} 
directory, then put
 @end example
 
 @noindent
-in the @code{dired-load-hook} (@pxref{Installation}).  This assumes
+after loading @file{dired-x} (@pxref{Installation}).  This assumes
 @code{dired-omit-localp} has its default value of @code{no-dir} to make the
 @code{^}-anchored matches work.  As a slower alternative, with
 @code{dired-omit-localp} set to @code{nil}, you can use @code{/} instead of
@@ -429,7 +426,7 @@ in the @code{dired-load-hook} (@pxref{Installation}).  This 
assumes
 @cindex omitting tib files in Dired
 If you use @code{tib}, the bibliography program for use with @TeX{} and
 @LaTeX{}, and you
-want to omit the @file{INDEX} and the @file{*-t.tex} files, then put
+want to omit the @file{INDEX} and the @file{*-t.tex} files, then use
 
 @example
 (setq dired-omit-files
@@ -437,13 +434,13 @@ want to omit the @file{INDEX} and the @file{*-t.tex} 
files, then put
 @end example
 
 @noindent
-in the @code{dired-load-hook} (@pxref{Installation}).
+after loading @file{dired-x} (@pxref{Installation}).
 
 @item
 @cindex dot files, how to omit them in Dired
 @cindex omitting dot files in Dired
 If you do not wish to see @samp{dot} files (files starting with a @file{.}),
-then put
+then use
 
 @example
 (setq dired-omit-files
@@ -451,7 +448,7 @@ then put
 @end example
 
 @noindent
-in the @code{dired-load-hook} (@pxref{Installation}).  (Of course, a
+after loading @file{dired-x} (@pxref{Installation}).  (Of course, a
 better way to achieve this particular goal is simply to omit @samp{-a} from
 @code{dired-listing-switches}.)
 
@@ -830,7 +827,7 @@ When installed @file{dired-x} will substitute 
@code{dired-x-find-file} for
 (normally bound to @kbd{C-x 4 C-f}).
 
 In order to use this feature, you will need to set
-@code{dired-x-hands-off-my-keys} to @code{nil} inside @code{dired-load-hook}
+@code{dired-x-hands-off-my-keys} to @code{nil} before loading @file{dired-x}
 (@pxref{Optional Installation File At Point}).
 
 @table @code
diff --git a/doc/misc/ediff.texi b/doc/misc/ediff.texi
index 99ba89b..1ef1371 100644
--- a/doc/misc/ediff.texi
+++ b/doc/misc/ediff.texi
@@ -1197,10 +1197,6 @@ refer to Emacs manual for the information on how to set 
Emacs X resources.
 The bulk of customization can be done via the following hooks:
 
 @table @code
-@item ediff-load-hook
-@vindex ediff-load-hook
-This hook can be used to change defaults after Ediff is loaded.
-
 @item ediff-before-setup-hook
 @vindex ediff-before-setup-hook
 Hook that is run just before Ediff rearranges windows to its liking.
@@ -1211,8 +1207,8 @@ Can be used to save windows configuration.
 @vindex ediff-mode-map
 This hook can be used to alter bindings in Ediff's keymap,
 @code{ediff-mode-map}.  These hooks are
-run right after the default bindings are set but before
-@code{ediff-load-hook}.  The regular user needs not be concerned with this
+run right after the default bindings are set.
+The regular user needs not be concerned with this
 hook---it is provided for implementers of other Emacs packages built on top
 of Ediff.
 
@@ -1545,12 +1541,13 @@ directly (using @kbd{j})  to any numbered
 difference.
 
 Users can supply their own functions to specify how Ediff should do
-selective browsing.  To change the default Ediff function, add a function to
-@code{ediff-load-hook} which will do the following assignments:
+selective browsing.  To change the default Ediff function, use
+something like the following:
 
 @example
-(setq ediff-hide-regexp-matches-function 'your-hide-function)
-(setq ediff-focus-on-regexp-matches-function 'your-focus-function)
+(with-eval-after-load 'ediff
+  (setq ediff-hide-regexp-matches-function 'your-hide-function)
+  (setq ediff-focus-on-regexp-matches-function 'your-focus-function))
 @end example
 
 @strong{Useful hint}: To specify a regexp that matches everything, don't
@@ -1728,23 +1725,17 @@ difference region in buffer A (this face is not a good 
choice, by the way).
 
 If you are unhappy with just @emph{some} of the aspects of the default
 faces, you can modify them when Ediff is being loaded using
-@code{ediff-load-hook}.  For instance:
+@code{with-eval-after-load}.  For instance:
 
 @smallexample
-(add-hook 'ediff-load-hook
-          (lambda ()
-            (set-face-foreground
-              ediff-current-diff-face-B "blue")
-            (set-face-background
-              ediff-current-diff-face-B "red")
-            (make-face-italic
-              ediff-current-diff-face-B)))
+(with-eval-after-load 'ediff
+  (set-face-foreground
+    ediff-current-diff-face-B "blue")
+  (set-face-background
+    ediff-current-diff-face-B "red")
+  (make-face-italic ediff-current-diff-face-B))
 @end smallexample
 
-@strong{Please note:} to set Ediff's faces, use only @code{copy-face}
-or @code{set/make-face-@dots{}} as shown above. Emacs's low-level
-face-manipulation functions should be avoided.
-
 @node Narrowing
 @section Narrowing
 
diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi
index dcb0a68..50a208d 100644
--- a/doc/misc/efaq.texi
+++ b/doc/misc/efaq.texi
@@ -1440,7 +1440,6 @@ of files from Macintosh, Microsoft, and Unix platforms.
 * Compiler error messages::
 * Indenting switch statements::
 * Customizing C and C++ indentation::
-* Horizontal scrolling::
 * Overwrite mode::
 * Turning off beeping::
 * Turning the volume down::
@@ -2123,23 +2122,6 @@ Java sources, etc.  If you want the same customizations 
to be in
 effect in @emph{all} languages supported by @code{cc-mode}, use
 @code{c-mode-common-hook}.
 
-@node Horizontal scrolling
-@section How can I make Emacs automatically scroll horizontally?
-@cindex @code{hscroll-mode}
-@cindex Horizontal scrolling
-@cindex Scrolling horizontally
-
-In Emacs 21 and later, this is on by default: if the variable
-@code{truncate-lines} is non-@code{nil} in the current buffer, Emacs
-automatically scrolls the display horizontally when point moves off the
-left or right edge of the window.
-
-Note that this is overridden by the variable
-@code{truncate-partial-width-windows} if that variable is non-@code{nil}
-and the current buffer is not full-frame width.
-
-In Emacs 20, use @code{hscroll-mode}.
-
 @node Overwrite mode
 @section How do I make Emacs ``typeover'' or ``overwrite'' instead of 
inserting?
 @cindex @key{Insert}
@@ -2305,9 +2287,9 @@ to investigate @file{cpp.el}, which is distributed with 
Emacs.
 @cindex Commands, repeating many times
 @cindex @code{.}, equivalent to @code{vi} command
 
-As of Emacs 20.3, there is indeed a @code{repeat} command (@kbd{C-x z})
-that repeats the last command.  If you preface it with a prefix
-argument, the prefix arg is applied to the command.
+Use the @code{repeat} command (@kbd{C-x z}) to repeat the last
+command.  If you preface it with a prefix argument, the prefix arg is
+applied to the command.
 
 You can also type @kbd{C-x @key{ESC} @key{ESC}}
 (@code{repeat-complex-command}) to reinvoke commands that used the
@@ -2533,9 +2515,8 @@ To avoid seeing backup files (and other ``uninteresting'' 
files) in Dired,
 load @code{dired-x} by adding the following to your @file{.emacs} file:
 
 @lisp
-(add-hook 'dired-load-hook
-          (lambda ()
-           (require 'dired-x)))
+(with-eval-after-load 'dired
+  (require 'dired-x))
 @end lisp
 
 With @code{dired-x} loaded, @kbd{M-o} toggles omitting in each dired buffer.
@@ -2821,9 +2802,9 @@ Alternatively, use the following Lisp form in your 
@file{.emacs}:
 @cindex Microsoft files, editing
 @cindex Windows files, editing
 
-As of Emacs 20, detection and handling of MS-DOS (and Windows) files is
-performed transparently.  You can open MS-DOS files on a Unix system,
-edit it, and save it without having to worry about the file format.
+Detection and handling of MS-DOS (and Windows) files is performed
+transparently.  You can open MS-DOS files on a Unix system, edit it,
+and save it without having to worry about the file format.
 
 When editing an MS-DOS style file, the mode line will indicate that it
 is a DOS file.  On Unix and GNU/Linux systems, and also on a Macintosh,
@@ -3087,8 +3068,8 @@ begun}.
 @cindex Ignored X resources
 @cindex @file{.Xdefaults}
 
-As of version 19, Emacs searches for X resources in the files specified
-by the following environment variables:
+Emacs searches for X resources in the files specified by the following
+environment variables:
 
 @itemize @bullet
 
diff --git a/doc/misc/gnus-coding.texi b/doc/misc/gnus-coding.texi
index 55320bf..9a14a95 100644
--- a/doc/misc/gnus-coding.texi
+++ b/doc/misc/gnus-coding.texi
@@ -96,16 +96,6 @@ Read passwords from user, possibly using a password cache.
 @c As of 2005-10-21...
 There are no Gnus dependencies in this file.
 
-@item tls.el
-TLS/SSL support via wrapper around GnuTLS
-@c As of 2005-10-21...
-There are no Gnus dependencies in this file.
-
-@item pgg*.el
-Glue for the various PGP implementations.
-@c As of 2005-10-21...
-There are no Gnus dependencies in these files.
-
 @item sha1.el
 SHA1 Secure Hash Algorithm.
 @c As of 2007-08-25...
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 83641fe..2545d21 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -1563,12 +1563,6 @@ secondary select methods.
 
 @table @code
 
-@item gnus-load-hook
-@vindex gnus-load-hook
-A hook run while Gnus is being loaded.  Note that this hook will
-normally be run just once in each Emacs session, no matter how many
-times you start Gnus.
-
 @item gnus-before-startup-hook
 @vindex gnus-before-startup-hook
 A hook called as the first thing when Gnus is started.
@@ -27910,7 +27904,7 @@ The revised Gnus @acronym{FAQ} is included in the 
manual,
 @acronym{TLS} wrapper shipped with Gnus
 
 @acronym{TLS}/@acronym{SSL} is now supported in @acronym{IMAP} and
-@acronym{NNTP} via @file{tls.el} and GnuTLS.
+@acronym{NNTP} via GnuTLS.
 
 @item
 Improved anti-spam features.
diff --git a/doc/misc/idlwave.texi b/doc/misc/idlwave.texi
index 547b166..5cb6b19 100644
--- a/doc/misc/idlwave.texi
+++ b/doc/misc/idlwave.texi
@@ -1805,8 +1805,8 @@ Structure tag completion is not enabled by default.  To 
enable it,
 simply add the following to your @file{.emacs}:
 
 @lisp
-   (add-hook 'idlwave-load-hook
-             (lambda () (require 'idlw-complete-structtag)))
+(with-eval-after-load 'idlwave
+  (require 'idlw-complete-structtag))
 @end lisp
 
 Once enabled, you'll also be able to access online help on the structure
@@ -2360,10 +2360,6 @@ is first called.
 Normal hook.  Executed when a buffer is put into @code{idlwave-mode}.
 @end defopt
 
-@defopt idlwave-load-hook
-Normal hook.  Executed when @file{idlwave.el} is loaded.
-@end defopt
-
 @node The IDLWAVE Shell
 @chapter The IDLWAVE Shell
 @cindex IDLWAVE shell
diff --git a/doc/misc/ido.texi b/doc/misc/ido.texi
index 74d0bdd..7cc4edd 100644
--- a/doc/misc/ido.texi
+++ b/doc/misc/ido.texi
@@ -590,7 +590,7 @@ Now you can customize @code{completion-ignored-extensions} 
as well.
 Go ahead and add all the useless object files, backup files, shared
 library files and other computing flotsam you don't want Ido to show.
 
-@strong{Note:} Ido will still complete the ignored elements
+@strong{Please note:} Ido will still complete the ignored elements
 if it would otherwise not show any other matches.  So if you type out
 the name of an ignored file, Ido will still let you open it just fine.
 
diff --git a/doc/misc/org.texi b/doc/misc/org.texi
index 0de91fa..8979796 100644
--- a/doc/misc/org.texi
+++ b/doc/misc/org.texi
@@ -3979,10 +3979,9 @@ key bindings for this are really too long; you might 
want to bind
 this also to @kbd{M-n} and @kbd{M-p}.
 
 @lisp
-(add-hook 'org-load-hook
-          (lambda ()
-            (define-key org-mode-map "\M-n" 'org-next-link)
-            (define-key org-mode-map "\M-p" 'org-previous-link)))
+(with-eval-after-load 'org
+  (define-key org-mode-map "\M-n" 'org-next-link)
+  (define-key org-mode-map "\M-p" 'org-previous-link))
 @end lisp
 @end table
 
diff --git a/doc/misc/reftex.texi b/doc/misc/reftex.texi
index 013c563..0dab524 100644
--- a/doc/misc/reftex.texi
+++ b/doc/misc/reftex.texi
@@ -2896,9 +2896,8 @@ default.  If you want to have these key bindings 
available, set in your
 Note that this variable has to be set before @RefTeX{} is loaded to
 have an effect.
 
-@vindex reftex-load-hook
-Changing and adding to @RefTeX{}'s key bindings is best done in the hook
-@code{reftex-load-hook}.  For information on the keymaps
+Changing and adding to @RefTeX{}'s key bindings is best done using
+@code{with-eval-after-load}.  For information on the keymaps
 which should be used to add keys, see @ref{Keymaps and Hooks}.
 
 @node Faces
@@ -5320,10 +5319,6 @@ argument.
 The keymap for @RefTeX{} mode.
 @end deffn
 
-@deffn {Normal Hook} reftex-load-hook
-Normal hook which is being run when loading @file{reftex.el}.
-@end deffn
-
 @deffn {Normal Hook} reftex-mode-hook
 Normal hook which is being run when turning on @RefTeX{} mode.
 @end deffn
diff --git a/doc/misc/sem-user.texi b/doc/misc/sem-user.texi
index c02887d..d151cee 100644
--- a/doc/misc/sem-user.texi
+++ b/doc/misc/sem-user.texi
@@ -1068,7 +1068,7 @@ You can integrate @semantic{} with the Speedbar.
 line to your init file:
 
 @example
-(add-hook 'speedbar-load-hook (lambda () (require 'semantic/sb)))
+(with-eval-after-load 'speedbar (require 'semantic/sb))
 @end example
 
 @noindent
diff --git a/doc/misc/smtpmail.texi b/doc/misc/smtpmail.texi
index 99612d5..f29a5a8 100644
--- a/doc/misc/smtpmail.texi
+++ b/doc/misc/smtpmail.texi
@@ -295,26 +295,11 @@ encrypted connection if the server supports it.  Other 
possible values
 are: @code{starttls} to insist on STARTTLS; @code{ssl} to use TLS/SSL;
 and @code{plain} for no encryption.
 
-Use of any form of TLS/SSL requires support in Emacs.  You can either
-use the built-in support (in Emacs 24.1 and later), or the
-@file{starttls.el} Lisp library.  The built-in support uses the GnuTLS
-@footnote{@url{https://www.gnu.org/software/gnutls/}} library.
-If your Emacs has GnuTLS support built-in, the function
+Use of any form of TLS/SSL requires support in Emacs.  You can use the
+built-in support for the GnuTLS
+@footnote{@url{https://www.gnu.org/software/gnutls/}} library.  If your
+Emacs has GnuTLS support built-in, the function
 @code{gnutls-available-p} is defined and returns non-@code{nil}.
-Otherwise, you must use the @file{starttls.el} library (see that file for
-more information on customization options, etc.).  The Lisp library
-requires one of the following external tools to be installed:
-
-@enumerate
-@item
-The GnuTLS command line tool @samp{gnutls-cli}, which you can get from
-@url{https://www.gnu.org/software/gnutls/}.  This is the recommended
-tool, mainly because it can verify server certificates.
-
-@item
-The @samp{starttls} external program, which you can get from
-@file{starttls-*.tar.gz} from @uref{ftp://ftp.opaopa.org/pub/elisp/}.
-@end enumerate
 
 @cindex certificates
 @cindex keys
diff --git a/doc/misc/speedbar.texi b/doc/misc/speedbar.texi
index 57ad022..c9c3daf 100644
--- a/doc/misc/speedbar.texi
+++ b/doc/misc/speedbar.texi
@@ -828,9 +828,6 @@ Hooks run when speedbar visits a file in the selected frame.
 @cindex @code{speedbar-visiting-tag-hook}
 @item speedbar-visiting-tag-hook
 Hooks run when speedbar visits a tag in the selected frame.
-@cindex @code{speedbar-load-hook}
-@item speedbar-load-hook
-Hooks run when speedbar is loaded.
 @cindex @code{speedbar-reconfigure-keymaps-hook}
 @item speedbar-reconfigure-keymaps-hook
 Hooks run when the keymaps are regenerated.  Keymaps are reconfigured
@@ -913,12 +910,11 @@ bindings:
 This function creates a special keymap for use in speedbar.
 
 @item
-Call your install function, or assign it to a hook like this:
+Call your install function, like this:
 
 @smallexample
-(if (featurep 'speedbar)
-    (@var{name}-install-speedbar-variables)
-  (add-hook 'speedbar-load-hook '@var{name}-install-speedbar-variables))
+(with-eval-after-load 'speedbar
+  (@var{name}-install-speedbar-variables))
 @end smallexample
 
 @item
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index f81d996..61cf373 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -46,7 +46,7 @@ copy and modify this GNU manual.''
 @node Top, Overview, (dir), (dir)
 @top @value{tramp} @value{trampver} User Manual
 
-This file documents @value{tramp} @value{trampver}, a remote file
+This file documents @w{@value{tramp} @value{trampver}}, a remote file
 editing package for Emacs.
 
 @value{tramp} stands for ``Transparent Remote (file) Access, Multiple
@@ -312,7 +312,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 Emacs 22.1).
+@value{tramp} is included as part of Emacs (since @w{Emacs 22.1}).
 
 @value{tramp} is also freely packaged for download on the Internet at
 @uref{https://ftp.gnu.org/gnu/tramp/}.  The version number of
@@ -324,9 +324,9 @@ A @value{tramp} release, which is packaged with Emacs, 
could differ
 slightly from the corresponding standalone release.  This is because
 it isn't always possible to synchronize release dates between Emacs
 and @value{tramp}.  Such version numbers have the Emacs version number
-as suffix, like ``2.3.5.26.3''.  This means @value{tramp} 2.3.5 as
-integrated in Emacs 26.3.  A complete list of @value{tramp} versions
-packaged with Emacs can be retrieved by
+as suffix, like ``2.3.5.26.3''.  This means @w{@value{tramp} 2.3.5} as
+integrated in @w{Emacs 26.3}.  A complete list of @value{tramp}
+versions packaged with Emacs can be retrieved by
 
 @vindex customize-package-emacs-version-alist
 @lisp
@@ -557,13 +557,16 @@ of the local file name is the share exported by the 
remote host,
 @cindex method @option{davs}
 @cindex @option{dav} method
 @cindex @option{davs} method
+@cindex method @option{media}
+@cindex @option{media} method
 
 On systems, which have installed @acronym{GVFS, the GNOME Virtual File
 System}, its offered methods could be used by @value{tramp}.  Examples
 are @file{@trampfn{sftp,user@@host,/path/to/file}},
 @file{@trampfn{afp,user@@host,/path/to/file}} (accessing Apple's AFP
-file system), @file{@trampfn{dav,user@@host,/path/to/file}} and
-@file{@trampfn{davs,user@@host,/path/to/file}} (for WebDAV shares).
+file system), @file{@trampfn{dav,user@@host,/path/to/file}},
+@file{@trampfn{davs,user@@host,/path/to/file}} (for WebDAV shares) and
+@file{@trampfn{media,device,/path/to/file}} (for media devices).
 
 
 @anchor{Quick Start Guide: GNOME Online Accounts based methods}
@@ -1126,7 +1129,8 @@ Emacs.
 @value{tramp} does not require a host name part of the remote file
 name when a single Android device is connected to @command{adb}.
 @value{tramp} instead uses @file{@trampfn{adb,,}} as the default name.
-@command{adb devices} shows available host names.
+@command{adb devices}, run in a shell outside Emacs, shows available
+host names.
 
 @option{adb} method normally does not need user name to authenticate
 on the Android device because it runs under the @command{adbd}
@@ -1227,6 +1231,7 @@ supported by these methods.  See method 
@option{nextcloud} for
 handling them.
 
 @item @option{gdrive}
+@cindex @acronym{GNOME} Online Accounts
 @cindex method @option{gdrive}
 @cindex @option{gdrive} method
 @cindex google drive
@@ -1242,8 +1247,26 @@ Since Google Drive uses cryptic blob file names 
internally,
 could produce unexpected behavior in case two files in the same
 directory have the same @code{display-name}, such a situation must be avoided.
 
+@item @option{media}
+@cindex method @option{media}
+@cindex @option{media} method
+@cindex media
+
+Media devices, like cell phones, tablets, cameras, can be accessed via
+the @option{media} method.  Just the device name is needed in order to
+specify the host in the file name.  However, the device must already
+be connected via USB, before accessing it.  Possible device names are
+visible via host name completion, @ref{File name completion}.
+
+Depending on the device type, the access could be read-only.  Some
+devices are accessible under different names in parallel, offering
+different parts of their file system.
+
+@value{tramp} does not require a host name as part of the remote file
+name when a single media device is connected.  @value{tramp} instead
+uses @file{@trampfn{media,,}} as the default name.
+
 @item @option{nextcloud}
-@cindex @acronym{GNOME} Online Accounts
 @cindex method @option{nextcloud}
 @cindex @option{nextcloud} method
 @cindex nextcloud
@@ -1267,11 +1290,11 @@ that for security reasons refuse @command{ssh} 
connections.
 @defopt tramp-gvfs-methods
 This user option is a list of external methods for @acronym{GVFS}@.
 By default, this list includes @option{afp}, @option{dav},
-@option{davs}, @option{gdrive}, @option{nextcloud} and @option{sftp}.
-Other methods to include are @option{ftp}, @option{http},
-@option{https} and @option{smb}.  These methods are not intended to be
-used directly as @acronym{GVFS}-based method.  Instead, they are added
-here for the benefit of @ref{Archive file names}.
+@option{davs}, @option{gdrive}, @option{media}, @option{nextcloud} and
+@option{sftp}.  Other methods to include are @option{ftp},
+@option{http}, @option{https} and @option{smb}.  These methods are not
+intended to be used directly as @acronym{GVFS}-based method.  Instead,
+they are added here for the benefit of @ref{Archive file names}.
 
 If you want to use @acronym{GVFS}-based @option{ftp} or @option{smb}
 methods, you must add them to @code{tramp-gvfs-methods}, and you must
@@ -1642,7 +1665,7 @@ suitable settings.  Refer to the Lisp documentation of 
that variable,
 accessible with @kbd{C-h v tramp-methods @key{RET}}.
 
 In the ELPA archives, there are several examples of such extensions.
-They can be installed with Emacs' Package Manager.  This includes
+They can be installed with Emacs's Package Manager.  This includes
 
 @table @samp
 @c @item anything-tramp
@@ -2095,8 +2118,8 @@ preserves the path value, which can be used to update
 shell supports the login argument @samp{-l}.
 @end defopt
 
-Starting with Emacs 26, @code{tramp-remote-path} can be set per host
-via connection-local
+Starting with @w{Emacs 26}, @code{tramp-remote-path} can be set per
+host via connection-local
 @ifinfo
 variables, @xref{Connection Variables, , , emacs}.
 @end ifinfo
@@ -2450,7 +2473,7 @@ where @samp{192.168.0.1} is the remote host IP address
 Android devices provide a restricted shell access through an USB
 connection.  The local host must have the @command{adb} program
 installed.  Usually, it is sufficient to open the file
-@file{@trampfn{adb,,/}}.  Then you can navigate in the filesystem via
+@file{@trampfn{adb,,/}}.  Then you can navigate in the file system via
 @code{dired}.
 
 Alternatively, applications such as @code{Termux} or @code{SSHDroid}
@@ -2937,10 +2960,10 @@ Example:
 @end example
 
 During file name completion, remote directory contents are re-read
-regularly to account for any changes in the filesystem that may affect
-the completion candidates.  Such re-reads can account for changes to
-the file system by applications outside Emacs (@pxref{Connection
-caching}).
+regularly to account for any changes in the file system that may
+affect the completion candidates.  Such re-reads can account for
+changes to the file system by applications outside Emacs
+(@pxref{Connection caching}).
 
 @defopt tramp-completion-reread-directory-timeout
 The timeout is number of seconds since last remote command for
@@ -3161,8 +3184,8 @@ ensures the correct name of the remote shell program.
 When @code{explicit-shell-file-name} is equal to @code{nil}, calling
 @code{shell} interactively will prompt for a shell name.
 
-Starting with Emacs 26, you could use connection-local variables for
-setting different values of @code{explicit-shell-file-name} for
+Starting with @w{Emacs 26}, you could use connection-local variables
+for setting different values of @code{explicit-shell-file-name} for
 different remote hosts.
 @ifinfo
 @xref{Connection Variables, , , emacs}.
@@ -3231,7 +3254,7 @@ variables.
 @vindex async-shell-command-width
 @vindex COLUMNS@r{, environment variable}
 If Emacs supports the variable @code{async-shell-command-width} (since
-Emacs 27.1), @value{tramp} cares about its value for asynchronous
+@w{Emacs 27.1}), @value{tramp} cares about its value for asynchronous
 shell commands.  It specifies the number of display columns for
 command output.  For synchronous shell commands, a similar effect can
 be achieved by adding the environment variable @env{COLUMNS} to
@@ -3799,7 +3822,11 @@ help the development team find the best solution and 
avoid unrelated
 detours.
 
 To exclude cache-related problems, flush all caches before running the
-test, @ref{Cleanup remote connections}.
+test, @ref{Cleanup remote connections}.  Alternatively, and often
+better for analysis, reproduce the problem in a clean Emacs session
+started with @command{emacs -Q}.  Then, @value{tramp} does not load
+the persistency file (@pxref{Connection caching}), and it does not use
+passwords from @file{auth-source.el} (@pxref{Password handling}).
 
 When including @value{tramp}'s messages in the bug report, increase
 the verbosity level to 6 (@pxref{Traces and Profiles, Traces}) in the
@@ -3840,8 +3867,8 @@ Where is the latest @value{tramp}?
 @item
 Which systems does it work on?
 
-The package works successfully on Emacs 24, Emacs 25, Emacs 26, and
-Emacs 27.
+The package works successfully on @w{Emacs 25}, @w{Emacs 26}, @w{Emacs
+27}, and @w{Emacs 28}.
 
 While Unix and Unix-like systems are the primary remote targets,
 @value{tramp} has equal success connecting to other platforms, such as
@@ -4178,7 +4205,7 @@ Host indication in the mode line?
 
 @cindex @value{tramp} theme
 @vindex tramp-theme-face-remapping-alist
-Install @file{tramp-theme} from GNU ELPA via Emacs' Package Manager.
+Install @file{tramp-theme} from GNU ELPA via Emacs's Package Manager.
 Enable it via @kbd{M-x load-theme @key{RET} tramp @key{RET}}.  Further
 customization is explained in user option
 @code{tramp-theme-face-remapping-alist}.
diff --git a/doc/misc/trampver.texi b/doc/misc/trampver.texi
index 6ee6911..aabb2f8 100644
--- a/doc/misc/trampver.texi
+++ b/doc/misc/trampver.texi
@@ -8,9 +8,9 @@
 @c In the Tramp GIT, the version numbers are auto-frobbed from
 @c tramp.el, and the bug report address is auto-frobbed from
 @c configure.ac.
-@set trampver 2.4.3
+@set trampver 2.5.0-pre
 @set tramp-bug-report-address tramp-devel@@gnu.org
-@set emacsver 24.4
+@set emacsver 25.1
 
 @c Other flags from configuration.
 @set instprefix /usr/local
diff --git a/doc/misc/viper.texi b/doc/misc/viper.texi
index 9ce809e..661eb7c 100644
--- a/doc/misc/viper.texi
+++ b/doc/misc/viper.texi
@@ -1752,10 +1752,10 @@ state.  If @code{nil}, the cursor stays where it was 
before the switch.
 @item viper-always t
 @code{t} means: leave it to Viper to decide when a buffer must be brought
 up in Vi state,
-Insert state, or Emacs state.  This heuristics works well in virtually all
-cases.  @code{nil} means you either has to invoke @code{viper-mode} manually
+Insert state, or Emacs state.  This heuristic works well in virtually all
+cases.  @code{nil} means you either have to invoke @code{viper-mode} manually
 for each buffer (or you can add @code{viper-mode} to the appropriate major mode
-hooks using @code{viper-load-hook}).
+hooks using @code{with-eval-after-load}).
 
 This option must be set in your Viper customization file.
 @item viper-custom-file-name "~/.emacs.d/viper"
@@ -1903,9 +1903,6 @@ List of (parameterless) functions called just after 
entering Replace state
 @item viper-emacs-state-hook nil
 List of (parameterless) functions called just after switching from Vi state
 to Emacs state.
-@item viper-load-hook nil
-List of (parameterless) functions called just after loading Viper.  This is
-the last chance to do customization before Viper is up and running.
 @end table
 @noindent
 You can reset some of these constants in Viper with the Ex command @kbd{:set}
diff --git a/etc/NEWS b/etc/NEWS
index df12c7e..de8e20e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -24,6 +24,40 @@ applies, and please also update docstrings as needed.
 
 * Installation Changes in Emacs 28.1
 
+** Cairo graphics library is now used by default if found.
+'--with-cairo' is now the default, if the appropriate development files
+are found by 'configure'.  Note that building with Cairo means using
+Pango instead of libXFT for font support.  Since Pango 1.44 has
+removed support for bitmapped fonts, this may require you to adjust
+your font settings.
+
+Note also that 'FontBackend' settings in ".Xdefaults" or
+".Xresources", or 'font-backend' frame parameter settings in your init
+files, may need to be adjusted, as 'xft' is no longer a valid backend
+when using Cairo.  Use 'ftcrhb' if your Emacs was built with HarfBuzz
+text shaping support, and 'ftcr' otherwise.  You can determine this by
+checking 'system-configuration-features'.  The 'ftcr' backend will
+still be available when HarfBuzz is supported, but will not be used by
+default.  We strongly recommend building with HarBuzz support. 'x' is
+still a valid backend.
+
+---
+** 'configure' now warns about building with libXft support.
+libXft is unmaintained, and causes a number of problems with modern
+fonts including but not limited to crashes; support for it may be
+removed in a future version of Emacs.  Please consider using
+Cairo + HarfBuzz instead.
+
+---
+** 'configure' now warns about not using HarfBuzz if using Cairo.
+We want to encourage people to use the most modern font features
+available, and this is the Cairo graphics library + HarfBuzz for font
+shaping, so 'configure' now recommends that combination.
+
+---
+** The ftx font backend driver has been removed.
+It was declared obsolete in Emacs 27.1.
+
 
 * Startup Changes in Emacs 28.1
 
@@ -33,15 +67,78 @@ applies, and please also update docstrings as needed.
 
 * Editing Changes in Emacs 28.1
 
++++
+** 'read-number' now has its own history variable.
+Additionally, the function now accepts a HIST argument which can be
+used to specify a custom history variable.
+
++++
+** Input history for 'goto-line' is now local to every buffer.
+Each buffer will keep a separate history of line numbers used with
+'goto-line'.  This should help making faster the process of finding
+line numbers that were previously jumped to.
+
++++
+** When 'suggest-key-bindings' is non-nil, the completion list of 'M-x'
+shows equivalent key bindings for all commands that have them.
+
 
 * Changes in Specialized Modes and Packages in Emacs 28.1
 
+** Help
+
++++
+*** New command 'describe-keymap' describes keybindings in a keymap.
+
+---
+** The old non-SMIE indentation of 'sh-mode' has been removed.
+
+---
+** The sb-image.el library is now marked obsolete.
+This file was a compatibility kludge which is no longer needed.
+
+---
+** 'lisp-mode' now uses 'common-lisp-indent-function'.
+To revert to the previous behaviour,
+'(setq lisp-indent-function 'lisp-indent-function)' from 'lisp-mode-hook'.
+
+** Edebug
+
++++
+*** Edebug specification lists can use the new keyword '&error', which
+unconditionally aborts the current edebug instrumentation with the
+supplied error message.
+
+** Tramp
+
++++
+*** New connection method "media", which allows accessing media devices
+like cell phones, tablets or cameras.
+
 
 * New Modes and Packages in Emacs 28.1
 
 
 * Incompatible Lisp Changes in Emacs 28.1
 
+** 'equal' no longer examines some contents of window configurations.
+Instead, it considers window configurations to be equal only if they
+are 'eq'.  To compare contents, use 'compare-window-configurations'
+instead.  This change helps fix a bug in 'sxhash-equal', which returned
+incorrect hashes for window configurations and some other objects.
+
+---
+** The obsolete function 'thread-alive-p' has been removed.
+
+** 'dns-query' now consistently uses Lisp integers to represent integers.
+Formerly it made an exception for integer components of SOA records,
+because SOA serial numbers can exceed fixnum ranges on 32-bit platforms.
+Emacs now supports bignums so this old glitch is no longer needed.
+
+** The Lisp variables 'previous-system-messages-locale' and
+'previous-system-time-locale' have been removed, as they were created
+by mistake and were not useful to Lisp code.
+
 
 * Lisp Changes in Emacs 28.1
 
@@ -49,13 +146,21 @@ applies, and please also update docstrings as needed.
 'emacs_function' and 'emacs_finalizer' for module functions and
 finalizers, respectively.
 
+** Module functions can now install an optional finalizer that is
+called when the function object is garbage-collected.  Use
+'set_function_finalizer' to set the finalizer and
+'get_function_finalizer' to retrieve it.
+
+** 'parse-time-string' can now parse ISO 8601 format strings,
+such as "2020-01-15T16:12:21-08:00".
+
 
 * Changes in Emacs 28.1 on Non-Free Operating Systems
 
 +++
-** On macOS, Emacs can now load dynamic modules with a '.dylib' suffix.
+** On macOS, Emacs can now load dynamic modules with a ".dylib" suffix.
 'module-file-suffix' now has the value ".dylib" on macOS, but the
-'.so' suffix is supported as well.
+".so" suffix is supported as well.
 
 
 ----------------------------------------------------------------------
@@ -74,17 +179,6 @@ 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/>.
 
-+++
-** 'read-number' now has its own history variable.
-Additionally, the function now accepts a HIST argument which can be
-used to specify a custom history variable.
-
-+++
-** Input history for 'goto-line' is now local to every buffer.
-Each buffer will keep a separate history of line numbers used with
-'goto-line'.  This should help making faster the process of finding
-line numbers that were previously jumped to.
-
 
 Local variables:
 coding: utf-8
diff --git a/etc/NEWS.24 b/etc/NEWS.24
index 8207a8c..60c2b4d 100644
--- a/etc/NEWS.24
+++ b/etc/NEWS.24
@@ -3604,10 +3604,12 @@ advertised at the time.)
 
 ** Debugger changes
 
-*** New macro `condition-case-unless-debug' (this was actually added in
-Emacs 23.1 as condition-case-no-debug, but not advertised)
+*** New macro `condition-case-unless-debug'.
+(This was actually added in Emacs 23.1 as condition-case-no-debug, but
+not advertised)
 
-*** The macro `with-demoted-errors' was added in Emacs 23.1, but not 
advertised.
+*** The macro `with-demoted-errors'.
+It was also added in Emacs 23.1, but not advertised.
 
 *** Variable `stack-trace-on-error' removed.
 
@@ -3691,6 +3693,8 @@ argument is supplied (see Trash changes, above).
 
 *** New file predicates: `file-equal-p', `file-in-directory-p'.
 
+*** New function `file-size-human-readable'.
+
 ** Tool-bars can display separators.
 Tool-bar separators are handled like menu separators in menu-bar maps,
 i.e. via menu entries of the form `(menu-item "--")'.
diff --git a/etc/NEWS.27 b/etc/NEWS.27
index a8c8e27..433f1f7 100644
--- a/etc/NEWS.27
+++ b/etc/NEWS.27
@@ -38,7 +38,7 @@ HarfBuzz text shaping engine.  It is on by default; use 
'./configure
 --without-harfbuzz' to build without it.  The HarfBuzz text shaping is
 available via new font backend drivers 'xfthb' and 'ftcrhb' for Xft
 and Cairo drawings, respectively, and via the 'harfbuzz' backend on
-MS-Windows.  The Harfbuzz text shaping is preferred to the previously
+MS-Windows.  The HarfBuzz text shaping is preferred to the previously
 supported ones, so the font backends that use older shaping engines
 (FLT on GNU and Unix systems and Uniscribe on MS-Windows) are not
 enabled by default; they can be enabled via the 'font-backend' frame
@@ -56,7 +56,10 @@ than their Lisp counterparts from json.el.
 ** The configure option '--with-cairo' is no longer experimental.
 This builds Emacs with Cairo drawing, and supports built-in printing
 when Emacs is built with GTK+.  Some severe bugs in this build were
-fixed, and we can therefore offer this to users without caveats.
+fixed, and we can therefore offer this to users without caveats.  Note
+that building with Cairo enabled results in using Pango instead of
+libXft for font support, and that Pango 1.44 has removed support for
+bitmapped fonts.
 
 +++
 ** Emacs now uses a "portable dumper" instead of unexec.
@@ -66,11 +69,11 @@ Randomization (ASLR) feature, a security technique used by 
most modern
 operating systems.
 
 When built with the portable dumping support (which is the default),
-Emacs looks for the 'emacs.pdmp' file, generated during the build, in
+Emacs looks for the "emacs.pdmp" file, generated during the build, in
 its data directory at startup, and loads the dumped state from there.
-The new command-line argument '--dump-file=FILE' allows to specify a
-non-default '.pdmp' file to load the state from; see the node "Initial
-Options" in the Emacs manual for more information.
+The new command-line argument '--dump-file=FILE' allows specifying a
+non-default ".pdmp" file to load the state from; see the node
+"(emacs) Initial Options" in the Emacs manual for more information.
 
 An Emacs started via a dump file can create a new dump file only if it
 was invoked with the '-batch' option.  (This is a temporary
@@ -92,7 +95,7 @@ change to one of the data structures that it relies on.
 '--enable-checking=xmallocoverrun' have been withdrawn.  The former
 made Emacs irredeemably slow, and the latter made it crash.  Neither
 option was useful with modern debugging tools such as AddressSanitizer.
-(See etc/DEBUG for the details of using the modern replacements of the
+(See "etc/DEBUG" for the details of using the modern replacements of the
 removed configure options.)
 
 ---
@@ -150,28 +153,36 @@ builds respectively.
 Pass '--without-modules' to 'configure' to disable dynamic module
 support.
 
+---
+** The ftx font backend driver is now obsolete and will be removed in
+Emacs 28.
+
 
 * Startup Changes in Emacs 27.1
 
 +++
-** Emacs now uses the XDG convention for init files.
-For example, it looks for init.el in "~/.config/emacs/init.el", and
-similarly for other init files.
+** Emacs can now use the XDG convention for init files.
+The 'XDG_CONFIG_HOME' environment variable (which defaults to
+"~/.config") specifies the XDG configuration parent directory.  Emacs
+checks for "init.el" and other configuration files inside the "emacs"
+subdirectory of 'XDG_CONFIG_HOME', i.e. "$XDG_CONFIG_HOME/emacs/init.el"
 
-The XDG_CONFIG_HOME environment variable (which defaults to "~/.config")
-specifies the parent directory of these and other configuration files,
-and will override their traditional locations (the home directory,
-"~/.emacs.d", etc.).
+However, Emacs will still initially look for init files in their
+traditional locations if "~/.emacs.d" or "~/.emacs" exist, even if
+"$XDG_CONFIG_HOME/emacs" also exists.  This means that you must delete
+or rename any existing "~/.emacs.d" and "~/.emacs" to enable use of
+the XDG directory.
 
-Emacs will still look for init files in their traditional locations if
-XDG_CONFIG_HOME/emacs does not exist, so invoking Emacs with
-XDG_CONFIG_HOME='/nowhere' might be useful if your new-location init
-files are scrambled, or if you want to force Emacs to ignore files
-under XDG_CONFIG_HOME for some other reason.
+If "~/.emacs.d" does not exist, and Emacs has decided to use it
+(i.e. "$XDG_CONFIG_HOME/emacs" does not exist), Emacs will create it.
+Emacs will never create "$XDG_CONFIG_HOME/emacs".
+
+Whichever directory Emacs decides to use, it will set
+'user-emacs-directory' to point to it.
 
 +++
 ** Emacs can now be configured using an early init file.
-The file is called 'early-init.el', in 'user-emacs-directory'.  It is
+The file is called "early-init.el", in 'user-emacs-directory'.  It is
 loaded very early in the startup process: before graphical elements
 such as the tool bar are initialized, and before the package manager
 is initialized.  The primary purpose is to allow customizing how the
@@ -212,7 +223,7 @@ it won't work right without some adjustment:
 Units that are ordered after 'emacs.service' will only be started
 after Emacs has finished initialization and is ready for use.
 (If your Emacs is installed in a non-standard location and you copied the
-emacs.service file to eg "~/.config/systemd/user/", you will need to copy
+emacs.service file to e.g. "~/.config/systemd/user/", you will need to copy
 the new version of the file again.)
 
 
@@ -278,7 +289,6 @@ The old function names are maintained as aliases for 
backward
 compatibility.
 
 ** emacsclient
-
 +++
 *** emacsclient now supports the 'EMACS_SOCKET_NAME' environment variable.
 The command-line argument '--socket-name' overrides it.
@@ -304,6 +314,15 @@ causing XFT crashes, they are now filtered out.  Setting
 require setting 'face-ignored-fonts' to filter out problematic fonts.
 Known problematic fonts are "Noto Color Emoji" and "Emoji One".
 
+---
+** The GTK+ font chooser now respects 'face-ignored-fonts'.
+When using 'menu-set-font' under GTK3, the available fonts are now
+matched against 'face-ignored-fonts'.
+
+---
+** The GTK+ font chooser now remembers the previously selected settings.
+It now remembers the name, size, style, etc.
+
 +++
 ** New user option 'what-cursor-show-names'.
 When non-nil, 'what-cursor-position' will show the name of the character
@@ -333,8 +352,9 @@ answers, but also function keys like 'F1', character events 
such as
 'C-M-h', and control characters like 'C-h'.
 
 ** Lexical binding is now used when evaluating interactive Elisp forms.
-More specifically, lexical-binding is now used for 'M-:', '--eval', as
-well as in the "*scratch*" and "*ielm*" buffers.
+More specifically, 'lexical-binding' is now used for 'M-:', '--eval',
+as well as in 'lisp-interaction-mode' and 'ielm-mode', used in the
+"*scratch*" and "*ielm*" buffers.
 
 ---
 ** The new user option 'tooltip-resize-echo-area' avoids truncating
@@ -429,7 +449,7 @@ from a remote host.
 
 +++
 ** The function 'executable-find' supports an optional argument REMOTE.
-This triggers to search the program on the remote host as indicated by
+This triggers searching for the program on the remote host as indicated by
 'default-directory'.
 
 +++
@@ -459,11 +479,11 @@ Customize 'switch-to-prev-buffer-skip' instead.
 
 +++
 ** New user option 'switch-to-prev-buffer-skip'.
-This user option allows to specify the set of buffers that may be
+This user option allows specifying the set of buffers that may be
 shown by 'switch-to-prev-buffer' and 'switch-to-next-buffer' more
 stringently than the now obsolete 'switch-to-visible-buffer'.
 
-** New 'flex' completion style
+** New 'flex' completion style.
 An implementation of popular "flex/fuzzy/scatter" completion which
 matches strings where the pattern appears as a subsequence.  Put
 simply, makes "foo" complete to both "barfoo" and "frodo".  Add 'flex'
@@ -488,7 +508,6 @@ Consequently, a theme generally shouldn't specify this 
attribute
 unless it has a good reason to do so.
 
 ** Connection-local variables
-
 +++
 *** Connection-local variables are applied by default like file-local
 and directory-local variables.
@@ -516,7 +535,6 @@ Emacs configured with Cairo drawing and linked with cairo 
>= 1.16.0.
 
 +++
 ** Emacs now optionally displays a fill column indicator.
-
 This is similar to what 'fill-column-indicator' package provides, but
 much faster and compatible with 'show-trailing-whitespace'.
 
@@ -528,10 +546,10 @@ The indicator is not displayed at all in minibuffer 
windows and
 in tooltips, as it is not useful there.
 
 There are 2 new buffer local variables and 1 face to customize this
-mode they are described in the manual "(emacs) Display".
+mode, they are described in the manual "(emacs) Display".
 
 +++
-** 'progress-reporter-update' accepts a suffix string to display.
+** 'progress-reporter-update' now accepts an optional suffix string to display.
 
 ---
 ** New user option 'xref-file-name-display' controls the display of
@@ -542,7 +560,6 @@ It is used for displaying file sizes and disk space in some 
cases.
 
 +++
 ** Emacs now interprets RGB triplets like HTML, SVG, and CSS do.
-
 The X convention previously used differed slightly, particularly for
 RGB triplets with a single hexadecimal digit per component.
 
@@ -550,8 +567,8 @@ RGB triplets with a single hexadecimal digit per component.
 ** The toolbar now shows the equivalent key binding in its tooltips.
 
 ---
-** The File menu-bar menu was re-arranged: Print menu items moved to
-submenu, and also added the new entries for tabs.
+** The File menu-bar menu was re-arranged.
+Print menu items moved to submenu, and also added the new entries for tabs.
 
 ---
 ** 'scroll-lock-mode' is now bound to the 'Scroll_Lock' key globally.
@@ -578,14 +595,14 @@ if so, 'backup-by-copying-when-mismatch' will be forced 
on.
 * Editing Changes in Emacs 27.1
 
 +++
-** When asked to visit a large file, Emacs now offers visiting it literally.
+** When asked to visit a large file, Emacs now offers to visit it literally.
 Previously, Emacs would only ask for confirmation before visiting
 large files.  Now it also offers a third alternative: to visit the
 file literally, as in 'find-file-literally', which speeds up
 navigation and editing of large files.
 
 +++
-** 'zap-to-char' now uses history of characters you used to zap to.
+** 'zap-to-char' now uses the history of characters you used to zap to.
 'zap-to-char' uses the new 'read-char-from-minibuffer' function to allow
 navigating through the history of characters that have been input.
 This is mostly useful for characters that have complex input methods
@@ -680,7 +697,7 @@ current and the previous or the next line, as before.
 
 +++
 ** You can now change the font size with the mouse wheel.
-Scroling the mouse wheel with the Ctrl key pressed will now act the
+Scrolling the mouse wheel with the Ctrl key pressed will now act the
 same as the 'C-x C-+' and 'C-x C--' commands.
 
 
@@ -715,7 +732,7 @@ non-nil.
 
 ---
 ** 'autoconf-mode' is now used instead of 'm4-mode' for the
-acinclude.m4/aclocal.m4/acsite.m4 files.
+"acinclude.m4" / "aclocal.m4" / "acsite.m4" files.
 
 ---
 ** On GNU/Linux, 'M-x battery' will now list all batteries, no matter
@@ -729,6 +746,7 @@ network connection information (in addition to the host 
name).
 
 ---
 ** desktop
+
 *** When called interactively with a prefix arg 'C-u', 'desktop-read'
 now prompts the user for the directory containing the desktop file.
 
@@ -745,53 +763,63 @@ an offset to absolute line numbers.
 
 +++
 ** winner
+
 *** A new user option, 'winner-boring-buffers-regexp', has been added.
 
 ** table
-** 'table-generate-source' and friends now support outputting wiki and
+
+*** 'table-generate-source' and friends now support outputting wiki and
 mediawiki format tables.
 
 ---
 ** telnet-mode
+
 *** Reverting a buffer in 'telnet-mode' will restart a closed connection.
 
 ** goto-addr
-*** A way to more conveniently specify what URI address schemes that
-should be ignored have been added via the
-'goto-address-uri-schemes-ignored' variable.
+
+*** A way to more conveniently specify what URI address schemes should
+be ignored has been added via the 'goto-address-uri-schemes-ignored'
+variable.
 
 +++
 ** tex-mode
+
 *** 'latex-noindent-commands' controls indentation of certain commands.
 You can use this new user option to control indentation of arguments of
 \emph, \footnote, and similar commands.
 
 ** byte compiler
+
 *** 'byte-compile-dynamic' is now obsolete.
 This is because on the one hand it suffers from misbehavior in corner
 cases that have plagued it for years, and on the other experiments indicated
 that it doesn't bring any measurable benefit.
 
 ---
-*** The 'g' keystroke in *Compile-Log* buffers has been bound to a new
-command that will recompile the file previously compiled with 'M-x
+*** The 'g' keystroke in "*Compile-Log*" buffers has been bound to a
+new command that will recompile the file previously compiled with 'M-x
 byte-compile-file' and the like.
 
 ** compile.el
+
 ---
 *** In 'compilation-error-regexp-alist', 'line' (and 'end-line') can
 be functions.
+
 +++
 *** 'compilation-context-lines' can now take the value t; this is like
 nil, but instead of scrolling the current line to the top of the
 screen when there is no left fringe, it inserts a visible arrow before
 column zero.
+
 ---
 *** The new 'compilation-transform-file-match-alist' user option can
 be used to transform file name matches compilation output, and remove
 known false positives being recognized as warnings/errors.
 
 ** cl-lib.el
+
 +++
 *** 'cl-defstruct' has a new ':noinline' argument to prevent inlining
 its functions.
@@ -803,13 +831,16 @@ its functions.
 *** 'cl-values-list' will now signal an error if its argument isn't a list.
 
 ** doc-view.el
+
 *** New commands 'doc-view-presentation' and 'doc-view-fit-window-to-page'.
-*** Added support for password-protected PDF files
+
+*** Added support for password-protected PDF files.
 
 *** A new user option 'doc-view-pdftotext-program-args' has been added
 to allow controlling how the conversion to text is done.
 
 ** Ido
+
 *** New user option 'ido-big-directories' to mark directories whose
 names match certain regular expressions as big.  Ido won't attempt to
 list the contents of such directories when completing file names.
@@ -841,13 +872,13 @@ at the end of the active minibuffer.
 a character using the minibuffer by 'read-char-from-minibuffer'.
 
 ** map.el
+
 *** Now also understands plists.
 *** Now defined via generic functions that can be extended via 'cl-defmethod'.
 *** Deprecate the 'map-put' macro in favor of a new 'map-put!' function.
 *** 'map-contains-key' now returns a boolean rather than the key.
 *** Deprecate the 'testfn' args of 'map-elt' and 'map-contains-key'.
 *** New generic function 'map-insert'.
-
 +++
 *** The 'type' arg can be a list '(hash-table :key1 VAL1 :key2 VAL2 ...)'.
 
@@ -917,7 +948,6 @@ The mode is automatically enabled in files that start with 
the
 ** project.el
 
 *** New commands 'project-search' and 'project-query-replace-regexp'.
-
 *** New user option 'project-read-file-name-function'.
 
 ** Etags
@@ -1065,7 +1095,7 @@ by Hg.
 you invoke 'C-x v m' ('vc-merge').
 
 ---
-*** The Hg (Mercurial) back-end now use tags, branches and bookmarks
+*** The Hg (Mercurial) back-end now uses tags, branches and bookmarks
 instead of revision numbers as completion candidates when it prompts
 for a revision.
 
@@ -1117,6 +1147,7 @@ Emacs 24.1, but wasn't documented until now.
 *** New command 'diff-buffers' interactively diffs two buffers.
 
 ** Diff mode
+
 +++
 *** Hunks are now automatically refined by font-lock.
 To disable refinement, set the new user option 'diff-refine' to nil.
@@ -1244,7 +1275,7 @@ included.
 Database passwords can now by stored in NETRC or JSON data files that
 may optionally be encrypted.  When establishing an interactive session
 with the database via 'sql-connect' or a product specific function,
-like 'sql-mysql' or 'my-postgres', the password wallet will be
+like 'sql-mysql' or 'sql-postgres', the password wallet will be
 searched for the password.  The 'sql-product', 'sql-server',
 'sql-database', and the 'sql-username' will be used to identify the
 appropriate authorization.  This eliminates the discouraged practice of
@@ -1252,9 +1283,9 @@ embedding database passwords in your Emacs initialization.
 
 See the 'auth-source' module for complete documentation on the file
 formats.  By default, the wallet file is expected to be in the
-'user-emacs-directory', named 'sql-wallet' or '.sql-wallet', with
-'.json' (JSON) or no (NETRC) suffix.  Both file formats can optionally
-be encrypted with GPG by adding an additional '.gpg' suffix.
+'user-emacs-directory', named "sql-wallet" or ".sql-wallet", with
+".json" (JSON) or no (NETRC) suffix.  Both file formats can optionally
+be encrypted with GPG by adding an additional ".gpg" suffix.
 
 ** Term
 
@@ -1316,8 +1347,8 @@ package data.  It is therefore recommended to keep this 
line.
 
 +++
 *** Change of 'package-check-signature' for packages with multiple sigs.
-In previous Emacsen, 't' checked that all signatures are valid.
-Now 't' only checks that at least one signature is valid and the new 'all'
+In previous Emacsen, t checked that all signatures are valid.
+Now t only checks that at least one signature is valid and the new 'all'
 value needs to be used if you want to enforce that all signatures
 are valid.  This only affects packages with multiple signatures.
 
@@ -1379,7 +1410,7 @@ where you can select a node to go back (like in browsers).
 *** Info can now follow 'file://' protocol URLs.
 The 'file://' URLs in Info documents can now be followed by passing
 them to the 'browse-url' function, like the other protocols: 'ftp',
-'http', and 'https'.  This allows to have references to local HTML
+'http', and 'https'.  This allows having references to local HTML
 files, for example.
 
 ---
@@ -1397,9 +1428,9 @@ This command finds definitions of the identifier at the 
place of a
 mouse click event, and is intended to be bound to a mouse event.
 
 +++
-*** Changing 'xref-marker-ring-length' works after 'xref.el' is loaded.
+*** Changing 'xref-marker-ring-length' works after xref.el is loaded.
 Previously, setting 'xref-marker-ring-length' would only take effect
-if set before 'xref.el' was loaded.
+if set before xref.el was loaded.
 
 ---
 *** 'xref-find-definitions' now sets the mark at the buffer position
@@ -1418,8 +1449,7 @@ behavior and the display of results.
 *** Search results show the buffer even for one hit.
 The search-type Xref commands (e.g. 'xref-find-references' or
 'project-find-regexp') now show the results buffer even when there is
-only one hit.  This can be altered by changing
-'xref-show-xrefs-function'.
+only one hit.  This can be altered by changing 'xref-show-xrefs-function'.
 
 +++
 *** Xref buffers support refreshing the search results.
@@ -1428,6 +1458,18 @@ A new command 'xref-revert-buffer' is bound to 'g'.
 ---
 *** Imenu support has been added to 'xref--xref-buffer-mode'.
 
+*** New generic method 'xref-backend-identifier-completion-ignore-case'.
+Using it, the etags backend now honors 'tags-case-fold-search' during
+identifier completion.
+
+** Checkdoc
+
+---
+*** Checkdoc can now optionally spell-check doc strings.
+Invoking 'checkdoc-buffer' with a non-nil TAKE-NOTES argument
+(interactively, with a prefix arg) will now spell-check the doc
+strings and report all the spelling mistakes.
+
 ** Icomplete
 
 +++
@@ -1441,12 +1483,13 @@ completion facilities.
 ** Ecomplete
 
 ---
-*** The ecomplete sorting has changed to a decay-based algorithm.
+*** The Ecomplete sorting has changed to a decay-based algorithm.
 This can be controlled by the new 'ecomplete-sort-predicate' user option.
 
 ---
-*** The 'ecompleterc' file is now placed in "~/.emacs.d/ecompleterc" by 
default.
-Of course it will still find it if you have it in "~/.ecompleterc".
+*** The 'ecomplete-database-file' file is now placed in
+"~/.emacs.d/ecompleterc" by default.  Of course it will still find it
+if you have it in "~/.ecompleterc".
 
 ** Gnus
 
@@ -1466,14 +1509,14 @@ are marked with "." in the summary mode lines.)
 'never' for never expunging messages, 'immediately' for immediately
 expunging deleted messages, and 'on-exit' to expunge deleted articles
 when exiting the group's summary buffer.  Setting 'nnimap-expunge' to
-'nil' or 't' is still supported but not recommended, since it may
+nil or t is still supported but not recommended, since it may
 result in Gnus expunging all messages that have been flagged as
 deleted by any IMAP client (rather than just those that have been
 deleted by Gnus).
 
 +++
 *** New user option 'gnus-use-atomic-windows' makes Gnus window layouts atomic.
-See the "Atomic Windows" section of the Elisp manual for details.
+See the "(elisp) Atomic Windows" node of the Elisp manual for details.
 
 +++
 *** There's a new value for 'gnus-article-date-headers',
@@ -1492,8 +1535,9 @@ This feature can be enabled by setting the new 
'nnimap-use-namespaces'
 server variable to non-nil.
 
 +++
-*** A prefix argument to 'gnus-summary-limit-to-score' will limit reverse.
-Limit to articles with score at below.
+*** A prefix argument to 'gnus-summary-limit-to-score' will limit in reverse.
+Limit to articles with score "at or below" the SCORE argument rather
+than "at or above".
 
 ---
 *** The function 'gnus-score-find-favorite-words' has been renamed
@@ -1511,20 +1555,19 @@ See the concept index in the Gnus manual for the 
'match-list' entry.
 *** nil is no longer an allowed value for 'mm-text-html-renderer'.
 
 +++
-The default value of 'mm-inline-large-images' has changed from nil to
-'resize', which means that large images will be resized instead of
+*** The default value of 'mm-inline-large-images' has changed from nil
+to 'resize', which means that large images will be resized instead of
 displayed with an external program by default.
 
 +++
-*** A new Gnus summary mode command, 'S A'
-('gnus-summary-attach-article') can be used to attach the current
-article(s) to a pre-existing Message buffer, or create a new Message
-buffer with the article(s) attached.
+*** A new Gnus summary mode command, 'S A' ('gnus-summary-attach-article')
+can be used to attach the current article(s) to a pre-existing Message
+buffer, or create a new Message buffer with the article(s) attached.
 
 +++
-*** A new Gnus summary mode command, 'w'
-('gnus-summary-browse-url') scans the article buffer for URLs, and
-offers them to the user to open with 'browse-url'.
+*** A new Gnus summary mode command, 'w' ('gnus-summary-browse-url')
+scans the article buffer for URLs, and offers them to the user to open
+with 'browse-url'.
 
 ---
 *** New user option 'nnir-notmuch-filter-group-names-function'.
@@ -1545,8 +1588,7 @@ fail.
 *** New hook 'erc-insert-done-hook'.
 This hook is called after strings have been inserted into the buffer,
 and is free to alter point and window configurations, as it's not
-called from inside a 'save-excursion', as opposed to
-'erc-insert-post-hook'.
+called from inside a 'save-excursion', as opposed to 'erc-insert-post-hook'.
 
 ---
 *** 'erc-button-google-url' has been renamed to 'erc-button-search-url'
@@ -1557,6 +1599,18 @@ and its value has been changed to Duck Duck Go.
 The user option to use instead to alter text to be sent is now
 'erc-pre-send-functions'.
 
+---
+*** Improve matching/highlighting of nicknames.
+Open and close parenthesis and apostrophe are not considered valid
+nick characters anymore, matching the given grammar in RFC 2812
+section 2.3.1.  This enables correct matching and highlighting of
+nicks when they are surrounded by parentheses, like "(nick)", and when
+adjacent to an apostrophe, like "nick's".
+
+---
+*** Set 'erc-button-url-regexp' to 'browse-url-button-regexp'
+which better handles surrounding pair of parentheses.
+
 ** EUDC
 
 ---
@@ -1632,14 +1686,14 @@ attempt when communicating with the SMTP server(s), the
 'smtpmail-servers-requiring-authorization' user option can be used.
 
 +++
-*** smtpmail will now try resending mail when getting a transient 4xx
+*** smtpmail will now try resending mail when getting a transient "4xx"
 error message from the SMTP server.  The new 'smtpmail-retries'
 user option says how many times to retry.
 
 ** Footnote mode
 
 ---
-*** Support Hebrew-style footnotes
+*** Support Hebrew-style footnotes.
 
 ---
 *** Footnote text lines are now aligned.
@@ -1675,7 +1729,7 @@ If non-nil, the default, buffers opened during 
pdbtracking session are
 killed when pdbtracking session is finished.
 
 ---
-*** New function 'python-shell-send-region'.
+*** New function 'python-shell-send-statement.
 It sends the statement delimited by 'python-nav-beginning-of-statement'
 and 'python-nav-end-of-statement' to the inferior Python process.
 
@@ -1733,7 +1787,7 @@ with a numeric argument.
 of matches in the Isearch prompt.  User options
 'lazy-count-prefix-format' and 'lazy-count-suffix-format' define the
 format of the current and the total number of matches in the prompt's
-prefix and suffix respectively.
+prefix and suffix, respectively.
 
 ---
 *** 'lazy-highlight-buffer' highlights matches in the full buffer.
@@ -1746,7 +1800,6 @@ highlight in one iteration while processing the full 
buffer.
 
 +++
 *** New isearch bindings.
-
 'C-M-z' invokes new function 'isearch-yank-until-char', which yanks
 everything from point up to but not including the specified
 character into the search string.  This is especially useful for
@@ -1763,13 +1816,13 @@ to the existing binding 'M-s h r' ('highlight-regexp') 
that highlights
 JUST the search string.
 
 +++
-*** New user option 'isearch-yank-on-move' provides options 't' and 'shift'
+*** New user option 'isearch-yank-on-move' provides options t and 'shift'
 to extend the search string by yanking text that ends at the new
 position after moving point in the current buffer.  'shift' extends
 the search string by motion commands while holding down the shift key.
 
 +++
-*** 'isearch-allow-scroll' provides new option 'unlimited' to allow
+*** 'isearch-allow-scroll' provides a new option 'unlimited' to allow
 scrolling any distance off screen.
 
 ---
@@ -1794,7 +1847,7 @@ IOTA WITH OXIA".
 *** New char-folding options: 'char-fold-include' lets you add ad hoc
 foldings, 'char-fold-exclude' to remove foldings from default decomposition,
 and 'char-fold-symmetric' to search for any of an equivalence class of
-characters.  For example, with a 'nil' value of 'char-fold-symmetric'
+characters.  For example, with a nil value of 'char-fold-symmetric'
 you can search for "e" to find "é", but not vice versa.  With a non-nil
 value you can search for either, for example, you can search for "é"
 to find "e".
@@ -1885,7 +1938,7 @@ The abbreviation can be disabled by the new user option
 ** ERT
 
 +++
-*** New variable 'ert-quiet' allows to make ERT output in batch mode
+*** New variable 'ert-quiet' allows making ERT output in batch mode
 less verbose by removing non-essential information.
 
 +++
@@ -1908,7 +1961,7 @@ This is useful for games where lower scores are better, 
like time-based games.
 ** Filecache
 
 ---
-*** Completing filenames in the minibuffer via 'C-TAB' now uses the
+*** Completing file names in the minibuffer via 'C-TAB' now uses the
 styles as configured by the user option 'completion-styles'.
 
 ** New macros 'thunk-let' and 'thunk-let*'.
@@ -1985,6 +2038,14 @@ variable for remote shells.  It still defaults to 
"/bin/sh".
 ** Single shell commands
 
 +++
+*** 'shell-command-dont-erase-buffer' accepts the value 'erase' to
+force to erase the output buffer before execution of the command.
+
+*** The new functions 'shell-command-save-pos-or-erase' and
+'shell-command-set-point-after-cmd' control how point is handled
+between two consecutive shell commands in the same buffer.
+
++++
 *** 'async-shell-command-width' defines the number of display columns
 available for output of asynchronous shell commands.
 
@@ -2024,21 +2085,21 @@ the real password is revealed (via 'reveal-mode').  The 
new
 ** Tramp
 
 +++
-*** New connection method "nextcloud", which allows to access OwnCloud
+*** New connection method "nextcloud", which allows accessing OwnCloud
 or NextCloud hosted files and directories.
 
 +++
-*** New connection method "rclone", which allows to access system
+*** New connection method "rclone", which allows accessing system
 storages via the 'rclone' program.  This feature is experimental.
 
 +++
-*** New connection method "sudoedit", which allows to edit local files
+*** New connection method "sudoedit", which allows editing local files
 with different user credentials.  Contrary to the "sudo" method, no
 session is run permanently in the background.  This is for security
 reasons.
 
 +++
-*** Connection methods "obex" and "synce" are removed, because they
+*** Connection methods "obex" and "synce" have been removed, because they
 are obsoleted in GVFS.
 
 +++
@@ -2050,18 +2111,18 @@ from auth-source search are taken into account.  This 
can be disabled
 by setting the user option 'tramp-completion-use-auth-sources' to nil.
 
 +++
-*** The user option 'tramp-ignored-file-name-regexp' allows to disable
+*** The user option 'tramp-ignored-file-name-regexp' allows disabling
 Tramp for some look-alike remote file names.
 
 +++
 *** For some connection methods, like "su" or "sudo", the host name in
-ad-hoc multi-hop file names must match the previous hop.  Default host
-names are adjusted to the host name from the previous hop.
+multi-hop file names must match the previous hop.  Default host names
+are adjusted to the host name from the previous hop.
 
 +++
-*** For the connection methods "sudo" and "doas" there exists a
-timeout, after which the underlying session is disabled.  This is for
-security reasons.
+*** A timeout has been added for the connection methods "sudo" and "doas".
+The underlying session is disabled when the timeout expires.  This is
+for security reasons.
 
 +++
 *** For some connection methods, like "sshx" or "plink", it is
@@ -2071,7 +2132,7 @@ cooperates badly with Tramp.
 
 +++
 *** New commands 'tramp-rename-files' and 'tramp-rename-these-files'.
-They allow to save remote files somewhere else when the corresponding
+They allow saving remote files somewhere else when the corresponding
 host is not reachable anymore.
 
 ** Rcirc
@@ -2092,15 +2153,6 @@ Two new user options are provided for this:
 *** The return value of method 'register-val-describe' includes the
 names of buffers shown by the windows of a window configuration.
 
----
-** The options.el library has been removed.
-It was obsolete since Emacs 22.1, replaced by customize.
-
----
-** The tls.el and starttls.el libraries are now marked obsolete.
-Use of built-in libgnutls based functionality (described in the Emacs
-GnuTLS manual) is recommended instead.
-
 ** Message
 
 ---
@@ -2135,7 +2187,7 @@ are formatted as MIME digests.
 *** 'message-forward-included-headers' has changed its default to
 exclude most headers when forwarding.
 
-*** 'mml-secure-openpgp-sign-with-sender' sets also "gpg --sender"
+*** 'mml-secure-openpgp-sign-with-sender' sets also "gpg --sender".
 When 'mml-secure-openpgp-sign-with-sender' is non-nil message sender's
 email address (in addition to its old behavior) will also be used to
 set gpg's "--sender email@domain" option.
@@ -2145,10 +2197,10 @@ The option is useful for two reasons when verifying the 
signature:
  1. GnuPG's TOFU statistics are updated for the specific user id
     (email) only.  See gpg(1) man page about "--sender".
 
- 2. GnuPG's '--auto-key-retrieve' functionality can use WKD (web key
+ 2. GnuPG's "--auto-key-retrieve" functionality can use WKD (web key
     directory) method for finding the signer's key.  You need GnuPG
     2.2.17 to fully benefit from this feature.  See gpg(1) man page for
-    '--auto-key-retrieve'.
+    "--auto-key-retrieve".
 
 ---
 ** EasyPG
@@ -2166,9 +2218,9 @@ been removed.  Use 'encode-coding-string', 
'decode-coding-string', and
 ---
 *** 'epg-context' structure supports now 'sender' slot.
 The value of the new 'sender' slot (if a string) is used to set gpg's
-'--sender' option.  This feature is used by
+"--sender" option.  This feature is used by
 'mml-secure-openpgp-sign-with-sender'.  See gpg(1) manual page about
-'--sender' for more information.
+"--sender" for more information.
 
 ---
 ** Rmail
@@ -2280,7 +2332,7 @@ expressions from simpler parts.
 
 +++
 *** New value of 'minibuffer' frame parameter 'child-frame'.
-This allows to create and parent immediately a minibuffer-only child
+This allows creating and immediately parenting a minibuffer-only child
 frame when making a frame.
 
 ---
@@ -2327,7 +2379,7 @@ in a terminal frame.
 ---
 *** JSX syntax is now automatically detected and enabled.
 If a file imports Facebook's 'React' library, or if the file uses the
-extension '.jsx', then various features supporting XML-like syntax
+extension ".jsx", then various features supporting XML-like syntax
 will be supported in 'js-mode' and derivative modes.  ('js-jsx-mode'
 no longer needs to be enabled.)
 
@@ -2409,7 +2461,7 @@ of an idle Emacs, but may fail on some network file 
systems; set
 notification is not supported.  The default value is nil.
 
 +++
-*** New variable 'buffer-auto-revert-by-notification'
+*** New variable 'buffer-auto-revert-by-notification'.
 A major mode can declare that notification on the buffer's default
 directory is sufficient to know when updates are required, by setting
 the new variable 'buffer-auto-revert-by-notification' to a non-nil
@@ -2546,6 +2598,7 @@ if you set 'time-stamp-format' or 'time-stamp-pattern' 
with a
 file-local variable, you may need to update the value.
 
 ** mode-local
+
 ---
 *** Declare 'define-overload' and 'define-child-mode' as obsolete.
 
@@ -2560,13 +2613,38 @@ To do this, use 'c-toggle-comment-style', if needed, to 
set the desired
 default comment style (block or line); then set the user option
 'c-mark-wrong-style-of-comment' to non-nil.
 
+** Mailcap
+
+---
+*** The new function 'mailcap-file-name-to-mime-type' has been added.
+It's a simple convenience function for looking up MIME types based on
+file name extensions.
+
+---
+*** The default way the list of possible external viewers for MIME
+types is sorted and chosen has changed.  Earlier, the most specific
+viewer was chosen, even if there was a general override in "~/.mailcap".
+For instance, if "/etc/mailcap" has an entry for "image/gif", that one
+will be chosen even if you have an entry for "image/*" in your
+"~/.mailcap" file.  But with the new method, entries from "~/.mailcap"
+overrides all system and Emacs-provided defaults.  To get the old
+method back, set 'mailcap-prefer-mailcap-viewers' to nil.
+
+** URL
+
+---
+*** The 'file:' handler no longer looks for "index.html" in
+directories if you ask it for a "file:///dir" URL.  Since this is a
+low-level library, such decisions (if they are to be made at all) are
+left to higher-level functions.
+
 
 * New Modes and Packages in Emacs 27.1
 
 ** Tab Bars
 
 +++
-*** Tab Bar mode.
+*** Tab Bar mode
 The new command 'tab-bar-mode' enables the tab bar at the top of each
 frame, where you can use tabs to switch between named persistent
 window configurations.
@@ -2749,43 +2827,48 @@ fixnum for such arguments.
 
 ---
 ** Some functions and variables obsolete since Emacs 22 have been removed:
-archive-mouse-extract, assoc-ignore-case, assoc-ignore-representation,
-backward-text-line, blink-cursor, bookmark-exit-hooks,
-c-opt-op-identitier-prefix, comint-use-prompt-regexp-instead-of-fields,
-compilation-finish-function, count-text-lines, cperl-vc-header-alist,
-custom-face-save-command, cvs-display-full-path, cvs-fileinfo->full-path,
-delete-frame-hook, derived-mode-class, describe-char-after, describe-project,
-desktop-basefilename, desktop-buffer-handlers, desktop-buffer-misc-functions,
-desktop-buffer-modes-to-save, desktop-enable, desktop-load-default,
-dired-omit-files-p, disabled-command-hook, dungeon-mode-map,
-electric-nroff-mode, electric-nroff-newline, electric-perl-terminator,
-focus-frame, forward-text-line, generic-define-mswindows-modes,
-generic-define-unix-modes, generic-font-lock-defaults, goto-address-at-mouse,
-highlight-changes-colours, ibuffer-elide-long-columns, ibuffer-hooks,
-ibuffer-mode-hooks, icalendar-convert-diary-to-ical,
-icalendar-extract-ical-from-buffer, imenu-always-use-completion-buffer-p,
-ipconfig-program, ipconfig-program-options, isearch-lazy-highlight-cleanup,
-isearch-lazy-highlight-initial-delay, isearch-lazy-highlight-interval,
-isearch-lazy-highlight-max-at-a-time, iswitchb-use-fonts,
-latin1-char-displayable-p, mouse-wheel-click-button, mouse-wheel-down-button,
-mouse-wheel-up-button, new-frame, pascal-outline, process-kill-without-query,
-recentf-menu-append-commands-p, rmail-pop-password,
-rmail-pop-password-required, savehist-load, set-default-font,
-spam-list-of-processors, speedbar-add-ignored-path-regexp,
-speedbar-buffers-line-path, speedbar-ignored-path-expressions,
-speedbar-ignored-path-regexp, speedbar-line-path, speedbar-path-line,
-timer-set-time-with-usecs, tooltip-gud-display, tooltip-gud-modes,
-tooltip-gud-toggle-dereference, unfocus-frame, unload-hook-features-list,
-update-autoloads-from-directories, vc-comment-ring, vc-comment-ring-index,
-vc-comment-search-forward, vc-comment-search-reverse, vc-comment-to-change-log,
-vc-diff-switches-list, vc-next-comment, vc-previous-comment, view-todo,
-x-lost-selection-hooks, x-sent-selection-hooks.
+'archive-mouse-extract', 'assoc-ignore-case', 'assoc-ignore-representation',
+'backward-text-line', 'blink-cursor', 'bookmark-exit-hooks',
+'c-opt-op-identitier-prefix', 'comint-use-prompt-regexp-instead-of-fields',
+'compilation-finish-function', 'count-text-lines', 'cperl-vc-header-alist',
+'custom-face-save-command', 'cvs-display-full-path', 'cvs-fileinfo->full-path',
+'delete-frame-hook', 'derived-mode-class', 'describe-char-after',
+'describe-project', 'desktop-basefilename', 'desktop-buffer-handlers',
+'desktop-buffer-misc-functions', 'desktop-buffer-modes-to-save',
+'desktop-enable', 'desktop-load-default', 'dired-omit-files-p',
+'disabled-command-hook', 'dungeon-mode-map', 'electric-nroff-mode',
+'electric-nroff-newline', 'electric-perl-terminator', 'focus-frame',
+'forward-text-line', 'generic-define-mswindows-modes',
+'generic-define-unix-modes', 'generic-font-lock-defaults',
+'goto-address-at-mouse', 'highlight-changes-colours',
+'ibuffer-elide-long-columns', 'ibuffer-hooks', 'ibuffer-mode-hooks',
+'icalendar-convert-diary-to-ical', 'icalendar-extract-ical-from-buffer',
+'imenu-always-use-completion-buffer-p', 'ipconfig-program',
+'ipconfig-program-options', 'isearch-lazy-highlight-cleanup',
+'isearch-lazy-highlight-initial-delay', 'isearch-lazy-highlight-interval',
+'isearch-lazy-highlight-max-at-a-time', 'iswitchb-use-fonts',
+'latin1-char-displayable-p', 'mouse-wheel-click-button',
+'mouse-wheel-down-button', 'mouse-wheel-up-button', 'new-frame',
+'pascal-outline', 'process-kill-without-query',
+'recentf-menu-append-commands-p', 'rmail-pop-password',
+'rmail-pop-password-required', 'savehist-load', 'set-default-font',
+'spam-list-of-processors', 'speedbar-add-ignored-path-regexp',
+'speedbar-buffers-line-path', 'speedbar-ignored-path-expressions',
+'speedbar-ignored-path-regexp', 'speedbar-line-path', 'speedbar-path-line',
+'timer-set-time-with-usecs', 'tooltip-gud-display', 'tooltip-gud-modes',
+'tooltip-gud-toggle-dereference', 'unfocus-frame', 'unload-hook-features-list',
+'update-autoloads-from-directories', 'vc-comment-ring', 
'vc-comment-ring-index',
+'vc-comment-search-forward', 'vc-comment-search-reverse',
+'vc-comment-to-change-log', 'vc-diff-switches-list', 'vc-next-comment',
+'vc-previous-comment', 'view-todo', 'x-lost-selection-hooks',
+'x-sent-selection-hooks'.
 
 ---
 ** Further functions and variables obsolete since Emacs 24 have been removed:
-default-directory-alist, dired-default-directory,
-dired-default-directory-alist, dired-enable-local-variables,
-dired-hack-local-variables, dired-local-variables-file, dired-omit-here-always.
+'default-directory-alist', 'dired-default-directory',
+'dired-default-directory-alist', 'dired-enable-local-variables',
+'dired-hack-local-variables', 'dired-local-variables-file',
+'dired-omit-here-always'.
 
 +++
 ** Garbage collection no longer treats miscellaneous objects specially;
@@ -2864,6 +2947,20 @@ where it scales the image under the mouse pointer.
 ** 'help-follow-symbol' now signals 'user-error' if point (or the
 position pointed to by the argument POS) is not in a symbol.
 
+---
+** The options.el library has been removed.
+It was obsolete since Emacs 22.1, replaced by customize.
+
+---
+** The tls.el and starttls.el libraries are now marked obsolete.
+Use of built-in libgnutls based functionality (described in the Emacs
+GnuTLS manual) is recommended instead.
+
+---
+** The url-ns.el library is now marked obsolete.
+This library is used to open configuration files for the long defunct
+web browser Netscape, and is no longer relevant.
+
 
 * Lisp Changes in Emacs 27.1
 
@@ -2964,7 +3061,7 @@ years containing more than four digits.  This is for 
compatibility
 with POSIX.1-2017.
 
 +++
-*** To access (or alter) the elements a decoded time value, the
+*** To access (or alter) the elements of a decoded time value, the
 'decoded-time-second', 'decoded-time-minute', 'decoded-time-hour',
 'decoded-time-day', 'decoded-time-month', 'decoded-time-year',
 'decoded-time-weekday', 'decoded-time-dst' and 'decoded-time-zone'
@@ -2983,7 +3080,7 @@ elements as if it's midnight January 1st, 1970) have been 
added.
 if it is not known whether daylight saving time is in effect.
 Formerly they were inconsistent: 'encode-time' returned t in this
 situation, whereas 'parse-time-string' returned nil.  Now they
-consistently use use nil to mean that DST is not in effect, and use -1
+consistently use nil to mean that DST is not in effect, and use -1
 to mean that it is not known whether DST is in effect.
 
 +++
@@ -3062,12 +3159,12 @@ informational messages that look pleasing during the 
Emacs build.
 
 ---
 ** New 'help-fns-describe-variable-functions' hook.
-Makes it possible to add metadata information to 'describe-variable'.
+It makes it possible to add metadata information to 'describe-variable'.
 
 ** i18n (internationalization)
 
 ---
-*** ngettext can be used now to return the right plural form
+*** 'ngettext' can be used now to return the right plural form
 according to the given numeric value.
 
 +++
@@ -3080,7 +3177,7 @@ according to the given numeric value.
 ** 'lookup-key' can take a list of keymaps as argument.
 
 +++
-** 'condition-case' now accepts 't' to match any error symbol.
+** 'condition-case' now accepts t to match any error symbol.
 
 +++
 ** New function 'proper-list-p'.
@@ -3152,7 +3249,7 @@ are unaffected by these changes.
 
 In addition, a number of functions now allow the caller to detect what
 has changed since last redisplay: 'window-old-buffer' returns for any
-window the buffer it showed at that time.  ‘old-selected-window’ and
+window the buffer it showed at that time.  'old-selected-window' and
 'old-selected-frame' return the window and frame that were selected
 during last redisplay.  'window-old-pixel-width' (renamed from
 'window-pixel-width-before-size-change'), 'window-old-pixel-height'
@@ -3173,22 +3270,22 @@ reliably survive subsequent invocations of 
'set-window-buffer'.
 
 +++
 ** New user option 'resize-mini-frames'.
-This option allows to automatically resize minibuffer-only frames
+This option allows automatically resizing minibuffer-only frames
 similarly to how minibuffer windows are resized on "normal" frames.
 
 +++
 ** New buffer display action function 'display-buffer-in-direction'.
-This function allows to specify the location of the window chosen by
+This function allows specifying the location of the window chosen by
 'display-buffer' in various ways.
 
 +++
 ** New buffer display action alist entry 'dedicated'.
-Such an entry allows to specify the dedicated status of a window
+Such an entry allows specifying the dedicated status of a window
 created by 'display-buffer'.
 
 +++
 ** New buffer display action alist entry 'window-min-height'.
-Such an entry allows to specify a minimum height of the window used
+Such an entry allows specifying a minimum height of the window used
 for displaying a buffer.  'display-buffer-below-selected' is the only
 action function to respect it at the moment.
 
@@ -3241,6 +3338,10 @@ versions.
 'forward-comment', 'scan-sexps', and 'forward-sexp' when parsing backward.
 The new variable 'comment-use-syntax-ppss' can be set to nil to recover
 the old behavior if needed.
+This also means that there is no longer any need to precede opening
+brackets at the start of a line inside documentation strings with a
+backslash, although there is no harm in doing so to make the code
+easier to edit with an older Emacs version.
 
 ---
 ** The 'server-name' and 'server-socket-dir' variables are set when a
@@ -3317,36 +3418,6 @@ If the new optional ALLOW-PARTIAL argument is passed, 
then the data
 that was decompressed successfully before failing will be inserted
 into the buffer.
 
-** Mailcap
-
----
-*** The new function 'mailcap-file-name-to-mime-type' has been added.
-It's a simple convenience function for looking up MIME types based on
-file name extensions.
-
----
-*** The default way the list of possible external viewers for MIME
-types is sorted and chosen has changed.  Earlier, the most specific
-viewer was chosen, even if there was a general override in "~/.mailcap".
-For instance, if "/etc/mailcap" has an entry for "image/gif", that one
-will be chosen even if you have an entry for "image/*" in your
-"~/.mailcap" file.  But with the new method, entries from "~/.mailcap"
-overrides all system and Emacs-provided defaults.  To get the old
-method back, set 'mailcap-prefer-mailcap-viewers' to nil.
-
-** URL
-
----
-*** The 'file:' handler no longer looks for "index.html" in
-directories if you ask it for a "file:///dir" URL.  Since this is a
-low-level library, such decisions (if they are to be made at all) are
-left to higher-level functions.
-
----
-** The url-ns.el library is now marked obsolete.
-This library is used to open configuration files for the long defunct
-web browser Netscape, and is no longer relevant.
-
 ** Image mode
 
 ---
@@ -3465,7 +3536,7 @@ case.
 It is a convenient and readable way to specify a regexp that should
 not match anything, and is as fast as any such regexp can be.
 
-++++
++++
 ** New functions to handle the URL variant of base-64 encoding.
 New functions 'base64url-encode-string' and 'base64url-encode-region'
 implement the url-variant of base-64 encoding as defined in RFC4648.
@@ -3479,7 +3550,7 @@ encoding.
 The new third argument is a string put between the number and unit; it
 defaults to the empty string.  The new fourth argument is a string
 representing the unit to use; it defaults to "B" when the second
-argument is 'iec' and the empty string otherwise.  We recomment a
+argument is 'iec' and the empty string otherwise.  We recommend a
 space or non-breaking space as third argument, and "B" as fourth
 argument, circumstances allowing.
 
@@ -3538,7 +3609,7 @@ ordinary keys, function keys and mouse clicks.  This 
allows using them
 in their standard macOS way for composing characters.
 
 ** The special handling of 'frame-title-format' on NS where setting it
-to 't' would enable the macOS proxy icon has been replaced with a
+to t would enable the macOS proxy icon has been replaced with a
 separate variable, 'ns-use-proxy-icon'.  'frame-title-format' will now
 work as on other platforms.
 
diff --git a/etc/PROBLEMS b/etc/PROBLEMS
index 5067b53..4ce738d 100644
--- a/etc/PROBLEMS
+++ b/etc/PROBLEMS
@@ -318,6 +318,83 @@ element from LD_LIBRARY_PATH before starting emacs proper.
 Or you could recompile Emacs with an -Wl,-rpath option that
 gives the location of the correct libotf.
 
+* Problems when reading or debugging Emacs C code
+
+Because Emacs does not install a copy of its C source code, users
+normally cannot easily read that code via commands like 'M-x
+describe-function' (C-h f) that display the definition of a function.
+However, some GNU/Linux systems provide separate packages containing
+this source code which can get C-h f to work if you are willing to do
+some tinkering, and some systems also provide packages containing
+debug info, which when combined with the source can be used to debug
+Emacs at the C level.
+
+** Debian-based source and debuginfo
+
+On recent Debian-based systems, you can obtain and use a source
+package of Emacs as follows.
+
+*** Add the appropriate URI to /etc/apt/sources.list.
+
+To do this, become superuser and uncomment or add the appropriate
+'deb-src' line.  Details depend on the distribution.
+
+*** Execute a command like 'apt-get source emacs'.
+
+On older systems, append the top-level version number, e.g., 'apt-get
+source emacs25'.  The target directory for unpacking the source tree
+is the current directory.
+
+*** Set find-function-C-source-directory accordingly.
+
+Once you have installed the source package, for example at
+/home/myself/deb-src/emacs-26.3, add the following line to your
+startup file:
+
+     (setq find-function-C-source-directory
+           "/home/myself/deb-src/emacs-26.3/src/")
+
+The installation directory of the Emacs source package will contain
+the exact package name and version number of Emacs that is installed
+on your system.  If a new Emacs package is installed, the source
+package must be reinstalled as well, and the setting in your startup
+file must be updated.
+
+*** Debian-based debuginfo
+
+You can also install a debug package of Emacs with a command like
+'apt-get install emacs-dbg' (on older systems, 'apt-get install
+emacs25-dbg').  You need to arrange for GDB to find where you
+installed the source code, e.g., by using GDB's 'directory' command.
+
+** Red Hat-based source and debuginfo
+
+On recent Red Hat-based systems, you can install source and debug info
+via superuser commands like the following:
+
+  # Add the *-debuginfo repositories (exact command depends on system).
+  dnf config-manager --set-enabled fedora-debuginfo updates-debuginfo'
+
+  # Install Emacs source and debug info.
+  dnf install emacs-debugsource
+
+To get describe-function and similar commands to work, you can then
+add something like the following to your startup file:
+
+     (setq find-function-C-source-directory
+           "/usr/src/debug/emacs-26.3-1.fc31.x86_64/src/")
+
+However, the exact directory name will depend on the system, and you
+will need to both upgrade source and debug info when your system
+upgrades or patches Emacs, and change your startup file accordingly.
+
+** Source and debuginfo for other systems
+
+If your system follows neither the Debian nor the Red Hat patterns,
+you can obtain the source and debuginfo by obtaining the source code
+of Emacs, building Emacs with the appropriate debug flags enabled, and
+running the just-built Emacs.
+
 * General runtime problems
 
 ** Lisp problems
@@ -728,6 +805,18 @@ and ps-mule to print Unicode characters.
 
 You may have bad fonts.
 
+** Under X, some characters are unexpectedly wide.
+
+e.g. recent versions of Inconsolata show this issue for almost all of
+its characters.  Due to what is probably an Xft bug, the determination
+of the width of some characters is incorrect.  One workaround is to
+build emacs with Cairo enabled ("configure --with-cairo" and have the
+appropriate Cairo development packages installed) as this
+configuration does not suffer from this problem.  See
+<https://github.com/googlefonts/Inconsolata/issues/42> and
+<https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-01/msg00456.html>
+for more discussion.
+
 ** Under X, an unexpected monospace font is used as the default font.
 
 When compiled with XFT, Emacs tries to use a default font named
diff --git a/etc/TODO b/etc/TODO
index e87fd85..0a06484 100644
--- a/etc/TODO
+++ b/etc/TODO
@@ -384,6 +384,12 @@ specified filters, specified timers, and specified hooks.
 
 ** Install address@hidden's no-flicker change.
 
+  https://lists.gnu.org/archive/html/emacs-devel/2005-12/msg00699.html
+
+  I don't know if this is still relevant.  I can't reach the URLs in
+  the above message thread and double-buffering may have solved some
+  of the problems.
+
 ** Add a "current vertical pixel level" value that goes with point,
   so that motion commands can also move through tall images.
   This value would be to point as window-vscroll is to window-start.
@@ -537,11 +543,6 @@ from the emacsclient process.
 ** Provide an optional feature which computes a scroll bar slider's
   size and its position from lines instead of characters.
 
-** Allow unknown image types to be rendered via an external program
-  converting them to, say, PBM (in the same way as PostScript?). [does
-  doc-view.el do this, or could it be extended to do this?
-  Does ImageMagick obsolete this idea?]
-
 ** Allow displaying an X window from an external program in a buffer,
   e.g. to render graphics from Java applets.  [gerd and/or wmperry
   thought this was feasible.]
@@ -555,6 +556,8 @@ from the emacsclient process.
 
 ** Use the XIE X extension, if available, for image display.
 
+(Obsolete as XIE is now considered obsolete itself.)
+
 ** Make monochrome images display using the foreground and background
   colors of the applicable faces.
 
@@ -679,6 +682,10 @@ simple buttons to webkit (effectively, a web browser).
 Currently, xwidgets works only for the gtk+ framework but it is
 designed to be compatible with multiple Emacs ports.
 
+(See the scratch/nsxwidget branch, and the discussion around
+Objective-C code and GCC at
+https://lists.gnu.org/archive/html/emacs-devel/2019-08/msg00072.html)
+
 **** Respect 'frame-inhibit-implied-resize'
 
 When the variable 'frame-inhibit-implied-resize' is non-nil, frames
@@ -855,32 +862,6 @@ all build versions.
 
 *** Bugs
 
-**** Incorrect translation of Super modifier with Ctrl or Meta on macOS
-
-When pressing 'M-s-a', Emacs replies "M-s-å is undefined".  What
-happened is a mix of Emacs view that Meta and Super has been pressed,
-and macOS view that ALT-a should yield "å" (U+00E5 LATIN SMALL LETTER
-A WITH RING ABOVE).
-
-The bug reports suggest two different patches; unfortunately, neither
-works properly.  For example:
-
-   Use a Swedish keyboard layout
-
-   (setq ns-alternate-modifier nil)
-
-   "CMD-ALT-9"
-
-Today, this correctly yields that s-] is undefined.  With either
-of the two patches, Emacs responds that s-9 was pressed.
-
-More investigation is needed to fix this problem.
-
-Links:
-- https://debbugs.gnu.org/19977
-- https://debbugs.gnu.org/21330
-- https://debbugs.gnu.org/21551
-
 **** Toggling the toolbar in fullheight or maximized modes
 
 The toolbar, in the NS interface, is not considered part of the text
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index 645ff04..204064f 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -924,21 +924,22 @@ open_config (char const *home, char const *xdg, char 
const *config_file)
   char *configname = xmalloc (max (xdgsubdirsize, homesubdirsizemax)
                              + strlen (config_file));
   FILE *config;
-  if (xdg || home)
+
+  if (home)
     {
-      strcpy ((xdg
-              ? stpcpy (stpcpy (configname, xdg), "/emacs/server/")
-              : stpcpy (stpcpy (configname, home), "/.config/emacs/server/")),
-             config_file);
+      strcpy (stpcpy (stpcpy (configname, home), "/.emacs.d/server/"),
+              config_file);
       config = fopen (configname, "rb");
     }
   else
     config = NULL;
 
-  if (! config && home)
+  if (! config && (xdg || home))
     {
-      strcpy (stpcpy (stpcpy (configname, home), "/.emacs.d/server/"),
-             config_file);
+      strcpy ((xdg
+               ? stpcpy (stpcpy (configname, xdg), "/emacs/server/")
+               : stpcpy (stpcpy (configname, home), "/.config/emacs/server/")),
+              config_file);
       config = fopen (configname, "rb");
     }
 
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 951e5b1..1c8085b 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -127,7 +127,6 @@
 #  pipe2 \
 #  pselect \
 #  pthread_sigmask \
-#  putenv \
 #  qcopy-acl \
 #  readlink \
 #  readlinkat \
@@ -316,6 +315,7 @@ GNULIB_GETLINE = @GNULIB_GETLINE@
 GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@
 GNULIB_GETLOGIN = @GNULIB_GETLOGIN@
 GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@
+GNULIB_GETOPT_POSIX = @GNULIB_GETOPT_POSIX@
 GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@
 GNULIB_GETPASS = @GNULIB_GETPASS@
 GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@
@@ -2161,17 +2161,6 @@ EXTRA_libgnu_a_SOURCES += pthread_sigmask.c
 endif
 ## end   gnulib module pthread_sigmask
 
-## begin gnulib module putenv
-ifeq (,$(OMIT_GNULIB_MODULE_putenv))
-
-
-EXTRA_DIST += putenv.c
-
-EXTRA_libgnu_a_SOURCES += putenv.c
-
-endif
-## end   gnulib module putenv
-
 ## begin gnulib module qcopy-acl
 ifeq (,$(OMIT_GNULIB_MODULE_qcopy-acl))
 
@@ -3210,6 +3199,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's/@''GNULIB_GETHOSTNAME''@/$(GNULIB_GETHOSTNAME)/g' \
              -e 's/@''GNULIB_GETLOGIN''@/$(GNULIB_GETLOGIN)/g' \
              -e 's/@''GNULIB_GETLOGIN_R''@/$(GNULIB_GETLOGIN_R)/g' \
+             -e 's/@''GNULIB_GETOPT_POSIX''@/$(GNULIB_GETOPT_POSIX)/g' \
              -e 's/@''GNULIB_GETPAGESIZE''@/$(GNULIB_GETPAGESIZE)/g' \
              -e 's/@''GNULIB_GETPASS''@/$(GNULIB_GETPASS)/g' \
              -e 's/@''GNULIB_GETUSERSHELL''@/$(GNULIB_GETUSERSHELL)/g' \
diff --git a/lib/inttypes.in.h b/lib/inttypes.in.h
index 5184e26..d6efc7e 100644
--- a/lib/inttypes.in.h
+++ b/lib/inttypes.in.h
@@ -38,6 +38,8 @@
 #  endif
 
 #  @INCLUDE_NEXT@ @NEXT_INTTYPES_H@
+
+#  define _GL_FINISHED_INCLUDING_SYSTEM_INTTYPES_H
 # endif
 #endif
 
diff --git a/lib/putenv.c b/lib/putenv.c
deleted file mode 100644
index 9e862e6..0000000
--- a/lib/putenv.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/* Copyright (C) 1991, 1994, 1997-1998, 2000, 2003-2020 Free Software
-   Foundation, Inc.
-
-   NOTE: The canonical source of this file is maintained with the GNU C
-   Library.  Bugs can be reported to address@hidden.
-
-   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 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/>.  */
-
-#include <config.h>
-
-/* Specification.  */
-#include <stdlib.h>
-
-#include <stddef.h>
-
-/* Include errno.h *after* sys/types.h to work around header problems
-   on AIX 3.2.5.  */
-#include <errno.h>
-#ifndef __set_errno
-# define __set_errno(ev) ((errno) = (ev))
-#endif
-
-#include <string.h>
-#include <unistd.h>
-
-#if defined _WIN32 && ! defined __CYGWIN__
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-#endif
-
-#if _LIBC
-# if HAVE_GNU_LD
-#  define environ __environ
-# else
-extern char **environ;
-# endif
-#endif
-
-#if _LIBC
-/* This lock protects against simultaneous modifications of 'environ'.  */
-# include <bits/libc-lock.h>
-__libc_lock_define_initialized (static, envlock)
-# define LOCK   __libc_lock_lock (envlock)
-# define UNLOCK __libc_lock_unlock (envlock)
-#else
-# define LOCK
-# define UNLOCK
-#endif
-
-static int
-_unsetenv (const char *name)
-{
-  size_t len;
-#if !HAVE_DECL__PUTENV
-  char **ep;
-#endif
-
-  if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  len = strlen (name);
-
-#if HAVE_DECL__PUTENV
-  {
-    int putenv_result, putenv_errno;
-    char *name_ = malloc (len + 2);
-    memcpy (name_, name, len);
-    name_[len] = '=';
-    name_[len + 1] = 0;
-    putenv_result = _putenv (name_);
-    putenv_errno = errno;
-    free (name_);
-    __set_errno (putenv_errno);
-    return putenv_result;
-  }
-#else
-
-  LOCK;
-
-  ep = environ;
-  while (*ep != NULL)
-    if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
-      {
-        /* Found it.  Remove this pointer by moving later ones back.  */
-        char **dp = ep;
-
-        do
-          dp[0] = dp[1];
-        while (*dp++);
-        /* Continue the loop in case NAME appears again.  */
-      }
-    else
-      ++ep;
-
-  UNLOCK;
-
-  return 0;
-#endif
-}
-
-
-/* Put STRING, which is of the form "NAME=VALUE", in the environment.
-   If STRING contains no '=', then remove STRING from the environment.  */
-int
-putenv (char *string)
-{
-  const char *name_end = strchr (string, '=');
-  char **ep;
-
-  if (name_end == NULL)
-    {
-      /* Remove the variable from the environment.  */
-      return _unsetenv (string);
-    }
-
-#if HAVE_DECL__PUTENV
-  /* Rely on _putenv to allocate the new environment.  If other
-     parts of the application use _putenv, the !HAVE_DECL__PUTENV code
-     would fight over who owns the environ vector, causing a crash.  */
-  if (name_end[1])
-    return _putenv (string);
-  else
-    {
-      /* _putenv ("NAME=") unsets NAME, so invoke _putenv ("NAME= ")
-         to allocate the environ vector and then replace the new
-         entry with "NAME=".  */
-      int putenv_result, putenv_errno;
-      char *name_x = malloc (name_end - string + sizeof "= ");
-      if (!name_x)
-        return -1;
-      memcpy (name_x, string, name_end - string + 1);
-      name_x[name_end - string + 1] = ' ';
-      name_x[name_end - string + 2] = 0;
-      putenv_result = _putenv (name_x);
-      putenv_errno = errno;
-      for (ep = environ; *ep; ep++)
-        if (strcmp (*ep, name_x) == 0)
-          {
-            *ep = string;
-            break;
-          }
-# if defined _WIN32 && ! defined __CYGWIN__
-      if (putenv_result == 0)
-        {
-          /* _putenv propagated "NAME= " into the subprocess environment;
-             fix that by calling SetEnvironmentVariable directly.  */
-          name_x[name_end - string] = 0;
-          putenv_result = SetEnvironmentVariable (name_x, "") ? 0 : -1;
-          putenv_errno = ENOMEM; /* ENOMEM is the only way to fail.  */
-        }
-# endif
-      free (name_x);
-      __set_errno (putenv_errno);
-      return putenv_result;
-    }
-#else
-  for (ep = environ; *ep; ep++)
-    if (strncmp (*ep, string, name_end - string) == 0
-        && (*ep)[name_end - string] == '=')
-      break;
-
-  if (*ep)
-    *ep = string;
-  else
-    {
-      static char **last_environ = NULL;
-      size_t size = ep - environ;
-      char **new_environ = malloc ((size + 2) * sizeof *new_environ);
-      if (! new_environ)
-        return -1;
-      new_environ[0] = string;
-      memcpy (new_environ + 1, environ, (size + 1) * sizeof *new_environ);
-      free (last_environ);
-      last_environ = new_environ;
-      environ = new_environ;
-    }
-
-  return 0;
-#endif
-}
diff --git a/lib/regex.c b/lib/regex.c
index 6bdd77f..88173bb 100644
--- a/lib/regex.c
+++ b/lib/regex.c
@@ -17,6 +17,8 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
+#define __STDC_WANT_IEC_60559_BFP_EXT__
+
 #ifndef _LIBC
 # include <libc-config.h>
 
diff --git a/lib/regex_internal.h b/lib/regex_internal.h
index 5c9cbf3..f6ebfb0 100644
--- a/lib/regex_internal.h
+++ b/lib/regex_internal.h
@@ -141,6 +141,24 @@
 #ifndef SSIZE_MAX
 # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
 #endif
+#ifndef ULONG_WIDTH
+# define ULONG_WIDTH REGEX_UINTEGER_WIDTH (ULONG_MAX)
+/* The number of usable bits in an unsigned integer type with maximum
+   value MAX, as an int expression suitable in #if.  Cover all known
+   practical hosts.  This implementation exploits the fact that MAX is
+   1 less than a power of 2, and merely counts the number of 1 bits in
+   MAX; "COBn" means "count the number of 1 bits in the low-order n bits".  */
+# define REGEX_UINTEGER_WIDTH(max) REGEX_COB128 (max)
+# define REGEX_COB128(n) (REGEX_COB64 ((n) >> 31 >> 31 >> 2) + REGEX_COB64 (n))
+# define REGEX_COB64(n) (REGEX_COB32 ((n) >> 31 >> 1) + REGEX_COB32 (n))
+# define REGEX_COB32(n) (REGEX_COB16 ((n) >> 16) + REGEX_COB16 (n))
+# define REGEX_COB16(n) (REGEX_COB8 ((n) >> 8) + REGEX_COB8 (n))
+# define REGEX_COB8(n) (REGEX_COB4 ((n) >> 4) + REGEX_COB4 (n))
+# define REGEX_COB4(n) (!!((n) & 8) + !!((n) & 4) + !!((n) & 2) + ((n) & 1))
+# if ULONG_MAX / 2 + 1 != 1ul << (ULONG_WIDTH - 1)
+#  error "ULONG_MAX out of range"
+# endif
+#endif
 
 /* The type of indexes into strings.  This is signed, not size_t,
    since the API requires indexes to fit in regoff_t anyway, and using
@@ -164,36 +182,8 @@ typedef __re_size_t re_hashval_t;
 typedef unsigned long int bitset_word_t;
 /* All bits set in a bitset_word_t.  */
 #define BITSET_WORD_MAX ULONG_MAX
-
-/* Number of bits in a bitset_word_t.  For portability to hosts with
-   padding bits, do not use '(sizeof (bitset_word_t) * CHAR_BIT)';
-   instead, deduce it directly from BITSET_WORD_MAX.  Avoid
-   greater-than-32-bit integers and unconditional shifts by more than
-   31 bits, as they're not portable.  */
-#if BITSET_WORD_MAX == 0xffffffffUL
-# define BITSET_WORD_BITS 32
-#elif BITSET_WORD_MAX >> 31 >> 4 == 1
-# define BITSET_WORD_BITS 36
-#elif BITSET_WORD_MAX >> 31 >> 16 == 1
-# define BITSET_WORD_BITS 48
-#elif BITSET_WORD_MAX >> 31 >> 28 == 1
-# define BITSET_WORD_BITS 60
-#elif BITSET_WORD_MAX >> 31 >> 31 >> 1 == 1
-# define BITSET_WORD_BITS 64
-#elif BITSET_WORD_MAX >> 31 >> 31 >> 9 == 1
-# define BITSET_WORD_BITS 72
-#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 3 == 1
-# define BITSET_WORD_BITS 128
-#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 == 1
-# define BITSET_WORD_BITS 256
-#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 > 1
-# define BITSET_WORD_BITS 257 /* any value > SBC_MAX will do here */
-# if BITSET_WORD_BITS <= SBC_MAX
-#  error "Invalid SBC_MAX"
-# endif
-#else
-# error "Add case for new bitset_word_t size"
-#endif
+/* Number of bits in a bitset_word_t.  */
+#define BITSET_WORD_BITS ULONG_WIDTH
 
 /* Number of bitset_word_t values in a bitset_t.  */
 #define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
@@ -601,9 +591,8 @@ struct re_backref_cache_entry
   Idx str_idx;
   Idx subexp_from;
   Idx subexp_to;
+  bitset_word_t eps_reachable_subexps_map;
   char more;
-  char unused;
-  unsigned short int eps_reachable_subexps_map;
 };
 
 typedef struct
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index e088959..49bbf6f 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -201,6 +201,10 @@ _GL_FUNCDECL_SYS (canonicalize_file_name, char *, (const 
char *name)
 #  endif
 _GL_CXXALIAS_SYS (canonicalize_file_name, char *, (const char *name));
 # endif
+# ifndef GNULIB_defined_canonicalize_file_name
+#  define GNULIB_defined_canonicalize_file_name \
+     (!@HAVE_CANONICALIZE_FILE_NAME@ || @REPLACE_CANONICALIZE_FILE_NAME@)
+# endif
 _GL_CXXALIASWARN (canonicalize_file_name);
 #elif defined GNULIB_POSIXCHECK
 # undef canonicalize_file_name
@@ -516,6 +520,9 @@ _GL_FUNCDECL_SYS (ptsname_r, int, (int fd, char *buf, 
size_t len));
 #  endif
 _GL_CXXALIAS_SYS (ptsname_r, int, (int fd, char *buf, size_t len));
 # endif
+# ifndef GNULIB_defined_ptsname_r
+#  define GNULIB_defined_ptsname_r (!@HAVE_PTSNAME_R@ || @REPLACE_PTSNAME_R@)
+# endif
 _GL_CXXALIASWARN (ptsname_r);
 #elif defined GNULIB_POSIXCHECK
 # undef ptsname_r
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 7909416..d6176ad 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -141,7 +141,7 @@
 
 
 /* Get getopt(), optarg, optind, opterr, optopt.  */
-#if @GNULIB_UNISTD_H_GETOPT@ && !defined _GL_SYSTEM_GETOPT
+#if @GNULIB_GETOPT_POSIX@ && @GNULIB_UNISTD_H_GETOPT@ && !defined 
_GL_SYSTEM_GETOPT
 # include <getopt-cdefs.h>
 # include <getopt-pfx-core.h>
 #endif
diff --git a/lisp/align.el b/lisp/align.el
index 2c5492f..f16cb84 100644
--- a/lisp/align.el
+++ b/lisp/align.el
@@ -129,6 +129,8 @@
   "Hook that gets run after the aligner has been loaded."
   :type 'hook
   :group 'align)
+(make-obsolete-variable 'align-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defcustom align-indent-before-aligning nil
   "If non-nil, indent the marked region before aligning it."
diff --git a/lisp/allout.el b/lisp/allout.el
index 56f7487..408a2a9 100644
--- a/lisp/allout.el
+++ b/lisp/allout.el
@@ -1675,10 +1675,8 @@ valid values."
   ;; least in emacs 21, 22.1, and xemacs 21.4.
   (put 'allout-exposure-category 'isearch-open-invisible
        'allout-isearch-end-handler)
-  (if (featurep 'xemacs)
-      (put 'allout-exposure-category 'start-open t)
-    (put 'allout-exposure-category 'insert-in-front-hooks
-         '(allout-overlay-insert-in-front-handler)))
+  (put 'allout-exposure-category 'insert-in-front-hooks
+       '(allout-overlay-insert-in-front-handler))
   (put 'allout-exposure-category 'modification-hooks
        '(allout-overlay-interior-modification-handler)))
 ;;;_  > define-minor-mode allout-mode
@@ -2115,9 +2113,7 @@ internal functions use this feature cohesively bunch 
changes."
                               (allout-show-to-offshoot)))
           (when (not first)
             (setq first (point))))
-        (goto-char (if (featurep 'xemacs)
-                       (next-property-change (1+ (point)) nil end)
-                     (next-char-property-change (1+ (point)) end))))
+        (goto-char (next-char-property-change (1+ (point)) end)))
       (when first
         (goto-char first)
         (condition-case nil
@@ -2141,18 +2137,7 @@ See `allout-overlay-interior-modification-handler' for 
details."
   (when (and (allout-mode-p) undo-in-progress)
     (setq allout-just-did-undo t)
     (if (allout-hidden-p)
-        (allout-show-children)))
-
-  ;; allout-overlay-interior-modification-handler on an overlay handles
-  ;; this in other emacs, via `allout-exposure-category's 'modification-hooks.
-  (when (and (featurep 'xemacs) (allout-mode-p))
-    ;; process all of the pending overlays:
-    (save-excursion
-      (goto-char beg)
-      (let ((overlay (allout-get-invisibility-overlay)))
-        (if overlay
-            (allout-overlay-interior-modification-handler
-             overlay nil beg end nil))))))
+        (allout-show-children))))
 ;;;_  > allout-isearch-end-handler (&optional overlay)
 (defun allout-isearch-end-handler (&optional _overlay)
   "Reconcile allout outline exposure on arriving in hidden text after isearch.
@@ -2453,7 +2438,7 @@ Outermost is first."
       (progn
         (if (and (not (bolp))
                  (allout-hidden-p (1- (point))))
-            (goto-char (allout-previous-single-char-property-change
+            (goto-char (previous-single-char-property-change
                         (1- (point)) 'invisible)))
         (move-beginning-of-line 1))
     (allout-depth)
@@ -3443,7 +3428,7 @@ Offer one suitable for current depth DEPTH as default."
                     (format-message
                      "Select bullet: %s (`%s' default): "
                      sans-escapes
-                     (allout-substring-no-properties default-bullet))
+                     (substring-no-properties default-bullet))
                     sans-escapes
                     t)))
     (message "")
@@ -4458,9 +4443,9 @@ Topic exposure is marked with text-properties, to be used 
by
           (if (not (allout-hidden-p))
               (setq next
                     (max (1+ (point))
-                         (allout-next-single-char-property-change (point)
-                                                                  'invisible
-                                                                  nil end))))
+                         (next-single-char-property-change (point)
+                                                           'invisible
+                                                           nil end))))
           (if (or (not next) (eq prev next))
               ;; still not at start of hidden area -- must not be any left.
               (setq done t)
@@ -4499,7 +4484,7 @@ Topic exposure is marked with text-properties, to be used 
by
       (while (not done)
         ;; at or advance to start of next annotation:
         (if (not (get-text-property (point) 'allout-was-hidden))
-            (setq next (allout-next-single-char-property-change
+            (setq next (next-single-char-property-change
                         (point) 'allout-was-hidden nil end)))
         (if (or (not next) (eq prev next))
             ;; no more or not advancing -- must not be any left.
@@ -4510,7 +4495,7 @@ Topic exposure is marked with text-properties, to be used 
by
               ;; still not at start of annotation.
               (setq done t)
             ;; advance to just after end of this annotation:
-            (setq next (allout-next-single-char-property-change
+            (setq next (next-single-char-property-change
                         (point) 'allout-was-hidden nil end))
             (let ((o (make-overlay prev next nil 'front-advance)))
               (overlay-put o 'category 'allout-exposure-category)
@@ -4543,12 +4528,12 @@ however, are left exactly like normal, 
non-allout-specific yanks."
   (interactive "*P")
                                        ; Get to beginning, leaving
                                        ; region around subject:
-  (if (< (allout-mark-marker t) (point))
+  (if (< (mark-marker) (point))
       (exchange-point-and-mark))
   (save-match-data
     (let* ((subj-beg (point))
            (into-bol (bolp))
-           (subj-end (allout-mark-marker t))
+           (subj-end (mark-marker))
            ;; 'resituate' if yanking an entire topic into topic header:
            (resituate (and (let ((allout-inhibit-aberrance-doublecheck t))
                              (allout-e-o-prefix-p))
@@ -4642,8 +4627,8 @@ however, are left exactly like normal, 
non-allout-specific yanks."
                                             t)))
               (message ""))))
       (if (or into-bol resituate)
-          (allout-hide-by-annotation (point) (allout-mark-marker t))
-        (allout-deannotate-hidden (allout-mark-marker t) (point)))
+          (allout-hide-by-annotation (point) (mark-marker))
+        (allout-deannotate-hidden (mark-marker) (point)))
       (if (not resituate)
           (exchange-point-and-mark))
       (run-hook-with-args 'allout-structure-added-functions subj-beg 
subj-end))))
@@ -4752,14 +4737,7 @@ this function."
   (when flag
     (let ((o (make-overlay from to nil 'front-advance)))
       (overlay-put o 'category 'allout-exposure-category)
-      (overlay-put o 'evaporate t)
-      (when (featurep 'xemacs)
-        (let ((props (symbol-plist 'allout-exposure-category)))
-          (while props
-            (condition-case nil
-                ;; as of 2008-02-27, xemacs lacks modification-hooks
-                (overlay-put o (pop props) (pop props))
-              (error nil))))))
+      (overlay-put o 'evaporate t))
     (setq allout-this-command-hid-text t))
   (run-hook-with-args 'allout-exposure-change-functions from to flag))
 ;;;_   > allout-flag-current-subtree (flag)
@@ -5946,7 +5924,7 @@ See `allout-toggle-current-subtree-encryption' for more 
details."
         ;; they're encrypted, so the coding system is set to accommodate
         ;; them.
         (setq buffer-file-coding-system
-              (allout-select-safe-coding-system subtree-beg subtree-end))
+              (select-safe-coding-system subtree-beg subtree-end))
         ;; if the coding system for the text being encrypted is different
         ;; than that prevailing, then there a real risk that the coding
         ;; system can't be noticed by emacs when the file is visited.  to
@@ -6542,204 +6520,15 @@ If BEG is bigger than END we return 0."
          (mapcar (lambda (char) (if (= char ?%) "%%" (char-to-string char)))
                  string)))
 (define-obsolete-function-alias 'allout-flatten #'flatten-tree "27.1")
-;;;_  : Compatibility:
-;;;_   : xemacs undo-in-progress provision:
-(unless (boundp 'undo-in-progress)
-  (defvar undo-in-progress nil
-    "Placeholder defvar for XEmacs compatibility from allout.el.")
-  (defadvice undo-more (around allout activate)
-    ;; This defadvice used only in emacs that lack undo-in-progress, eg xemacs.
-    (let ((undo-in-progress t)) ad-do-it)))
-
-;;;_   > allout-mark-marker to accommodate divergent emacsen:
-(defun allout-mark-marker (&optional force buffer)
-  "Accommodate the different signature for `mark-marker' across Emacsen.
-
-XEmacs takes two optional args, while Emacs does not,
-so pass them along when appropriate."
-  (if (featurep 'xemacs)
-      (apply 'mark-marker force buffer)
-    (mark-marker)))
-;;;_   > subst-char-in-string if necessary
-(if (not (fboundp 'subst-char-in-string))
-    (defun subst-char-in-string (fromchar tochar string &optional inplace)
-      "Replace FROMCHAR with TOCHAR in STRING each time it occurs.
-Unless optional argument INPLACE is non-nil, return a new string."
-      (let ((i (length string))
-            (newstr (if inplace string (copy-sequence string))))
-        (while (> i 0)
-          (setq i (1- i))
-          (if (eq (aref newstr i) fromchar)
-              (aset newstr i tochar)))
-        newstr)))
-;;;_   > wholenump if necessary
-(if (not (fboundp 'wholenump))
-    (defalias 'wholenump 'natnump))
-;;;_   > remove-overlays if necessary
-(if (not (fboundp 'remove-overlays))
-    (defun remove-overlays (&optional beg end name val)
-      "Clear BEG and END of overlays whose property NAME has value VAL.
-Overlays might be moved and/or split.
-BEG and END default respectively to the beginning and end of buffer."
-      (unless beg (setq beg (point-min)))
-      (unless end (setq end (point-max)))
-      (if (< end beg)
-          (setq beg (prog1 end (setq end beg))))
-      (save-excursion
-        (dolist (o (overlays-in beg end))
-          (when (eq (overlay-get o name) val)
-            ;; Either push this overlay outside beg...end
-            ;; or split it to exclude beg...end
-            ;; or delete it entirely (if it is contained in beg...end).
-            (if (< (overlay-start o) beg)
-                (if (> (overlay-end o) end)
-                    (progn
-                      (move-overlay (copy-overlay o)
-                                    (overlay-start o) beg)
-                      (move-overlay o end (overlay-end o)))
-                  (move-overlay o (overlay-start o) beg))
-              (if (> (overlay-end o) end)
-                  (move-overlay o end (overlay-end o))
-                (delete-overlay o)))))))
-  )
-;;;_   > copy-overlay if necessary -- xemacs ~ 21.4
-(if (not (fboundp 'copy-overlay))
-    (defun copy-overlay (o)
-      "Return a copy of overlay O."
-      (let ((o1 (make-overlay (overlay-start o) (overlay-end o)
-                              ;; FIXME: there's no easy way to find the
-                              ;; insertion-type of the two markers.
-                              (overlay-buffer o)))
-            (props (overlay-properties o)))
-        (while props
-          (overlay-put o1 (pop props) (pop props)))
-        o1)))
-;;;_   > add-to-invisibility-spec if necessary -- xemacs ~ 21.4
-(if (not (fboundp 'add-to-invisibility-spec))
-    (defun add-to-invisibility-spec (element)
-      "Add ELEMENT to `buffer-invisibility-spec'.
-See documentation for `buffer-invisibility-spec' for the kind of elements
-that can be added."
-      (if (eq buffer-invisibility-spec t)
-          (setq buffer-invisibility-spec (list t)))
-      (setq buffer-invisibility-spec
-            (cons element buffer-invisibility-spec))))
-;;;_   > remove-from-invisibility-spec if necessary -- xemacs ~ 21.4
-(if (not (fboundp 'remove-from-invisibility-spec))
-    (defun remove-from-invisibility-spec (element)
-      "Remove ELEMENT from `buffer-invisibility-spec'."
-      (if (consp buffer-invisibility-spec)
-          (setq buffer-invisibility-spec (delete element
-                                                 buffer-invisibility-spec)))))
-;;;_   > move-beginning-of-line if necessary -- older emacs, xemacs
-(if (not (fboundp 'move-beginning-of-line))
-    (defun move-beginning-of-line (arg)
-      "Move point to beginning of current line as displayed.
-\(This disregards invisible newlines such as those
-which are part of the text that an image rests on.)
-
-With argument ARG not nil or 1, move forward ARG - 1 lines first.
-If point reaches the beginning or end of buffer, it stops there.
-To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
-      (interactive "p")
-      (or arg (setq arg 1))
-      (if (/= arg 1)
-          (condition-case nil (line-move (1- arg)) (error nil)))
-
-      ;; Move to beginning-of-line, ignoring fields and invisible text.
-      (skip-chars-backward "^\n")
-      (while (and (not (bobp))
-                  (let ((prop
-                          (get-char-property (1- (point)) 'invisible)))
-                    (if (eq buffer-invisibility-spec t)
-                        prop
-                      (or (memq prop buffer-invisibility-spec)
-                          (assq prop buffer-invisibility-spec)))))
-        (goto-char (if (featurep 'xemacs)
-                       (previous-property-change (point))
-                     (previous-char-property-change (point))))
-        (skip-chars-backward "^\n"))
-      (vertical-motion 0))
-)
-;;;_   > move-end-of-line if necessary -- Emacs < 22.1, xemacs
-(if (not (fboundp 'move-end-of-line))
-    (defun move-end-of-line (arg)
-      "Move point to end of current line as displayed.
-\(This disregards invisible newlines such as those
-which are part of the text that an image rests on.)
-
-With argument ARG not nil or 1, move forward ARG - 1 lines first.
-If point reaches the beginning or end of buffer, it stops there.
-To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
-      (interactive "p")
-      (or arg (setq arg 1))
-      (let (done)
-        (while (not done)
-          (let ((newpos
-                 (save-excursion
-                   (let ((goal-column 0))
-                     (and (condition-case nil
-                              (or (line-move arg) t)
-                            (error nil))
-                          (not (bobp))
-                          (progn
-                            (while
-                                (and
-                                 (not (bobp))
-                                 (let ((prop
-                                        (get-char-property (1- (point))
-                                                           'invisible)))
-                                   (if (eq buffer-invisibility-spec t)
-                                       prop
-                                     (or (memq prop
-                                               buffer-invisibility-spec)
-                                         (assq prop
-                                               buffer-invisibility-spec)))))
-                              (goto-char
-                               (previous-char-property-change (point))))
-                            (backward-char 1)))
-                     (point)))))
-            (goto-char newpos)
-            (if (and (> (point) newpos)
-                     (eq (preceding-char) ?\n))
-                (backward-char 1)
-              (if (and (> (point) newpos) (not (eobp))
-                       (not (eq (following-char) ?\n)))
-                  ;; If we skipped something intangible
-                  ;; and now we're not really at eol,
-                  ;; keep going.
-                  (setq arg 1)
-                (setq done t)))))))
-  )
-;;;_   > allout-next-single-char-property-change -- alias unless lacking
-(defalias 'allout-next-single-char-property-change
-  (if (fboundp 'next-single-char-property-change)
-      'next-single-char-property-change
-    'next-single-property-change)
-  ;; No docstring because xemacs defalias doesn't support it.
-  )
-;;;_   > allout-previous-single-char-property-change -- alias unless lacking
-(defalias 'allout-previous-single-char-property-change
-  (if (fboundp 'previous-single-char-property-change)
-      'previous-single-char-property-change
-    'previous-single-property-change)
-  ;; No docstring because xemacs defalias doesn't support it.
-  )
-;;;_   > allout-select-safe-coding-system
-(defalias 'allout-select-safe-coding-system
-  (if (fboundp 'select-safe-coding-system)
-      'select-safe-coding-system
-    'detect-coding-region)
- )
-;;;_   > allout-substring-no-properties
-;; define as alias first, so byte compiler is happy.
-(defalias 'allout-substring-no-properties 'substring-no-properties)
-;; then supplant with definition if underlying alias absent.
-(if (not (fboundp 'substring-no-properties))
-  (defun allout-substring-no-properties (string &optional start end)
-    (substring string (or start 0) end))
-  )
-
+(define-obsolete-function-alias 'allout-mark-marker #'mark-marker "28.1")
+(define-obsolete-function-alias 'allout-substring-no-properties
+  #'substring-no-properties "28.1")
+(define-obsolete-function-alias 'allout-select-safe-coding-system
+  #'select-safe-coding-system "28.1")
+(define-obsolete-function-alias 'allout-previous-single-char-property-change
+  #'previous-single-char-property-change "28.1")
+(define-obsolete-function-alias 'allout-next-single-char-property-change
+  #'next-single-char-property-change "28.1")
 ;;;_ #10 Unfinished
 ;;;_  > allout-bullet-isearch (&optional bullet)
 (defun allout-bullet-isearch (&optional bullet)
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index d6e85bf..677483e 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -1797,8 +1797,7 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
         (maxlen 8)
        (totalsize 0)
         files
-       visual
-        emacs-int-has-32bits)
+       visual)
     (when (= p -1)
       ;; If the offset of end-of-central-directory is -1, this is a
       ;; Zip64 extended ZIP file format, and we need to glean the info
diff --git a/lisp/autorevert.el b/lisp/autorevert.el
index 7503fcc..e023c8f 100644
--- a/lisp/autorevert.el
+++ b/lisp/autorevert.el
@@ -242,6 +242,8 @@ For more information, see Info node `(emacs)Autorevert'."
   :tag "Load Hook"
   :group 'auto-revert
   :type 'hook)
+(make-obsolete-variable 'auto-revert-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defcustom auto-revert-check-vc-info nil
   "If non-nil Auto-Revert Mode reliably updates version control info.
@@ -733,8 +735,8 @@ system.")
                      (null buffer-file-name))
                 (auto-revert-notify-rm-watch)
                 ;; Restart the timer if it wasn't running.
-                (unless auto-revert-timer)
-                  (auto-revert-set-timer))))
+                (unless auto-revert-timer
+                  (auto-revert-set-timer)))))
 
         ;; Loop over all buffers, in order to find the intended one.
         (cl-dolist (buffer buffers)
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index 6cd624c..720ad18 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -2321,6 +2321,8 @@ strings returned are not."
 ;; Load Hook
 (defvar bookmark-load-hook nil
   "Hook run at the end of loading library `bookmark.el'.")
+(make-obsolete-variable 'bookmark-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 ;; Exit Hook, called from kill-emacs-hook
 (defvar bookmark-exit-hook nil
diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el
index d299c5b..4b2a938 100644
--- a/lisp/calc/calc.el
+++ b/lisp/calc/calc.el
@@ -884,6 +884,8 @@ Used by `calc-user-invocation'.")
 
 (defvar calc-load-hook nil
   "Hook run when calc.el is loaded.")
+(make-obsolete-variable 'calc-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defvar calc-window-hook nil
   "Hook called to create the Calc window.")
@@ -2288,7 +2290,7 @@ the United States."
        (calc-alg-digit-entry)
      (setq calc-aborted-prefix nil)
      (let* ((calc-digit-value nil)
-           (calc-prev-char nil)
+           (calc-prev-char last-command-event)
            (calc-prev-prev-char nil)
            (calc-buffer (current-buffer))
            (buf
diff --git a/lisp/calendar/iso8601.el b/lisp/calendar/iso8601.el
index ae1dab1..906c29b 100644
--- a/lisp/calendar/iso8601.el
+++ b/lisp/calendar/iso8601.el
@@ -69,6 +69,8 @@
   "\\([+-]?[0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)")
 (defconst iso8601--outdated-date-match
   "--\\([0-9][0-9]\\)-?\\([0-9][0-9]\\)")
+(defconst iso8601--outdated-reduced-precision-date-match
+  "---?\\([0-9][0-9]\\)")
 (defconst iso8601--week-date-match
   "\\([+-]?[0-9][0-9][0-9][0-9]\\)-?W\\([0-9][0-9]\\)-?\\([0-9]\\)?")
 (defconst iso8601--ordinal-date-match
@@ -79,6 +81,7 @@
          iso8601--full-date-match
          iso8601--without-day-match
          iso8601--outdated-date-match
+         iso8601--outdated-reduced-precision-date-match
          iso8601--week-date-match
          iso8601--ordinal-date-match)))
 
@@ -136,7 +139,8 @@ See `decode-time' for the meaning of FORM."
       (when zone-string
         (setf (decoded-time-zone date)
               ;; The time zone in decoded times are in seconds.
-              (* (iso8601-parse-zone zone-string) 60)))
+             (* (iso8601-parse-zone zone-string) 60))
+       (setf (decoded-time-dst date) nil))
       date)))
 
 (defun iso8601-parse-date (string)
@@ -201,6 +205,12 @@ See `decode-time' for the meaning of FORM."
       (iso8601--decoded-time :year year
                              :month (decoded-time-month month-day)
                              :day (decoded-time-day month-day))))
+   ;; Obsolete format with implied year: --MM
+   ((iso8601--match "--\\([0-9][0-9]\\)" string)
+    (iso8601--decoded-time :month (string-to-number (match-string 1 string))))
+   ;; Obsolete format with implied year and month: ---DD
+   ((iso8601--match "---\\([0-9][0-9]\\)" string)
+    (iso8601--decoded-time :day (string-to-number (match-string 1 string))))
    (t
     (signal 'wrong-type-argument string))))
 
@@ -332,6 +342,9 @@ Return the number of minutes."
     (list start end
           (or duration
              ;; FIXME: Support subseconds.
+             ;; FIXME: It makes no sense to decode a time difference
+             ;; according to (decoded-time-zone end), or according to
+             ;; any other time zone for that matter.
               (decode-time (time-subtract (iso8601--encode-time end)
                                           (iso8601--encode-time start))
                           (or (decoded-time-zone end) 0) 'integer)))))
@@ -354,7 +367,7 @@ Return the number of minutes."
         (iso8601--value month)
         (iso8601--value year)
         nil
-        dst
+       (if (or dst zone) dst -1)
         zone))
 
 (defun iso8601--encode-time (time)
diff --git a/lisp/calendar/lunar.el b/lisp/calendar/lunar.el
index 616d2b0..3d5a0a2 100644
--- a/lisp/calendar/lunar.el
+++ b/lisp/calendar/lunar.el
@@ -91,6 +91,7 @@ remainder mod 4 gives the phase: 0 new moon, 1 first quarter, 
2 full moon,
                        (* -0.0016528 time time)
                        (* -0.00000239 time time time))
                     360.0))
+        (eclipse (eclipse-check moon-lat phase))
          (adjustment
           (if (memq phase '(0 2))
               (+ (* (- 0.1734 (* 0.000393 time))
@@ -146,7 +147,26 @@ remainder mod 4 gives the phase: 0 new moon, 1 first 
quarter, 2 full moon,
          (time (* 24 (- date (truncate date))))
          (date (calendar-gregorian-from-absolute (truncate date)))
          (adj (dst-adjust-time date time)))
-    (list (car adj) (apply 'solar-time-string (cdr adj)) phase)))
+    (list (car adj) (apply 'solar-time-string (cdr adj)) phase eclipse)))
+
+;; from "Astronomy with your Personal Computer", Subroutine Eclipse
+;; Line 7000 Peter Duffett-Smith Cambridge University Press 1990
+(defun eclipse-check (moon-lat phase)
+  (let* ((moon-lat (* (/ float-pi 180) moon-lat))
+         (moon-lat (abs (- moon-lat (* (floor (/ moon-lat float-pi))
+                                       float-pi))))
+         (moon-lat (if (> moon-lat 0.37)
+                       (- float-pi moon-lat)
+                     moon-lat))
+         (phase-name (cond ((= phase 0) "Solar")
+                           ((= phase 2) "Lunar")
+                           (t ""))))
+    (cond ((< moon-lat 2.42600766e-1)
+          (concat "** " phase-name " Eclipse **"))
+         ((< moon-lat 0.37)
+          (concat "** " phase-name " Eclipse possible **"))
+         (t
+          ""))))
 
 (defconst lunar-cycles-per-year 12.3685 ; 365.25/29.530588853
   "Mean number of lunar cycles per 365.25 day year.")
@@ -222,9 +242,10 @@ use instead of point."
         (insert
          (mapconcat
           (lambda (x)
-            (format "%s: %s %s" (calendar-date-string (car x))
+            (format "%s: %s %s %s" (calendar-date-string (car x))
                     (lunar-phase-name (nth 2 x))
-                    (cadr x)))
+                    (cadr x)
+                   (car (last x))))
           (lunar-phase-list m1 y1) "\n")))
       (message "Computing phases of the moon...done"))))
 
diff --git a/lisp/calendar/parse-time.el b/lisp/calendar/parse-time.el
index 7110a81..b199fca 100644
--- a/lisp/calendar/parse-time.el
+++ b/lisp/calendar/parse-time.el
@@ -149,62 +149,62 @@ letters, digits, plus or minus signs or colons."
 ;;;###autoload
 (defun parse-time-string (string)
   "Parse the time in STRING into (SEC MIN HOUR DAY MON YEAR DOW DST TZ).
-STRING should be something resembling an RFC 822 (or later) date-time, e.g.,
-\"Fri, 25 Mar 2016 16:24:56 +0100\", but this function is
+STRING should be an ISO 8601 time string, e.g., \"2020-01-15T16:12:21-08:00\",
+or something resembling an RFC 822 (or later) date-time, e.g.,
+\"Wed, 15 Jan 2020 16:12:21 -0800\".  This function is
 somewhat liberal in what format it accepts, and will attempt to
 return a \"likely\" value even for somewhat malformed strings.
 The values returned are identical to those of `decode-time', but
 any unknown values other than DST are returned as nil, and an
 unknown DST value is returned as -1."
-  (let ((time (list nil nil nil nil nil nil nil -1 nil))
-       (temp (parse-time-tokenize (downcase string))))
-    (while temp
-      (let ((parse-time-elt (pop temp))
-           (rules parse-time-rules)
-           (exit nil))
-       (while (and rules (not exit))
-         (let* ((rule (pop rules))
-                (slots (pop rule))
-                (predicate (pop rule))
-                (parse-time-val))
-           (when (and (not (nth (car slots) time)) ;not already set
-                      (setq parse-time-val
-                            (cond ((and (consp predicate)
-                                        (not (functionp predicate)))
-                                   (and (numberp parse-time-elt)
-                                        (<= (car predicate) parse-time-elt)
-                                        (or (not (cdr predicate))
-                                            (<= parse-time-elt
-                                                (cadr predicate)))
-                                        parse-time-elt))
-                                  ((symbolp predicate)
-                                   (cdr (assoc parse-time-elt
-                                               (symbol-value predicate))))
-                                  ((funcall predicate)))))
-             (setq exit t)
-             (while slots
-               (let ((new-val (if rule
-                                  (let ((this (pop rule)))
-                                    (if (vectorp this)
-                                        (cl-parse-integer
-                                         parse-time-elt
-                                         :start (aref this 0)
-                                         :end (aref this 1))
-                                      (funcall this)))
-                                parse-time-val)))
-                 (setf (nth (pop slots) time) new-val))))))))
-    time))
+  (condition-case ()
+      (iso8601-parse string)
+    (wrong-type-argument
+     (let ((time (list nil nil nil nil nil nil nil -1 nil))
+          (temp (parse-time-tokenize (downcase string))))
+       (while temp
+        (let ((parse-time-elt (pop temp))
+              (rules parse-time-rules)
+              (exit nil))
+          (while (and rules (not exit))
+            (let* ((rule (pop rules))
+                   (slots (pop rule))
+                   (predicate (pop rule))
+                   (parse-time-val))
+              (when (and (not (nth (car slots) time)) ;not already set
+                         (setq parse-time-val
+                               (cond ((and (consp predicate)
+                                           (not (functionp predicate)))
+                                      (and (numberp parse-time-elt)
+                                           (<= (car predicate) parse-time-elt)
+                                           (or (not (cdr predicate))
+                                               (<= parse-time-elt
+                                                   (cadr predicate)))
+                                           parse-time-elt))
+                                     ((symbolp predicate)
+                                      (cdr (assoc parse-time-elt
+                                                  (symbol-value predicate))))
+                                     ((funcall predicate)))))
+                (setq exit t)
+                (while slots
+                  (let ((new-val (if rule
+                                     (let ((this (pop rule)))
+                                       (if (vectorp this)
+                                           (cl-parse-integer
+                                            parse-time-elt
+                                            :start (aref this 0)
+                                            :end (aref this 1))
+                                         (funcall this)))
+                                   parse-time-val)))
+                    (setf (nth (pop slots) time) new-val))))))))
+       time))))
 
 (defun parse-iso8601-time-string (date-string)
-  "Parse an ISO 8601 time string, such as 2016-12-01T23:35:06-05:00.
-If DATE-STRING cannot be parsed, it falls back to
-`parse-time-string'."
-  (when-let ((time
-              (if (iso8601-valid-p date-string)
-                  (decoded-time-set-defaults (iso8601-parse date-string))
-                ;; Fall back to having `parse-time-string' do fancy
-                ;; things for us.
-                (parse-time-string date-string))))
+  "Parse an ISO 8601 time string, such as \"2020-01-15T16:12:21-08:00\".
+Fall back on parsing something resembling an RFC 822 (or later) date-time.
+This function is like `parse-time-string' except that it returns
+a Lisp timestamp when successful."
+  (when-let ((time (parse-time-string date-string)))
     (encode-time time)))
 
 (provide 'parse-time)
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el
index 1e589ec..e2402de 100644
--- a/lisp/calendar/time-date.el
+++ b/lisp/calendar/time-date.el
@@ -515,15 +515,14 @@ TIME is modified and returned."
   (unless (decoded-time-year time)
     (setf (decoded-time-year time) 0))
 
-  ;; When we don't have a time zone and we don't have a DST, then mark
-  ;; it as unknown.
-  (when (and (not (decoded-time-zone time))
-             (not (decoded-time-dst time)))
-    (setf (decoded-time-dst time) -1))
-
-  (when (and (not (decoded-time-zone time))
-             default-zone)
-    (setf (decoded-time-zone time) 0))
+  ;; When we don't have a time zone, default to DEFAULT-ZONE without
+  ;; DST if DEFAULT-ZONE if given, and to unknown DST otherwise.
+  (unless (decoded-time-zone time)
+    (if default-zone
+       (progn (setf (decoded-time-zone time) default-zone)
+              (setf (decoded-time-dst time) nil))
+      (setf (decoded-time-dst time) -1)))
+
   time)
 
 (provide 'time-date)
diff --git a/lisp/calendar/timeclock.el b/lisp/calendar/timeclock.el
index f3a5d9c..d12feaa 100644
--- a/lisp/calendar/timeclock.el
+++ b/lisp/calendar/timeclock.el
@@ -193,6 +193,8 @@ to today."
 (defcustom timeclock-load-hook nil
   "Hook that gets run after timeclock has been loaded."
   :type 'hook)
+(make-obsolete-variable 'timeclock-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defcustom timeclock-in-hook nil
   "A hook run every time an \"in\" event is recorded."
diff --git a/lisp/cedet/ede.el b/lisp/cedet/ede.el
index 1418ad9..c203687 100644
--- a/lisp/cedet/ede.el
+++ b/lisp/cedet/ede.el
@@ -1527,8 +1527,7 @@ It does not apply the value to buffers."
 
 ;; If this does not occur after the provide, we can get a recursive
 ;; load.  Yuck!
-(if (featurep 'speedbar)
-    (ede-speedbar-file-setup)
-  (add-hook 'speedbar-load-hook 'ede-speedbar-file-setup))
+(with-eval-after-load 'speedbar
+  (ede-speedbar-file-setup))
 
 ;;; ede.el ends here
diff --git a/lisp/cedet/ede/cpp-root.el b/lisp/cedet/ede/cpp-root.el
index ee8aa5d..f0dbccb 100644
--- a/lisp/cedet/ede/cpp-root.el
+++ b/lisp/cedet/ede/cpp-root.el
@@ -478,21 +478,6 @@ Argument COMMAND is the command to use for compiling the 
target."
   "Don't rescan this project from the sources."
   (message "cpp-root has nothing to rescan."))
 
-;;; Quick Hack
-(defun ede-create-lots-of-projects-under-dir (dir projfile &rest attributes)
-  "Create a bunch of projects under directory DIR.
-PROJFILE is a file name sans directory that indicates a subdirectory
-is a project directory.
-Generic ATTRIBUTES, such as :include-path can be added.
-Note: This needs some work."
-  (let ((files (directory-files dir t)))
-    (dolist (F files)
-      (if (file-exists-p (expand-file-name projfile F))
-         `(ede-cpp-root-project (file-name-nondirectory F)
-                                :name (file-name-nondirectory F)
-                                :file (expand-file-name projfile F)
-                                attributes)))))
-
 (provide 'ede/cpp-root)
 
 ;; Local variables:
diff --git a/lisp/cedet/ede/makefile-edit.el b/lisp/cedet/ede/makefile-edit.el
index b68d671..218e75c 100644
--- a/lisp/cedet/ede/makefile-edit.el
+++ b/lisp/cedet/ede/makefile-edit.el
@@ -78,7 +78,8 @@
 If NEXT is non-nil, move to the next occurrence of MACRO."
   (let ((oldpt (point)))
     (when (not next) (goto-char (point-min)))
-    (if (re-search-forward (concat "^\\s-*" macro "\\s-*[+:?]?=") nil t)
+    (if (re-search-forward (concat "^\\s-*" (regexp-quote macro) 
"\\s-*[+:?]?=")
+                          nil t)
        t
       (goto-char oldpt)
       nil)))
diff --git a/lisp/cedet/ede/pconf.el b/lisp/cedet/ede/pconf.el
index 63fb62b..b85b397 100644
--- a/lisp/cedet/ede/pconf.el
+++ b/lisp/cedet/ede/pconf.el
@@ -56,8 +56,9 @@ don't do it.  A value of nil means to just do it.")
            (and (eq ede-pconf-create-file-query 'ask)
                 (not (eq ede-pconf-create-file-query 'never))
                 (not (y-or-n-p
-                      (format "I had to create the %s file for you.  Ok? " 
file)))
-                (error "Quit")))))))
+                      (format "I had to create the %s file for you.  Ok? "
+                              file))))
+         (error "Quit"))))))
 
 
 (cl-defmethod ede-proj-configure-synchronize ((this ede-proj-project))
diff --git a/lisp/cedet/mode-local.el b/lisp/cedet/mode-local.el
index bd02a4f..a6e143c 100644
--- a/lisp/cedet/mode-local.el
+++ b/lisp/cedet/mode-local.el
@@ -588,7 +588,7 @@ OVERARGS is a list of arguments passed to the override and
 (defmacro define-mode-local-override
   (name mode args docstring &rest body)
   "Define a mode specific override of the function overload NAME.
-Has meaning only if NAME has been created with `define-overload'.
+Has meaning only if NAME has been created with `define-overloadable-function'.
 MODE is the major mode this override is being defined for.
 ARGS are the function arguments, which should match those of the same
 named function created with `define-overload'.
diff --git a/lisp/cedet/semantic/imenu.el b/lisp/cedet/semantic/imenu.el
index 19e0515..cdf0a23 100644
--- a/lisp/cedet/semantic/imenu.el
+++ b/lisp/cedet/semantic/imenu.el
@@ -44,9 +44,8 @@
 
 ;; Because semantic imenu tags will hose the current imenu handling
 ;; code in speedbar, force semantic/sb in.
-(if (featurep 'speedbar)
-    (require 'semantic/sb)
-  (add-hook 'speedbar-load-hook (lambda () (require 'semantic/sb))))
+(with-eval-after-load 'speedbar
+  (require 'semantic/sb))
 
 (defgroup semantic-imenu nil
   "Semantic interface to Imenu."
diff --git a/lisp/cedet/srecode/semantic.el b/lisp/cedet/srecode/semantic.el
index 26c1489..5b2dd03 100644
--- a/lisp/cedet/srecode/semantic.el
+++ b/lisp/cedet/srecode/semantic.el
@@ -201,7 +201,7 @@ variable default values, and other things."
   (let ((tag (or srecode-semantic-selected-tag
                 (srecode-semantic-tag-from-kill-ring))))
     (when (not tag)
-      "No tag for current template.  Use the semantic kill-ring.")
+      (error "No tag for current template.  Use the semantic kill-ring."))
     (srecode-semantic-apply-tag-to-dict
      (srecode-semantic-tag (semantic-tag-name tag)
                           :prime tag)
diff --git a/lisp/cmuscheme.el b/lisp/cmuscheme.el
index d590b9e..d4bec95 100644
--- a/lisp/cmuscheme.el
+++ b/lisp/cmuscheme.el
@@ -517,6 +517,8 @@ command to run."
 This is a good place to put keybindings."
   :type 'hook
   :group 'cmuscheme)
+(make-obsolete-variable 'cmuscheme-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (run-hooks 'cmuscheme-load-hook)
 
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index 79c2357..d3d17fd 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -3035,17 +3035,18 @@ Update the widget to show that value.  The value that 
was current
 before this operation becomes the backup value."
   (let* ((symbol (widget-value widget))
         (saved-value (get symbol 'saved-value))
-        (comment (get symbol 'saved-variable-comment)))
+        (comment (get symbol 'saved-variable-comment))
+         value)
     (custom-variable-backup-value widget)
     (if (not (or saved-value comment))
-       ;; If there is no saved value, remove the setting.
-       (custom-push-theme 'theme-value symbol 'user 'reset)
-      ;; Otherwise, apply the saved value.
-      (put symbol 'variable-comment comment)
-      (custom-push-theme 'theme-value symbol 'user 'set (car-safe saved-value))
-      (ignore-errors
-       (funcall (or (get symbol 'custom-set) 'set-default)
-                symbol (eval (car saved-value)))))
+        ;; If there is no saved value, remove the setting.
+        (custom-push-theme 'theme-value symbol 'user 'reset)
+      (setq value (car-safe saved-value))
+      (custom-push-theme 'theme-value symbol 'user 'set value)
+      (put symbol 'variable-comment comment))
+    (ignore-errors
+      (funcall (or (get symbol 'custom-set) #'set-default) symbol
+               (eval (or value (car (get symbol 'standard-value))))))
     (put symbol 'customized-value nil)
     (put symbol 'customized-variable-comment nil)
     (widget-put widget :custom-state 'unknown)
@@ -4295,6 +4296,7 @@ This works for both graphical and text displays."
             (widget-put widget :children children)
             (custom-group-state-update widget))
           ;; End line
+           (insert "\n")
            (custom-group--draw-horizontal-line)))))
 
 (defvar custom-group-menu
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index e3dc6f0..dff4d9a 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -324,7 +324,7 @@ Leaving \"Default\" unchecked is equivalent with specifying 
a default of
                            ;; FIXME?
                             ;; :initialize custom-initialize-default
                            :set custom-set-minor-mode)
-            (tab-bar-mode (frames mouse) boolean nil
+            (tab-bar-mode tab-bar boolean nil
                            ;; :initialize custom-initialize-default
                           :set custom-set-minor-mode)
             (tool-bar-mode (frames mouse) boolean nil
diff --git a/lisp/custom.el b/lisp/custom.el
index ba7f999..885c486 100644
--- a/lisp/custom.el
+++ b/lisp/custom.el
@@ -886,7 +886,10 @@ See `custom-known-themes' for a list of known themes."
        (put theme 'theme-settings
             (cons (list prop symbol theme value)
                   (delq res theme-settings)))
-       (setcar (cdr setting) value)))
+        ;; It's tempting to use setcar here, but that could
+        ;; inadvertently modify other properties in SYMBOL's proplist,
+        ;; if those just happen to share elements with the value of PROP.
+        (put symbol prop (cons (list theme value) (delq setting old)))))
      ;; Add a new setting:
      (t
       (when (custom--should-apply-setting theme)
@@ -1378,7 +1381,7 @@ function runs.  To disable other themes, use 
`disable-theme'."
            (custom-theme-recalc-variable symbol)))))))
   (unless (eq theme 'user)
     (setq custom-enabled-themes
-         (cons theme (delq theme custom-enabled-themes)))
+         (cons theme (remq theme custom-enabled-themes)))
     ;; Give the `user' theme the highest priority.
     (enable-theme 'user)))
 
diff --git a/lisp/desktop.el b/lisp/desktop.el
index 9538bb4..de601a4 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -946,7 +946,12 @@ which means to truncate VAR's value to at most MAX-SIZE 
elements
              ")\n"))))
 
 ;; ----------------------------------------------------------------------------
-(defvar desktop-buffers-not-to-save-function nil)
+(defvar desktop-buffers-not-to-save-function nil
+  "Function identifying buffers that are to be excluded from saving.
+Like `desktop-buffers-not-to-save' it can be used to check whether
+a given buffer should not be saved.  It takes the same arguments as
+`desktop-save-buffer-p' and should return nil if buffer should not
+have its state saved in the desktop file.")
 
 (defun desktop-save-buffer-p (filename bufname mode &rest rest)
   "Return t if buffer should have its state saved in the desktop file.
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 59d389d..0069c17 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -992,7 +992,14 @@ command with a prefix argument (the value does not 
matter)."
          (ignore-errors (dired-remove-entry new-file))
          (goto-char start)
          ;; Now replace the current line with an entry for NEW-FILE.
-         (dired-update-file-line new-file) nil)
+         ;; But don't remove the current line if either FROM-FILE or
+         ;; NEW-FILE is a directory, because compressing/uncompressing
+          ;; directories doesn't remove the original.
+          (if (or (file-directory-p from-file)
+                  (file-directory-p new-file))
+              (dired-add-entry new-file nil t)
+            (dired-update-file-line new-file))
+          nil)
       (dired-log (concat "Failed to (un)compress " from-file))
       from-file)))
 
@@ -1020,8 +1027,9 @@ command with a prefix argument (the value does not 
matter)."
     ("\\.7z\\'" "" "7z x -aoa -o%o %i")
     ;; This item controls naming for compression.
     ("\\.tar\\'" ".tgz" nil)
-    ;; This item controls the compression of directories
-    (":" ".tar.gz" "tar -cf - %i | gzip -c9 > %o"))
+    ;; This item controls the compression of directories.  Its REGEXP
+    ;; element should never match any valid file name.
+    ("\000" ".tar.gz" "tar -cf - %i | gzip -c9 > %o"))
   "Control changes in file name suffixes for compression and uncompression.
 Each element specifies one transformation rule, and has the form:
   (REGEXP NEW-SUFFIX PROGRAM)
@@ -1145,7 +1153,7 @@ Return nil if no change in files."
            (condition-case nil
                (if (file-directory-p file)
                    (progn
-                     (setq suffix (cdr (assoc ":" 
dired-compress-file-suffixes)))
+                     (setq suffix (cdr (assoc "\000" 
dired-compress-file-suffixes)))
                      (when suffix
                        (let ((out-name (concat file (car suffix)))
                              (default-directory (file-name-directory file)))
diff --git a/lisp/dired-x.el b/lisp/dired-x.el
index 841434f..623a1dd 100644
--- a/lisp/dired-x.el
+++ b/lisp/dired-x.el
@@ -27,7 +27,7 @@
 ;;; Commentary:
 
 ;; This is based on Sebastian Kremer's excellent dired-x.el (Dired Extra),
-;; version 1.191, adapted for GNU Emacs.  See the `dired-x' info pages.
+;; version 1.191, adapted for GNU Emacs.  See the `dired-x' Info manual.
 
 ;; At load time dired-x.el will install itself and bind some dired keys.
 ;; Some dired.el and dired-aux.el functions have extra features if
@@ -35,7 +35,7 @@
 
 ;; User customization: M-x customize-group RET dired-x RET.
 
-;; *Please* see the `dired-x' info pages for more details.
+;; *Please* see the `dired-x' Info manual for more details.
 
 
 ;;; Code:
diff --git a/lisp/dired.el b/lisp/dired.el
index 689ad1f..a4de51f 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -230,6 +230,8 @@ The target is used in the prompt for file copy, rename etc."
 You can customize key bindings or load extensions with this."
   :group 'dired
   :type 'hook)
+(make-obsolete-variable 'dired-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defcustom dired-mode-hook nil
   "Run at the very end of `dired-mode'."
@@ -849,7 +851,6 @@ If a directory or nothing is found at point, return nil."
     (if (and file-name
             (not (file-directory-p file-name)))
        file-name)))
-(put 'dired-mode 'grep-read-files 'dired-grep-read-files)
 
 ;;;###autoload (define-key ctl-x-map "d" 'dired)
 ;;;###autoload
@@ -2149,6 +2150,7 @@ Do so according to the former subdir alist 
OLD-SUBDIR-ALIST."
 ;; Dired mode is suitable only for specially formatted data.
 (put 'dired-mode 'mode-class 'special)
 
+(defvar grep-read-files-function)
 ;; Autoload cookie needed by desktop.el
 ;;;###autoload
 (defun dired-mode (&optional dirname switches)
@@ -2210,7 +2212,6 @@ Hooks (use \\[describe-variable] to see their 
documentation):
   `dired-before-readin-hook'
   `dired-after-readin-hook'
   `dired-mode-hook'
-  `dired-load-hook'
 
 Keybindings:
 \\{dired-mode-map}"
@@ -2243,6 +2244,7 @@ Keybindings:
   (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)
+  (setq-local grep-read-files-function #'dired-grep-read-files)
   (setq dired-switches-alist nil)
   (hack-dir-local-variables-non-file-buffer) ; before sorting
   (dired-sort-other dired-actual-switches t)
@@ -3857,28 +3859,31 @@ With prefix argument, unmark or unflag these files."
            (if fn (backup-file-name-p fn))))
      "backup file")))
 
-(defun dired-change-marks (&optional old new)
+(defun dired-change-marks (old new)
   "Change all OLD marks to NEW marks.
 OLD and NEW are both characters used to mark files."
+  (declare (advertised-calling-convention '(old new) "28.1"))
   (interactive
    (let* ((cursor-in-echo-area t)
          (old (progn (message "Change (old mark): ") (read-char)))
          (new (progn (message  "Change %c marks to (new mark): " old)
                      (read-char))))
      (list old new)))
-  (if (or (eq old ?\r) (eq new ?\r))
-      (ding)
-    (let ((string (format "\n%c" old))
-         (inhibit-read-only t))
-      (save-excursion
-       (goto-char (point-min))
-       (while (search-forward string nil t)
-         (if (if (= old ?\s)
-                 (save-match-data
-                   (dired-get-filename 'no-dir t))
-               t)
-             (subst-char-in-region (match-beginning 0)
-                                   (match-end 0) old new)))))))
+  (dolist (c (list new old))
+    (if (or (not (char-displayable-p c))
+            (eq c ?\r))
+        (user-error "Invalid mark character: `%c'" c)))
+  (let ((string (format "\n%c" old))
+        (inhibit-read-only t))
+    (save-excursion
+      (goto-char (point-min))
+      (while (search-forward string nil t)
+        (if (if (= old ?\s)
+                (save-match-data
+                  (dired-get-filename 'no-dir t))
+              t)
+            (subst-char-in-region (match-beginning 0)
+                                  (match-end 0) old new))))))
 
 (defun dired-unmark-all-marks ()
   "Remove all marks from all files in the Dired buffer."
diff --git a/lisp/disp-table.el b/lisp/disp-table.el
index fe63573..2e88d35 100644
--- a/lisp/disp-table.el
+++ b/lisp/disp-table.el
@@ -221,7 +221,7 @@ for a graphical frame."
 (defun make-glyph-code (char &optional face)
   "Return a glyph code representing char CHAR with face FACE."
   ;; Due to limitations on Emacs integer values, faces with
-  ;; face id greater that 512 are silently ignored.
+  ;; face id greater than 512 are silently ignored.
   (if (not face)
       char
     (let ((fid (face-id face)))
diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el
index 850af93..b5d99e3 100644
--- a/lisp/emacs-lisp/bindat.el
+++ b/lisp/emacs-lisp/bindat.el
@@ -149,9 +149,6 @@
 ;;          |  ip                       -- 4 byte vector
 ;;          |  bits LEN                 -- List with bits set in LEN bytes.
 ;;
-;;          -- Note: 32 bit values may be limited by emacs' INTEGER
-;;             implementation limits.
-;;
 ;;          -- Example: `bits 2' will unpack 0x28 0x1c to (2 3 4 11 13)
 ;;                                       and 0x1c 0x28 to (3 5 10 11 12).
 
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 38bf112..fe0930c 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -498,15 +498,12 @@
           form)
 
          ((eq fn 'condition-case)
-           (if byte-compile--use-old-handlers
-               ;; Will be optimized later.
-               form
-             `(condition-case ,(nth 1 form) ;Not evaluated.
-                  ,(byte-optimize-form (nth 2 form) for-effect)
-                ,@(mapcar (lambda (clause)
-                            `(,(car clause)
-                              ,@(byte-optimize-body (cdr clause) for-effect)))
-                          (nthcdr 3 form)))))
+           `(condition-case ,(nth 1 form) ;Not evaluated.
+                ,(byte-optimize-form (nth 2 form) for-effect)
+              ,@(mapcar (lambda (clause)
+                          `(,(car clause)
+                            ,@(byte-optimize-body (cdr clause) for-effect)))
+                        (nthcdr 3 form))))
 
          ((eq fn 'unwind-protect)
           ;; the "protected" part of an unwind-protect is compiled (and thus
@@ -521,12 +518,7 @@
          ((eq fn 'catch)
           (cons fn
                 (cons (byte-optimize-form (nth 1 form) nil)
-                       (if byte-compile--use-old-handlers
-                           ;; The body of a catch is compiled (and thus
-                           ;; optimized) as a top-level form, so don't do it
-                           ;; here.
-                           (cdr (cdr form))
-                         (byte-optimize-body (cdr form) for-effect)))))
+                       (byte-optimize-body (cdr form) for-effect))))
 
          ((eq fn 'ignore)
           ;; Don't treat the args to `ignore' as being
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 9278c92..89a7114 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -736,14 +736,15 @@ otherwise pop it")
   "to make a binding to record entire window configuration")
 (byte-defop 140  0 byte-save-restriction
   "to make a binding to record the current buffer clipping restrictions")
-(byte-defop 141 -1 byte-catch
+(byte-defop 141 -1 byte-catch-OBSOLETE   ; Not generated since Emacs 25.
   "for catch.  Takes, on stack, the tag and an expression for the body")
 (byte-defop 142 -1 byte-unwind-protect
   "for unwind-protect.  Takes, on stack, an expression for the unwind-action")
 
 ;; For condition-case.  Takes, on stack, the variable to bind,
 ;; an expression for the body, and a list of clauses.
-(byte-defop 143 -2 byte-condition-case)
+;; Not generated since Emacs 25.
+(byte-defop 143 -2 byte-condition-case-OBSOLETE)
 
 (byte-defop 144  0 byte-temp-output-buffer-setup-OBSOLETE)
 (byte-defop 145 -1 byte-temp-output-buffer-show-OBSOLETE)
@@ -1218,7 +1219,7 @@ message buffer `default-directory'."
                            byte-compile-last-warned-form))))
       (insert (format "\nIn %s:\n" form)))
     (when level
-      (insert (format "%s%s" file pos))))
+      (insert (format "%s%s " file pos))))
   (setq byte-compile-last-logged-file byte-compile-current-file
        byte-compile-last-warned-form byte-compile-current-form)
   entry)
@@ -2174,36 +2175,36 @@ With argument ARG, insert value in current buffer after 
the form."
   (when (< (point-max) (position-bytes (point-max)))
     (goto-char (point-min))
     ;; Find the comment that describes the version condition.
-    (search-forward "\n;;; This file uses")
-    (narrow-to-region (line-beginning-position) (point-max))
-    ;; Find the first line of ballast semicolons.
-    (search-forward ";;;;;;;;;;")
-    (beginning-of-line)
-    (narrow-to-region (point-min) (point))
-    (let ((old-header-end (point))
-         (minimum-version "23")
-         delta)
-      (delete-region (point-min) (point-max))
-      (insert
-       ";;; This file contains utf-8 non-ASCII characters,\n"
-       ";;; and so cannot be loaded into Emacs 22 or earlier.\n"
-       ;; Have to check if emacs-version is bound so that this works
-       ;; in files loaded early in loadup.el.
-       "(and (boundp 'emacs-version)\n"
-       ;; If there is a name at the end of emacs-version,
-       ;; don't try to check the version number.
-       "     (< (aref emacs-version (1- (length emacs-version))) ?A)\n"
-       (format "     (string-lessp emacs-version \"%s\")\n" minimum-version)
-       ;; Because the header must fit in a fixed width, we cannot
-       ;; insert arbitrary-length file names (Bug#11585).
-       "     (error \"`%s' was compiled for "
-       (format "Emacs %s or later\" #$))\n\n" minimum-version))
-      ;; Now compensate for any change in size, to make sure all
-      ;; positions in the file remain valid.
-      (setq delta (- (point-max) old-header-end))
-      (goto-char (point-max))
-      (widen)
-      (delete-char delta))))
+    (when (search-forward "\n;;; This file does not contain utf-8" nil t)
+      (narrow-to-region (line-beginning-position) (point-max))
+      ;; Find the first line of ballast semicolons.
+      (search-forward ";;;;;;;;;;")
+      (beginning-of-line)
+      (narrow-to-region (point-min) (point))
+      (let ((old-header-end (point))
+           (minimum-version "23")
+           delta)
+        (delete-region (point-min) (point-max))
+        (insert
+         ";;; This file contains utf-8 non-ASCII characters,\n"
+         ";;; and so cannot be loaded into Emacs 22 or earlier.\n"
+         ;; Have to check if emacs-version is bound so that this works
+         ;; in files loaded early in loadup.el.
+         "(and (boundp 'emacs-version)\n"
+         ;; If there is a name at the end of emacs-version,
+         ;; don't try to check the version number.
+         "     (< (aref emacs-version (1- (length emacs-version))) ?A)\n"
+         (format "     (string-lessp emacs-version \"%s\")\n" minimum-version)
+         ;; Because the header must fit in a fixed width, we cannot
+         ;; insert arbitrary-length file names (Bug#11585).
+         "     (error \"`%s' was compiled for "
+         (format "Emacs %s or later\" #$))\n\n" minimum-version))
+        ;; Now compensate for any change in size, to make sure all
+        ;; positions in the file remain valid.
+        (setq delta (- (point-max) old-header-end))
+        (goto-char (point-max))
+        (widen)
+        (delete-char delta)))))
 
 (defun byte-compile-insert-header (_filename outbuffer)
   "Insert a header at the start of OUTBUFFER.
@@ -2235,11 +2236,7 @@ Call from the source buffer."
        ".\n"
        (if dynamic ";;; Function definitions are lazy-loaded.\n"
         "")
-       "\n;;; This file uses "
-       (if dynamic-docstrings
-          "dynamic docstrings, first added in Emacs 19.29"
-        "opcodes that do not exist in Emacs 18")
-       ".\n\n"
+       "\n"
        ;; Note that byte-compile-fix-header may change this.
        ";;; This file does not contain utf-8 non-ASCII characters,\n"
        ";;; and so can be loaded in Emacs versions earlier than 23.\n\n"
@@ -2247,6 +2244,7 @@ Call from the source buffer."
        ;; can delete them so as to keep the buffer positions
        ;; constant for the actual compiled code.
        ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"
+       ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"
        
";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n"))))
 
 (defun byte-compile-output-file-form (form)
@@ -4568,96 +4566,25 @@ binding slots have been popped."
 ;; (byte-defop-compiler-1 save-window-excursion)      ;Obsolete: now a macro.
 ;; (byte-defop-compiler-1 with-output-to-temp-buffer) ;Obsolete: now a macro.
 
-(defvar byte-compile--use-old-handlers nil
-  "If nil, use new byte codes introduced in Emacs-24.4.")
-
 (defun byte-compile-catch (form)
   (byte-compile-form (car (cdr form)))
-  (if (not byte-compile--use-old-handlers)
-      (let ((endtag (byte-compile-make-tag)))
-        (byte-compile-goto 'byte-pushcatch endtag)
-        (byte-compile-body (cddr form) nil)
-        (byte-compile-out 'byte-pophandler)
-        (byte-compile-out-tag endtag))
-    (pcase (cddr form)
-      (`(:fun-body ,f)
-       (byte-compile-form `(list 'funcall ,f)))
-      (body
-       (byte-compile-push-constant
-        (byte-compile-top-level (cons 'progn body) byte-compile--for-effect))))
-    (byte-compile-out 'byte-catch 0)))
+  (let ((endtag (byte-compile-make-tag)))
+    (byte-compile-goto 'byte-pushcatch endtag)
+    (byte-compile-body (cddr form) nil)
+    (byte-compile-out 'byte-pophandler)
+    (byte-compile-out-tag endtag)))
 
 (defun byte-compile-unwind-protect (form)
   (pcase (cddr form)
     (`(:fun-body ,f)
-     (byte-compile-form
-      (if byte-compile--use-old-handlers `(list (list 'funcall ,f)) f)))
+     (byte-compile-form f))
     (handlers
-     (if byte-compile--use-old-handlers
-         (byte-compile-push-constant
-          (byte-compile-top-level-body handlers t))
-       (byte-compile-form `#'(lambda () ,@handlers)))))
+     (byte-compile-form `#'(lambda () ,@handlers))))
   (byte-compile-out 'byte-unwind-protect 0)
   (byte-compile-form-do-effect (car (cdr form)))
   (byte-compile-out 'byte-unbind 1))
 
 (defun byte-compile-condition-case (form)
-  (if byte-compile--use-old-handlers
-      (byte-compile-condition-case--old form)
-    (byte-compile-condition-case--new form)))
-
-(defun byte-compile-condition-case--old (form)
-  (let* ((var (nth 1 form))
-        (fun-bodies (eq var :fun-body))
-         (byte-compile-bound-variables
-         (if (and var (not fun-bodies))
-              (cons var byte-compile-bound-variables)
-           byte-compile-bound-variables)))
-    (byte-compile-set-symbol-position 'condition-case)
-    (unless (symbolp var)
-      (byte-compile-warn
-       "`%s' is not a variable-name or nil (in condition-case)" var))
-    (if fun-bodies (setq var (make-symbol "err")))
-    (byte-compile-push-constant var)
-    (if fun-bodies
-        (byte-compile-form `(list 'funcall ,(nth 2 form)))
-      (byte-compile-push-constant
-       (byte-compile-top-level (nth 2 form) byte-compile--for-effect)))
-    (let ((compiled-clauses
-           (mapcar
-            (lambda (clause)
-              (let ((condition (car clause)))
-                (cond ((not (or (symbolp condition)
-                                (and (listp condition)
-                                     (let ((ok t))
-                                       (dolist (sym condition)
-                                         (if (not (symbolp sym))
-                                             (setq ok nil)))
-                                       ok))))
-                       (byte-compile-warn
-                        "`%S' is not a condition name or list of such (in 
condition-case)"
-                        condition))
-                      ;; (not (or (eq condition 't)
-                      ;;         (and (stringp (get condition 'error-message))
-                      ;;              (consp (get condition
-                      ;;                          'error-conditions)))))
-                      ;; (byte-compile-warn
-                      ;;   "`%s' is not a known condition name
-                      ;;   (in condition-case)"
-                      ;;   condition))
-                      )
-                (if fun-bodies
-                    `(list ',condition (list 'funcall ,(cadr clause) ',var))
-                  (cons condition
-                        (byte-compile-top-level-body
-                         (cdr clause) byte-compile--for-effect)))))
-            (cdr (cdr (cdr form))))))
-      (if fun-bodies
-          (byte-compile-form `(list ,@compiled-clauses))
-        (byte-compile-push-constant compiled-clauses)))
-    (byte-compile-out 'byte-condition-case 0)))
-
-(defun byte-compile-condition-case--new (form)
   (let* ((var (nth 1 form))
          (body (nth 2 form))
          (depth byte-compile-depth)
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index e2e5933..351a097 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -462,20 +462,7 @@ places where they originally did not directly appear."
                        ;; and may be an invalid expression (e.g. ($# . 678)).
                        (cdr forms)))))
 
-                                       ;condition-case
-    ((and `(condition-case ,var ,protected-form . ,handlers)
-          (guard byte-compile--use-old-handlers))
-     (let ((newform (cconv--convert-function
-                     () (list protected-form) env form)))
-       `(condition-case :fun-body ,newform
-          ,@(mapcar (lambda (handler)
-                      (list (car handler)
-                            (cconv--convert-function
-                             (list (or var cconv--dummy-var))
-                             (cdr handler) env form)))
-                    handlers))))
-
-                                        ; condition-case with new byte-codes.
+                                        ; condition-case
     (`(condition-case ,var ,protected-form . ,handlers)
      `(condition-case ,var
           ,(cconv-convert protected-form env extend)
@@ -496,10 +483,8 @@ places where they originally did not directly appear."
                        `((let ((,var (list ,var))) ,@body))))))
              handlers))))
 
-    (`(,(and head (or (and 'catch (guard byte-compile--use-old-handlers))
-                      'unwind-protect))
-       ,form . ,body)
-     `(,head ,(cconv-convert form env extend)
+    (`(unwind-protect ,form . ,body)
+     `(unwind-protect ,(cconv-convert form env extend)
         :fun-body ,(cconv--convert-function () body env form)))
 
     (`(setq . ,forms)                   ; setq special form
@@ -718,15 +703,6 @@ and updates the data stored in ENV."
     (`(quote . ,_) nil)                 ; quote form
     (`(function . ,_) nil)              ; same as quote
 
-    ((and `(condition-case ,var ,protected-form . ,handlers)
-          (guard byte-compile--use-old-handlers))
-     ;; FIXME: The bytecode for condition-case forces us to wrap the
-     ;; form and handlers in closures.
-     (cconv--analyze-function () (list protected-form) env form)
-     (dolist (handler handlers)
-       (cconv--analyze-function (if var (list var)) (cdr handler)
-                                env form)))
-
     (`(condition-case ,var ,protected-form . ,handlers)
      (cconv-analyze-form protected-form env)
      (when (and var (symbolp var) (byte-compile-not-lexical-var-p var))
@@ -741,9 +717,7 @@ and updates the data stored in ENV."
                                    form "variable"))))
 
     ;; FIXME: The bytecode for unwind-protect forces us to wrap the unwind.
-    (`(,(or (and 'catch (guard byte-compile--use-old-handlers))
-            'unwind-protect)
-       ,form . ,body)
+    (`(unwind-protect ,form . ,body)
      (cconv-analyze-form form env)
      (cconv--analyze-function () body env form))
 
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index 93b9ffb..ccdddb4 100644
--- a/lisp/emacs-lisp/checkdoc.el
+++ b/lisp/emacs-lisp/checkdoc.el
@@ -849,7 +849,7 @@ otherwise stop after the first error."
     ;; every test is responsible for returning the cursor.
     (or (and buffer-file-name ;; only check comments in a file
             (checkdoc-comments))
-       (checkdoc-start)
+       (checkdoc-start take-notes)
        (checkdoc-message-text)
        (checkdoc-rogue-spaces)
         (when checkdoc-package-keywords-flag
@@ -902,7 +902,7 @@ buffer and save warnings in a separate buffer."
       ;; the user is navigating down through the buffer.
       (while (and (not wrong) (checkdoc-next-docstring))
        ;; OK, let's look at the doc string.
-       (setq msg (checkdoc-this-string-valid))
+       (setq msg (checkdoc-this-string-valid take-notes))
        (if msg (setq wrong (point)))))
     (if wrong
        (progn
@@ -1284,12 +1284,15 @@ checking of documentation strings.
 
 ;;; Checking engines
 ;;
-(defun checkdoc-this-string-valid ()
+(defun checkdoc-this-string-valid (&optional take-notes)
   "Return a message string if the current doc string is invalid.
 Check for style only, such as the first line always being a complete
 sentence, whitespace restrictions, and making sure there are no
 hard-coded key-codes such as C-[char] or mouse-[number] in the comment.
-See the style guide in the Emacs Lisp manual for more details."
+See the style guide in the Emacs Lisp manual for more details.
+
+With a non-nil TAKE-NOTES, store all errors found in a warnings
+buffer, otherwise stop after the first error."
 
   ;; Jump over comments between the last object and the doc string
   (while (looking-at "[ \t\n]*;")
@@ -1366,13 +1369,16 @@ documentation string")
              (point) (+ (point) 1) t)))))
     (if (and (not err) (= (following-char) ?\"))
         (with-syntax-table checkdoc-syntax-table
-          (checkdoc-this-string-valid-engine fp))
+          (checkdoc-this-string-valid-engine fp take-notes))
       err)))
 
-(defun checkdoc-this-string-valid-engine (fp)
+(defun checkdoc-this-string-valid-engine (fp &optional take-notes)
   "Return an error list or string if the current doc string is invalid.
 Depends on `checkdoc-this-string-valid' to reset the syntax table so that
-regexp short cuts work.  FP is the function defun information."
+regexp short cuts work.  FP is the function defun information.
+
+With a non-nil TAKE-NOTES, store all errors found in a warnings
+buffer, otherwise stop after the first error."
   (let ((case-fold-search nil)
        ;; Use a marker so if an early check modifies the text,
        ;; we won't accidentally lose our place.  This could cause
@@ -1864,7 +1870,7 @@ Replace with \"%s\"? " original replace)
      ;; Make sure the doc string has correctly spelled English words
      ;; in it.  This function is extracted due to its complexity,
      ;; and reliance on the Ispell program.
-     (checkdoc-ispell-docstring-engine e)
+     (checkdoc-ispell-docstring-engine e take-notes)
      ;; User supplied checks
      (save-excursion (checkdoc-run-hooks 'checkdoc-style-functions fp e))
      ;; Done!
@@ -2090,6 +2096,10 @@ If the offending word is in a piece of quoted text, then 
it is skipped."
 ;;
 (defvar ispell-process)
 (declare-function ispell-buffer-local-words "ispell" ())
+(declare-function ispell-correct-p "ispell" ())
+(declare-function ispell-set-spellchecker-params "ispell" ())
+(declare-function ispell-accept-buffer-local-defs "ispell" ())
+(declare-function ispell-error-checking-word "ispell" (word))
 
 (defun checkdoc-ispell-init ()
   "Initialize Ispell process (default version) with Lisp words.
@@ -2100,58 +2110,66 @@ nil."
   (unless ispell-process
     (condition-case nil
        (progn
-         (ispell-buffer-local-words)
+          (ispell-set-spellchecker-params)    ; Initialize variables and dict 
alists.
+          (ispell-accept-buffer-local-defs)   ; Use the correct dictionary.
          ;; This code copied in part from ispell.el Emacs 19.34
          (dolist (w checkdoc-ispell-lisp-words)
            (process-send-string ispell-process (concat "@" w "\n"))))
       (error (setq checkdoc-spellcheck-documentation-flag nil)))))
 
-(defun checkdoc-ispell-docstring-engine (end)
+(defun checkdoc-ispell-docstring-engine (end &optional take-notes)
   "Run the Ispell tools on the doc string between point and END.
 Since Ispell isn't Lisp-smart, we must pre-process the doc string
-before using the Ispell engine on it."
-  (if (or (not checkdoc-spellcheck-documentation-flag)
-         ;; If the user wants no questions or fixing, then we must
-         ;; disable spell checking as not useful.
-         (not checkdoc-autofix-flag)
-         (eq checkdoc-autofix-flag 'never))
-      nil
+before using the Ispell engine on it.
+
+With a non-nil TAKE-NOTES, store all errors found in a warnings
+buffer, otherwise stop after the first error."
+  (when (and checkdoc-spellcheck-documentation-flag
+             ;; If the user wants no questions or fixing, then we must
+             ;; disable spell checking as not useful.
+             (or take-notes
+                 (and checkdoc-autofix-flag
+                      (not (eq checkdoc-autofix-flag 'never)))))
     (checkdoc-ispell-init)
+    (unless checkdoc-spellcheck-documentation-flag
+      ;; this happens when (checkdoc-ispell-init) can't start 
`ispell-program-name'
+      (user-error "No spellchecker installed: check the variable 
`ispell-program-name'."))
     (save-excursion
       (skip-chars-forward "^a-zA-Z")
-      (let ((word nil) (sym nil) (case-fold-search nil) (err nil))
-       (while (and (not err) (< (point) end))
-         (if (save-excursion (forward-char -1) (looking-at "[('`]"))
-             ;; Skip lists describing meta-syntax, or bound variables
-             (forward-sexp 1)
-           (setq word (buffer-substring-no-properties
-                       (point) (progn
-                                 (skip-chars-forward "a-zA-Z-")
-                                 (point)))
-                 sym (intern-soft word))
-           (if (and sym (or (boundp sym) (fboundp sym)))
-               ;; This is probably repetitive in most cases, but not always.
-               nil
-             ;; Find out how we spell-check this word.
-             (if (or
-                  ;; All caps w/ option th, or s tacked on the end
-                  ;; for pluralization or number.
-                  (string-match "^[A-Z][A-Z]+\\(s\\|th\\)?$" word)
-                  (looking-at "}") ; a keymap expression
-                  )
-                 nil
-               (save-excursion
-                 (if (not (eq checkdoc-autofix-flag 'never))
-                     (let ((lk last-input-event))
-                       (ispell-word nil t)
-                       (if (not (equal last-input-event lk))
-                           (progn
-                             (sit-for 0)
-                             (message "Continuing..."))))
-                   ;; Nothing here.
-                   )))))
-         (skip-chars-forward "^a-zA-Z"))
-       err))))
+      (let (word sym case-fold-search err word-beginning word-end)
+        (while (and (not err) (< (point) end))
+          (if (save-excursion (forward-char -1) (looking-at "[('`]"))
+              ;; Skip lists describing meta-syntax, or bound variables
+              (forward-sexp 1)
+            (setq word-beginning (point)
+                  word-end (progn
+                             (skip-chars-forward "a-zA-Z-")
+                             (point))
+                  word (buffer-substring-no-properties word-beginning word-end)
+                  sym (intern-soft word))
+            (unless (and sym (or (boundp sym) (fboundp sym)))
+              ;; Find out how we spell-check this word.
+              (unless (or
+                       ;; All caps w/ option th, or s tacked on the end
+                       ;; for pluralization or number.
+                       (string-match "^[A-Z][A-Z]+\\(s\\|th\\)?$" word)
+                       (looking-at "}") ; a keymap expression
+                       )
+                (save-excursion
+                  (let ((lk last-input-event))
+                    (if take-notes
+                        (progn
+                          (unless (ispell-correct-p)
+                            (checkdoc-create-error
+                             (ispell-error-checking-word word)
+                             word-beginning word-end)))
+                      (ispell-word nil t))
+                    (if (not (equal last-input-event lk))
+                        (progn
+                          (sit-for 0)
+                          (message "Continuing..."))))))))
+          (skip-chars-forward "^a-zA-Z"))
+        err))))
 
 ;;; Rogue space checking engine
 ;;
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index c4f6912..9d0fd15 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -1318,7 +1318,10 @@ For more details, see Info node `(cl)Loop Facility'.
                                                 (nreverse 
cl--loop-conditions)))
                                          ,then ,var))
                               loop-for-steps))
-                   (push `(,var (if ,first-assign ,start ,then)) 
loop-for-sets))))
+                    (push (if (eq start then)
+                             `(,var ,then)
+                            `(,var (if ,first-assign ,start ,then)))
+                          loop-for-sets))))
 
               ((memq word '(across across-ref))
                (let ((temp-vec (make-symbol "--cl-vec--"))
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
index f67aa89..ed28997 100644
--- a/lisp/emacs-lisp/debug.el
+++ b/lisp/emacs-lisp/debug.el
@@ -168,158 +168,150 @@ first will be printed into the backtrace buffer.
 If `inhibit-redisplay' is non-nil when this function is called,
 the debugger will not be entered."
   (interactive)
-  (cond
-   (inhibit-redisplay
-    ;; Don't really try to enter debugger within an eval from redisplay.
-    debugger-value)
-   ((and (eq t (framep (selected-frame)))
-         (equal "initial_terminal" (terminal-name)))
-    ;; We're in the initial-frame (where `message' just outputs to stdout) so
-    ;; there's no tty or GUI frame to display the backtrace and interact with
-    ;; it: just dump a backtrace to stdout.
-    ;; This happens for example while handling an error in code from
-    ;; early-init.el with --debug-init.
-    (message "Error: %S" args)
-    (let ((print-escape-newlines t)
-          (print-escape-control-characters t)
-          (print-level 8)
-          (print-length 50)
-          (skip t))             ;Skip the first frame (i.e. the `debug' frame)!
-      (mapbacktrace (lambda (_evald func args _flags)
-                      (if skip
-                          (setq skip nil)
-                        (message "  %S" (cons func args))))
-                    'debug)))
-   (t
-    (unless noninteractive
-      (message "Entering debugger..."))
-    (let (debugger-value
-         (debugger-previous-state
-           (if (get-buffer "*Backtrace*")
-               (with-current-buffer (get-buffer "*Backtrace*")
-                 (debugger--save-buffer-state))))
-          (debugger-args args)
-         (debugger-buffer (get-buffer-create "*Backtrace*"))
-         (debugger-old-buffer (current-buffer))
-         (debugger-window nil)
-         (debugger-step-after-exit nil)
-          (debugger-will-be-back nil)
-         ;; Don't keep reading from an executing kbd macro!
-         (executing-kbd-macro nil)
-         ;; Save the outer values of these vars for the `e' command
-         ;; before we replace the values.
-         (debugger-outer-match-data (match-data))
-         (debugger-with-timeout-suspend (with-timeout-suspend)))
-      ;; Set this instead of binding it, so that `q'
-      ;; will not restore it.
-      (setq overriding-terminal-local-map nil)
-      ;; Don't let these magic variables affect the debugger itself.
-      (let ((last-command nil) this-command track-mouse
-           (inhibit-trace t)
-           unread-command-events
-           unread-post-input-method-events
-           last-input-event last-command-event last-nonmenu-event
-           last-event-frame
-           overriding-local-map
-           load-read-function
-           ;; If we are inside a minibuffer, allow nesting
-           ;; so that we don't get an error from the `e' command.
-           (enable-recursive-minibuffers
-            (or enable-recursive-minibuffers (> (minibuffer-depth) 0)))
-           (standard-input t) (standard-output t)
-           inhibit-redisplay
-           (cursor-in-echo-area nil)
-           (window-configuration (current-window-configuration)))
-       (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)))
-              (with-current-buffer debugger-buffer
-                (unless (derived-mode-p 'debugger-mode)
-                 (debugger-mode))
-               (debugger-setup-buffer debugger-args)
-               (when noninteractive
-                 ;; If the backtrace is long, save the beginning
-                 ;; and the end, but discard the middle.
-                 (when (> (count-lines (point-min) (point-max))
-                          debugger-batch-max-lines)
-                   (goto-char (point-min))
-                   (forward-line (/ 2 debugger-batch-max-lines))
-                   (let ((middlestart (point)))
-                     (goto-char (point-max))
-                     (forward-line (- (/ 2 debugger-batch-max-lines)
-                                      debugger-batch-max-lines))
-                     (delete-region middlestart (point)))
-                   (insert "...\n"))
-                 (goto-char (point-min))
-                 (message "%s" (buffer-string))
-                 (kill-emacs -1)))
-             (pop-to-buffer
-              debugger-buffer
-              `((display-buffer-reuse-window
-                 display-buffer-in-previous-window
-                 display-buffer-below-selected)
-                . ((window-min-height . 10)
-                    (window-height . fit-window-to-buffer)
-                   ,@(when (and (window-live-p debugger-previous-window)
-                                (frame-visible-p
-                                 (window-frame debugger-previous-window)))
-                       `((previous-window . ,debugger-previous-window))))))
-             (setq debugger-window (selected-window))
-             (if (eq debugger-previous-window debugger-window)
-                 (when debugger-jumping-flag
-                   ;; Try to restore previous height of debugger
-                   ;; window.
-                   (condition-case nil
-                       (window-resize
-                        debugger-window
-                        (- debugger-previous-window-height
-                           (window-total-height debugger-window)))
-                     (error nil)))
-               (setq debugger-previous-window debugger-window))
-             (message "")
-             (let ((standard-output nil)
-                   (buffer-read-only t))
-               (message "")
-               ;; Make sure we unbind buffer-read-only in the right buffer.
-               (save-excursion
-                 (recursive-edit))))
-         (when (and (window-live-p debugger-window)
-                    (eq (window-buffer debugger-window) debugger-buffer))
-           ;; Record height of debugger window.
-           (setq debugger-previous-window-height
-                 (window-total-height debugger-window)))
-         (if debugger-will-be-back
-             ;; Restore previous window configuration (Bug#12623).
-             (set-window-configuration window-configuration)
+  (if inhibit-redisplay
+      ;; Don't really try to enter debugger within an eval from redisplay.
+      debugger-value
+    (let ((non-interactive-frame
+           (or noninteractive           ;FIXME: Presumably redundant.
+               ;; If we're in the initial-frame (where `message' just
+               ;; outputs to stdout) so there's no tty or GUI frame to
+               ;; display the backtrace and interact with it: just dump a
+               ;; backtrace to stdout.  This happens for example while
+               ;; handling an error in code from early-init.el with
+               ;; --debug-init.
+               (and (eq t (framep (selected-frame)))
+                    (equal "initial_terminal" (terminal-name)))))
+          ;; Don't let `inhibit-message' get in our way (especially important 
if
+          ;; `non-interactive-frame' evaluated to a non-nil value.
+          (inhibit-message nil))
+      (unless non-interactive-frame
+        (message "Entering debugger..."))
+      (let (debugger-value
+           (debugger-previous-state
+             (if (get-buffer "*Backtrace*")
+                 (with-current-buffer (get-buffer "*Backtrace*")
+                   (debugger--save-buffer-state))))
+            (debugger-args args)
+           (debugger-buffer (get-buffer-create "*Backtrace*"))
+           (debugger-old-buffer (current-buffer))
+           (debugger-window nil)
+           (debugger-step-after-exit nil)
+            (debugger-will-be-back nil)
+           ;; Don't keep reading from an executing kbd macro!
+           (executing-kbd-macro nil)
+           ;; Save the outer values of these vars for the `e' command
+           ;; before we replace the values.
+           (debugger-outer-match-data (match-data))
+           (debugger-with-timeout-suspend (with-timeout-suspend)))
+        ;; Set this instead of binding it, so that `q'
+        ;; will not restore it.
+        (setq overriding-terminal-local-map nil)
+        ;; Don't let these magic variables affect the debugger itself.
+        (let ((last-command nil) this-command track-mouse
+             (inhibit-trace t)
+             unread-command-events
+             unread-post-input-method-events
+             last-input-event last-command-event last-nonmenu-event
+             last-event-frame
+             overriding-local-map
+             load-read-function
+             ;; If we are inside a minibuffer, allow nesting
+             ;; so that we don't get an error from the `e' command.
+             (enable-recursive-minibuffers
+              (or enable-recursive-minibuffers (> (minibuffer-depth) 0)))
+             (standard-input t) (standard-output t)
+             inhibit-redisplay
+             (cursor-in-echo-area nil)
+             (window-configuration (current-window-configuration)))
+         (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)))
+                (with-current-buffer debugger-buffer
+                  (unless (derived-mode-p 'debugger-mode)
+                   (debugger-mode))
+                 (debugger-setup-buffer debugger-args)
+                 (when non-interactive-frame
+                   ;; If the backtrace is long, save the beginning
+                   ;; and the end, but discard the middle.
+                    (let ((inhibit-read-only t))
+                     (when (> (count-lines (point-min) (point-max))
+                              debugger-batch-max-lines)
+                       (goto-char (point-min))
+                       (forward-line (/ debugger-batch-max-lines 2))
+                       (let ((middlestart (point)))
+                         (goto-char (point-max))
+                         (forward-line (- (/ debugger-batch-max-lines 2)))
+                         (delete-region middlestart (point)))
+                       (insert "...\n")))
+                   (message "%s" (buffer-string))
+                   (kill-emacs -1)))
+               (pop-to-buffer
+                debugger-buffer
+                `((display-buffer-reuse-window
+                   display-buffer-in-previous-window
+                   display-buffer-below-selected)
+                  . ((window-min-height . 10)
+                      (window-height . fit-window-to-buffer)
+                     ,@(when (and (window-live-p debugger-previous-window)
+                                  (frame-visible-p
+                                   (window-frame debugger-previous-window)))
+                         `((previous-window . ,debugger-previous-window))))))
+               (setq debugger-window (selected-window))
+               (if (eq debugger-previous-window debugger-window)
+                   (when debugger-jumping-flag
+                     ;; Try to restore previous height of debugger
+                     ;; window.
+                     (condition-case nil
+                         (window-resize
+                          debugger-window
+                          (- debugger-previous-window-height
+                             (window-total-height debugger-window)))
+                       (error nil)))
+                 (setq debugger-previous-window debugger-window))
+               (message "")
+               (let ((standard-output nil)
+                     (buffer-read-only t))
+                 (message "")
+                 ;; Make sure we unbind buffer-read-only in the right buffer.
+                 (save-excursion
+                   (recursive-edit))))
            (when (and (window-live-p debugger-window)
                       (eq (window-buffer debugger-window) debugger-buffer))
-             (progn
-               ;; Unshow debugger-buffer.
-               (quit-restore-window debugger-window debugger-bury-or-kill)
-               ;; Restore current buffer (Bug#12502).
-               (set-buffer debugger-old-buffer)))
-            ;; Forget debugger window, it won't be back (Bug#17882).
-            (setq debugger-previous-window nil))
-          ;; Restore previous state of debugger-buffer in case we were
-          ;; in a recursive invocation of the debugger, otherwise just
-          ;; erase the buffer.
-         (when (buffer-live-p debugger-buffer)
-           (with-current-buffer debugger-buffer
-             (if debugger-previous-state
-                  (debugger--restore-buffer-state debugger-previous-state)
-                (setq backtrace-insert-header-function nil)
-                (setq backtrace-frames nil)
-                (backtrace-print))))
-         (with-timeout-unsuspend debugger-with-timeout-suspend)
-         (set-match-data debugger-outer-match-data)))
-      (setq debug-on-next-call debugger-step-after-exit)
-      debugger-value))))
+             ;; Record height of debugger window.
+             (setq debugger-previous-window-height
+                   (window-total-height debugger-window)))
+           (if debugger-will-be-back
+               ;; Restore previous window configuration (Bug#12623).
+               (set-window-configuration window-configuration)
+             (when (and (window-live-p debugger-window)
+                        (eq (window-buffer debugger-window) debugger-buffer))
+               (progn
+                 ;; Unshow debugger-buffer.
+                 (quit-restore-window debugger-window debugger-bury-or-kill)
+                 ;; Restore current buffer (Bug#12502).
+                 (set-buffer debugger-old-buffer)))
+              ;; Forget debugger window, it won't be back (Bug#17882).
+              (setq debugger-previous-window nil))
+            ;; Restore previous state of debugger-buffer in case we were
+            ;; in a recursive invocation of the debugger, otherwise just
+            ;; erase the buffer.
+           (when (buffer-live-p debugger-buffer)
+             (with-current-buffer debugger-buffer
+               (if debugger-previous-state
+                    (debugger--restore-buffer-state debugger-previous-state)
+                  (setq backtrace-insert-header-function nil)
+                  (setq backtrace-frames nil)
+                  (backtrace-print))))
+           (with-timeout-unsuspend debugger-with-timeout-suspend)
+           (set-match-data debugger-outer-match-data)))
+        (setq debug-on-next-call debugger-step-after-exit)
+        debugger-value))))
 
 (defun debugger--print (obj &optional stream)
   (condition-case err
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index b8d2fb5..85cc8c8 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -1714,6 +1714,7 @@ contains a circular object."
                 (cl-macrolet-body . edebug-match-cl-macrolet-body)
                (&not . edebug-match-&not)
                (&key . edebug-match-&key)
+               (&error . edebug-match-&error)
                (place . edebug-match-place)
                (gate . edebug-match-gate)
                ;;   (nil . edebug-match-nil)  not this one - special case it.
@@ -1847,6 +1848,15 @@ contains a circular object."
                            (car (cdr pair))))
                 specs))))
 
+(defun edebug-match-&error (cursor specs)
+  ;; Signal an error, using the following string in the spec as argument.
+  (let ((error-string (car specs))
+        (edebug-error-point (edebug-before-offset cursor)))
+    (goto-char edebug-error-point)
+    (error "%s"
+           (if (stringp error-string)
+               error-string
+             "String expected after &error in edebug-spec"))))
 
 (defun edebug-match-gate (_cursor)
   ;; Simply set the gate to prevent backtracking at this level.
@@ -2216,6 +2226,8 @@ into `edebug--cl-macrolet-defs' which is checked in 
`edebug-list-form-args'."
 
 (def-edebug-spec nested-backquote-form
   (&or
+   ("`" &error "Triply nested backquotes (without commas \"between\" them) \
+are too difficult to instrument")
    ;; Allow instrumentation of any , or ,@ contained within the (\, ...) or
    ;; (\,@ ...) matched on the next line.
    ([&or "," ",@"] backquote-form)
@@ -4518,17 +4530,6 @@ With prefix argument, make it a temporary breakpoint."
   (edebug-modify-breakpoint t condition arg))
 
 (easy-menu-define edebug-menu edebug-mode-map "Edebug menus" edebug-mode-menus)
-
-;;; Autoloading of Edebug accessories
-
-;; edebug-cl-read and cl-read are available from address@hidden
-(defun edebug--require-cl-read ()
-  (require 'edebug-cl-read))
-
-(if (featurep 'cl-read)
-    (add-hook 'edebug-setup-hook #'edebug--require-cl-read)
-  ;; The following causes edebug-cl-read to be loaded when you load cl-read.el.
-  (add-hook 'cl-read-load-hooks #'edebug--require-cl-read))
 
 
 ;;; Finalize Loading
@@ -4564,7 +4565,6 @@ With prefix argument, make it a temporary breakpoint."
       (run-with-idle-timer 0 nil #'(lambda () (unload-feature 'edebug)))))
   (remove-hook 'called-interactively-p-functions
                #'edebug--called-interactively-skip)
-  (remove-hook 'cl-read-load-hooks #'edebug--require-cl-read)
   (edebug-uninstall-read-eval-functions)
   ;; Continue standard unloading.
   nil)
diff --git a/lisp/emacs-lisp/eieio-opt.el b/lisp/emacs-lisp/eieio-opt.el
index dda9037..59af7e1 100644
--- a/lisp/emacs-lisp/eieio-opt.el
+++ b/lisp/emacs-lisp/eieio-opt.el
@@ -278,14 +278,7 @@ are not abstract."
 
 (if eieio-class-speedbar-key-map
     nil
-  (if (not (featurep 'speedbar))
-      (add-hook 'speedbar-load-hook (lambda ()
-                                     (eieio-class-speedbar-make-map)
-                                     (speedbar-add-expansion-list
-                                      '("EIEIO"
-                                        eieio-class-speedbar-menu
-                                        eieio-class-speedbar-key-map
-                                        eieio-class-speedbar))))
+  (with-eval-after-load 'speedbar
     (eieio-class-speedbar-make-map)
     (speedbar-add-expansion-list '("EIEIO"
                                   eieio-class-speedbar-menu
diff --git a/lisp/emacs-lisp/eieio-speedbar.el 
b/lisp/emacs-lisp/eieio-speedbar.el
index c11608d..5c6e0e5 100644
--- a/lisp/emacs-lisp/eieio-speedbar.el
+++ b/lisp/emacs-lisp/eieio-speedbar.el
@@ -140,11 +140,7 @@ MENU-VAR is the symbol containing an easymenu compatible 
menu part to use.
 MODENAME is a string used to identify this browser mode.
 FETCHER is a generic function used to fetch the base object list used when
 creating the speedbar display."
-  (if (not (featurep 'speedbar))
-      (add-hook 'speedbar-load-hook
-               (list 'lambda nil
-                     (list 'eieio-speedbar-create-engine
-                           map-fn map-var menu-var modename fetcher)))
+  (with-eval-after-load 'speedbar
     (eieio-speedbar-create-engine map-fn map-var menu-var modename fetcher)))
 
 (defun eieio-speedbar-create-engine (map-fn map-var menu-var modename fetcher)
diff --git a/lisp/emacs-lisp/lisp-mnt.el b/lisp/emacs-lisp/lisp-mnt.el
index ceb9b6b..0d57bc1 100644
--- a/lisp/emacs-lisp/lisp-mnt.el
+++ b/lisp/emacs-lisp/lisp-mnt.el
@@ -485,7 +485,18 @@ absent, return nil."
   (lm-with-file file
     (let ((start (lm-commentary-start)))
       (when start
-        (buffer-substring-no-properties start (lm-commentary-end))))))
+        (replace-regexp-in-string       ; Get rid of...
+         "[[:blank:]]*$" ""             ; trailing white-space
+         (replace-regexp-in-string
+          (format "%s\\|%s\\|%s"
+                  ;; commentary header
+                  (concat "^;;;[[:blank:]]*\\("
+                          lm-commentary-header
+                          "\\):[[:blank:]\n]*")
+                  "^;;[[:blank:]]*"     ; double semicolon prefix
+                  "[[:blank:]\n]*\\'")  ; trailing new-lines
+          "" (buffer-substring-no-properties
+              start (lm-commentary-end))))))))
 
 (defun lm-homepage (&optional file)
   "Return the homepage in file FILE, or current buffer if FILE is nil."
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index fbbd389..f66122d 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -747,6 +747,7 @@ Blank lines separate paragraphs.  Semicolons start comments.
 Note that `run-lisp' may be used either to start an inferior Lisp job
 or to switch back to an existing one."
   (lisp-mode-variables nil t)
+  (setq-local lisp-indent-function 'common-lisp-indent-function)
   (setq-local find-tag-default-function 'lisp-find-tag-default)
   (setq-local comment-start-skip
              "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)\\(;+\\|#|\\) *")
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 91b32df..a9508c1 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -606,8 +606,10 @@ EXP should be a form read from a foo-pkg.el file.
 Convert EXP into a `package-desc' object using the
 `package-desc-from-define' constructor before pushing it to
 `package-alist'.
-If there already exists a package by that name in
-`package-alist', replace that definition with the new one."
+
+If there already exists a package by the same name in
+`package-alist', insert this object there such that the packages
+are sorted with the highest version first."
   (when (eq (car-safe exp) 'define-package)
     (let* ((new-pkg-desc (apply #'package-desc-from-define (cdr exp)))
            (name (package-desc-name new-pkg-desc))
@@ -924,7 +926,6 @@ untar into a directory named DIR; otherwise, signal an 
error."
                (if (> (length file-list) 1) 'tar 'single))))
       ('tar
        (make-directory package-user-dir t)
-       ;; FIXME: should we delete PKG-DIR if it exists?
        (let* ((default-directory (file-name-as-directory package-user-dir)))
          (package-untar-buffer dirname)))
       ('single
@@ -953,7 +954,7 @@ untar into a directory named DIR; otherwise, signal an 
error."
     pkg-dir))
 
 (defun package-generate-description-file (pkg-desc pkg-file)
-  "Create the foo-pkg.el file for single-file packages."
+  "Create the foo-pkg.el file PKG-FILE for single-file package PKG-DESC."
   (let* ((name (package-desc-name pkg-desc)))
     (let ((print-level nil)
           (print-quoted t)
@@ -997,6 +998,7 @@ untar into a directory named DIR; otherwise, signal an 
error."
 (defvar version-control)
 
 (defun package-generate-autoloads (name pkg-dir)
+  "Generate autoloads in PKG-DIR for package named NAME."
   (let* ((auto-name (format "%s-autoloads.el" name))
          ;;(ignore-name (concat name "-pkg.el"))
          (generated-autoload-file (expand-file-name auto-name pkg-dir))
@@ -1177,12 +1179,14 @@ The return result is a `package-desc'."
 ;; signature checking.
 
 (defun package--write-file-no-coding (file-name)
+  "Write file FILE-NAME without encoding using coding system."
   (let ((buffer-file-coding-system 'no-conversion))
     (write-region (point-min) (point-max) file-name nil 'silent)))
 
 (declare-function url-http-file-exists-p "url-http" (url))
 
 (defun package--archive-file-exists-p (location file)
+  "Return t if FILE exists in remote LOCATION."
   (let ((http (string-match "\\`https?:" location)))
     (if http
         (progn
@@ -2372,18 +2376,9 @@ The description is read from the installed package 
files."
      result
 
      ;; Look for Commentary header.
-     (let ((mainsrcfile (expand-file-name (format "%s.el" (package-desc-name 
desc))
-                                          srcdir)))
-       (when (file-readable-p mainsrcfile)
-         (with-temp-buffer
-           (insert (or (lm-commentary mainsrcfile) ""))
-           (goto-char (point-min))
-           (when (re-search-forward "^;;; Commentary:\n" nil t)
-             (replace-match ""))
-           (while (re-search-forward "^\\(;+ ?\\)" nil t)
-             (replace-match ""))
-           (buffer-string))))
-     )))
+     (lm-commentary (expand-file-name
+                     (format "%s.el" (package-desc-name desc)) srcdir))
+     "")))
 
 (defun describe-package-1 (pkg)
   "Insert the package description for PKG.
@@ -2578,16 +2573,10 @@ Helper function for `describe-package'."
       (if built-in
           ;; For built-in packages, get the description from the
           ;; Commentary header.
-          (let ((fn (locate-file (format "%s.el" name) load-path
-                                 load-file-rep-suffixes))
-                (opoint (point)))
-            (insert (or (lm-commentary fn) ""))
-            (save-excursion
-              (goto-char opoint)
-              (when (re-search-forward "^;;; Commentary:\n" nil t)
-                (replace-match ""))
-              (while (re-search-forward "^\\(;+ ?\\)" nil t)
-                (replace-match ""))))
+          (insert (or (lm-commentary (locate-file (format "%s.el" name)
+                                                  load-path
+                                                  load-file-rep-suffixes))
+                      ""))
 
         (if (package-installed-p desc)
             ;; For installed packages, get the description from the
@@ -2820,6 +2809,7 @@ of these dependencies, similar to the list returned by
                     (push dep out)))))))))))
 
 (defun package-desc-status (pkg-desc)
+  "Return the status of `package-desc' object PKG-DESC."
   (let* ((name (package-desc-name pkg-desc))
          (dir (package-desc-dir pkg-desc))
          (lle (assq name package-load-list))
diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el
index dbce079..03af053 100644
--- a/lisp/emacs-lisp/rx.el
+++ b/lisp/emacs-lisp/rx.el
@@ -273,7 +273,7 @@ Return (REGEXP . PRECEDENCE)."
   ;;   (or (+ digit) "CHARLIE" "CHAN" (+ blank))
   ;;   -> (or (+ digit) (or "CHARLIE" "CHAN") (+ blank))
   ;;
-  ;; - Optimise single-character alternatives better:
+  ;; - Optimize single-character alternatives better:
   ;;     * classes: space, alpha, ...
   ;;     * (syntax S), for some S (whitespace, word)
   ;;   so that (or "@" "%" digit (any "A-Z" space) (syntax word))
diff --git a/lisp/emacs-lisp/tabulated-list.el 
b/lisp/emacs-lisp/tabulated-list.el
index 501cc3a..b13f609 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -547,10 +547,10 @@ Return the column number after insertion."
     ;; Don't truncate to `width' if the next column is align-right
     ;; and has some space left, truncate to `available-space' instead.
     (when (and not-last-col
-               (> label-width available-space)
-               (setq label (truncate-string-to-width
-                            label available-space nil nil t t)
-                     label-width available-space)))
+              (> label-width available-space))
+      (setq label (truncate-string-to-width
+                  label available-space nil nil t t)
+           label-width available-space))
     (setq label (bidi-string-mark-left-to-right label))
     (when (and right-align (> width label-width))
       (let ((shift (- width label-width)))
diff --git a/lisp/emulation/viper-init.el b/lisp/emulation/viper-init.el
index 511c68f..6c4afe5 100644
--- a/lisp/emulation/viper-init.el
+++ b/lisp/emulation/viper-init.el
@@ -922,6 +922,8 @@ Should be set in `viper-custom-file-name'."
   "Hooks run just after loading Viper."
   :type 'hook
   :group 'viper-hooks)
+(make-obsolete-variable 'viper-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defun viper-restore-cursor-type ()
   (condition-case nil
diff --git a/lisp/erc/erc-autoaway.el b/lisp/erc/erc-autoaway.el
index 84f4011..be7baca 100644
--- a/lisp/erc/erc-autoaway.el
+++ b/lisp/erc/erc-autoaway.el
@@ -3,8 +3,8 @@
 ;; Copyright (C) 2002-2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Jorgen Schaefer <address@hidden>
-;; Maintainer: address@hidden
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcAutoAway
+;; Maintainer: Amin Bandali <address@hidden>
+;; URL: https://www.emacswiki.org/emacs/ErcAutoAway
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index 2102c5e..b1a829c 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -4,7 +4,7 @@
 
 ;; Filename: erc-backend.el
 ;; Author: Lawrence Mitchell <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Created: 2004-05-7
 ;; Keywords: IRC chat client internet
 
diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el
index 6e30b3a..cb1b71b 100644
--- a/lisp/erc/erc-button.el
+++ b/lisp/erc/erc-button.el
@@ -3,9 +3,9 @@
 ;; Copyright (C) 1996-2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: irc, button, url, regexp
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcButton
+;; URL: https://www.emacswiki.org/emacs/ErcButton
 
 ;; This file is part of GNU Emacs.
 
@@ -41,6 +41,7 @@
 (require 'erc)
 (require 'wid-edit)
 (require 'erc-fill)
+(require 'browse-url)
 
 ;;; Minor Mode
 
@@ -87,12 +88,9 @@ above them."
   :type 'face
   :group 'erc-faces)
 
-(defcustom erc-button-url-regexp
-  (concat "\\(www\\.\\|\\(s?https?\\|"
-          "ftp\\|file\\|gopher\\|news\\|telnet\\|wais\\|mailto\\):\\)"
-          "\\(//[-a-zA-Z0-9_.]+:[0-9]*\\)?"
-          "[-a-zA-Z0-9_=!?#$@~`%&*+\\/:;.,()]+[-a-zA-Z0-9_=#$@~`%&*+\\/()]")
+(defcustom erc-button-url-regexp browse-url-button-regexp
   "Regular expression that matches URLs."
+  :version "27.1"
   :group 'erc-button
   :type 'regexp)
 
@@ -223,14 +221,11 @@ PAR is a number of a regexp grouping whose text will be 
passed to
 
 (defvar erc-button-syntax-table
   (let ((table (make-syntax-table)))
-    (modify-syntax-entry ?\( "w" table)
-    (modify-syntax-entry ?\) "w" table)
     (modify-syntax-entry ?\[ "w" table)
     (modify-syntax-entry ?\] "w" table)
     (modify-syntax-entry ?\{ "w" table)
     (modify-syntax-entry ?\} "w" table)
     (modify-syntax-entry ?` "w" table)
-    (modify-syntax-entry ?' "w" table)
     (modify-syntax-entry ?^ "w" table)
     (modify-syntax-entry ?- "w" table)
     (modify-syntax-entry ?_ "w" table)
diff --git a/lisp/erc/erc-capab.el b/lisp/erc/erc-capab.el
index 975b53d..129f502 100644
--- a/lisp/erc/erc-capab.el
+++ b/lisp/erc/erc-capab.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2006-2020 Free Software Foundation, Inc.
 
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 
 ; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el
index 2dae90a..f433abc 100644
--- a/lisp/erc/erc-compat.el
+++ b/lisp/erc/erc-compat.el
@@ -3,8 +3,8 @@
 ;; Copyright (C) 2002-2003, 2005-2020 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <address@hidden>
-;; Maintainer: address@hidden
-;; URL: http://www.emacswiki.org/cgi-bin/wiki/ERC
+;; Maintainer: Amin Bandali <address@hidden>
+;; URL: https://www.emacswiki.org/emacs/ERC
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el
index ad46af3..e121003 100644
--- a/lisp/erc/erc-dcc.el
+++ b/lisp/erc/erc-dcc.el
@@ -6,7 +6,7 @@
 ;; Author: Ben A. Mesander <address@hidden>
 ;;         Noah Friedman <address@hidden>
 ;;         Per Persson <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm, processes
 ;; Created: 1994-01-23
 
diff --git a/lisp/erc/erc-desktop-notifications.el 
b/lisp/erc/erc-desktop-notifications.el
index fb4b41e..7c32429 100644
--- a/lisp/erc/erc-desktop-notifications.el
+++ b/lisp/erc/erc-desktop-notifications.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2012-2020 Free Software Foundation, Inc.
 
 ;; Author: Julien Danjou <address@hidden>
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm
 
 ;; This file is part of GNU Emacs.
@@ -54,12 +55,14 @@
 
 (defvar dbus-debug) ; used in the macroexpansion of dbus-ignore-errors
 
-(defun erc-notifications-notify (nick msg)
-  "Notify that NICK send some MSG.
+(defun erc-notifications-notify (nick msg &optional privp)
+  "Notify that NICK send some MSG, where PRIVP should be non-nil for PRIVMSGs.
 This will replace the last notification sent with this function."
+  ;; TODO: can we do this without PRIVP? (by "fixing" ERC's not
+  ;; setting the current buffer to the existing query buffer)
   (dbus-ignore-errors
     (setq erc-notifications-last-notification
-          (let ((channel (current-buffer)))
+          (let ((channel (if privp (erc-get-buffer nick) (current-buffer))))
             (notifications-notify :bus erc-notifications-bus
                                   :title (format "%s in %s"
                                                  (xml-escape-string nick)
@@ -79,7 +82,7 @@ This will replace the last notification sent with this 
function."
                (not (and (boundp 'erc-track-exclude)
                          (member nick erc-track-exclude)))
                (not (erc-is-message-ctcp-and-not-action-p msg)))
-      (erc-notifications-notify nick msg)))
+      (erc-notifications-notify nick msg t)))
   ;; Return nil to continue processing by ERC
   nil)
 
diff --git a/lisp/erc/erc-ezbounce.el b/lisp/erc/erc-ezbounce.el
index a604f51..a2d58e9 100644
--- a/lisp/erc/erc-ezbounce.el
+++ b/lisp/erc/erc-ezbounce.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2002, 2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Andreas Fuchs <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el
index bef5e8e..6abbe39 100644
--- a/lisp/erc/erc-fill.el
+++ b/lisp/erc/erc-fill.el
@@ -4,8 +4,8 @@
 
 ;; Author: Andreas Fuchs <address@hidden>
 ;;         Mario Lang <address@hidden>
-;; Maintainer: address@hidden
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcFilling
+;; Maintainer: Amin Bandali <address@hidden>
+;; URL: https://www.emacswiki.org/emacs/ErcFilling
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index bba0a72..809f8f0 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2001-2020 Free Software Foundation, Inc.
 
 ;; Author: Jorgen Schaefer <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 
 ;; Most code is taken verbatim from erc.el, see there for the original
 ;; authors.
diff --git a/lisp/erc/erc-ibuffer.el b/lisp/erc/erc-ibuffer.el
index b00e2bd..7a04ff1 100644
--- a/lisp/erc/erc-ibuffer.el
+++ b/lisp/erc/erc-ibuffer.el
@@ -3,9 +3,8 @@
 ;; Copyright (C) 2002, 2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcIbuffer
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-identd.el b/lisp/erc/erc-identd.el
index 034a3d6..70a0917 100644
--- a/lisp/erc/erc-identd.el
+++ b/lisp/erc/erc-identd.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2003, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm, processes
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-imenu.el b/lisp/erc/erc-imenu.el
index 23fb1a9..3fb91ec 100644
--- a/lisp/erc/erc-imenu.el
+++ b/lisp/erc/erc-imenu.el
@@ -4,9 +4,9 @@
 ;; Inc.
 
 ;; Author: Mario Lang <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcImenu
+;; URL: https://www.emacswiki.org/emacs/ErcImenu
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-join.el b/lisp/erc/erc-join.el
index 75f9562..7bc4f00 100644
--- a/lisp/erc/erc-join.el
+++ b/lisp/erc/erc-join.el
@@ -3,9 +3,9 @@
 ;; Copyright (C) 2002-2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: irc
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcAutoJoin
+;; URL: https://www.emacswiki.org/emacs/ErcAutoJoin
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-lang.el b/lisp/erc/erc-lang.el
index dc96c25..3ab1f03 100644
--- a/lisp/erc/erc-lang.el
+++ b/lisp/erc/erc-lang.el
@@ -3,9 +3,9 @@
 ;; Copyright (C) 2002, 2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Old-Version: 1.0.0
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcLang
+;; URL: https://www.emacswiki.org/emacs/ErcLang
 ;; Keywords: comm languages processes
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-list.el b/lisp/erc/erc-list.el
index 35e7fda..4fba9f4 100644
--- a/lisp/erc/erc-list.el
+++ b/lisp/erc/erc-list.el
@@ -3,8 +3,9 @@
 ;; Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
 ;; Author: Tom Tromey <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Old-Version: 0.1
+;; URL: https://www.emacswiki.org/emacs/ErcList
 ;; Keywords: comm
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el
index fda91c8..e53f3c0 100644
--- a/lisp/erc/erc-log.el
+++ b/lisp/erc/erc-log.el
@@ -3,7 +3,8 @@
 ;; Copyright (C) 2003-2020 Free Software Foundation, Inc.
 
 ;; Author: Lawrence Mitchell <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
+;; URL: https://www.emacswiki.org/emacs/ErcLogging
 ;; Keywords: IRC, chat, client, Internet, logging
 
 ;; Created 2003-04-26
diff --git a/lisp/erc/erc-match.el b/lisp/erc/erc-match.el
index 7a824cc..c0f3bf1 100644
--- a/lisp/erc/erc-match.el
+++ b/lisp/erc/erc-match.el
@@ -3,9 +3,9 @@
 ;; Copyright (C) 2002-2020 Free Software Foundation, Inc.
 
 ;; Author: Andreas Fuchs <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm, faces
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcMatch
+;; URL: https://www.emacswiki.org/emacs/ErcMatch
 
 ;; This file is part of GNU Emacs.
 
@@ -246,14 +246,11 @@ and other miscellaneous functions."
 ;; just put it in erc.el
 (defvar erc-match-syntax-table
   (let ((table (make-syntax-table)))
-    (modify-syntax-entry ?\( "w" table)
-    (modify-syntax-entry ?\) "w" table)
     (modify-syntax-entry ?\[ "w" table)
     (modify-syntax-entry ?\] "w" table)
     (modify-syntax-entry ?\{ "w" table)
     (modify-syntax-entry ?\} "w" table)
     (modify-syntax-entry ?` "w" table)
-    (modify-syntax-entry ?' "w" table)
     (modify-syntax-entry ?^ "w" table)
     (modify-syntax-entry ?- "w" table)
     (modify-syntax-entry ?_ "w" table)
diff --git a/lisp/erc/erc-menu.el b/lisp/erc/erc-menu.el
index e9a76b8..4bc758a 100644
--- a/lisp/erc/erc-menu.el
+++ b/lisp/erc/erc-menu.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2001-2002, 2004-2020 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm, processes, menu
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-netsplit.el b/lisp/erc/erc-netsplit.el
index 9b4d175..2816acd 100644
--- a/lisp/erc/erc-netsplit.el
+++ b/lisp/erc/erc-netsplit.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2002-2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el
index 7831b7e..0696993 100644
--- a/lisp/erc/erc-networks.el
+++ b/lisp/erc/erc-networks.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2002, 2004-2020 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-notify.el b/lisp/erc/erc-notify.el
index 59f20aa..80ae0c3 100644
--- a/lisp/erc/erc-notify.el
+++ b/lisp/erc/erc-notify.el
@@ -3,7 +3,8 @@
 ;; Copyright (C) 2002-2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
+;; URL: https://www.emacswiki.org/emacs/ErcNotify
 ;; Keywords: comm
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-page.el b/lisp/erc/erc-page.el
index 6991090..c6eca51 100644
--- a/lisp/erc/erc-page.el
+++ b/lisp/erc/erc-page.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2002, 2004, 2006-2020 Free Software Foundation, Inc.
 
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-pcomplete.el b/lisp/erc/erc-pcomplete.el
index 9df0558..65b0f66 100644
--- a/lisp/erc/erc-pcomplete.el
+++ b/lisp/erc/erc-pcomplete.el
@@ -3,9 +3,9 @@
 ;; Copyright (C) 2002-2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Sacha Chua <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm, convenience
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcCompletion
+;; URL: https://www.emacswiki.org/emacs/ErcCompletion
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-replace.el b/lisp/erc/erc-replace.el
index 027f2c3..dfb2062 100644
--- a/lisp/erc/erc-replace.el
+++ b/lisp/erc/erc-replace.el
@@ -4,7 +4,8 @@
 ;; Inc.
 
 ;; Author: Andreas Fuchs <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
+;; URL: https://www.emacswiki.org/emacs/ErcReplace
 ;; Keywords: IRC, client, Internet
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-ring.el b/lisp/erc/erc-ring.el
index b5b8b0d..7594b8e 100644
--- a/lisp/erc/erc-ring.el
+++ b/lisp/erc/erc-ring.el
@@ -3,9 +3,9 @@
 ;; Copyright (C) 2001-2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Alex Schroeder <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcHistory
+;; URL: https://www.emacswiki.org/emacs/ErcHistory
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el
index de890b6..2d1d855 100644
--- a/lisp/erc/erc-services.el
+++ b/lisp/erc/erc-services.el
@@ -2,7 +2,8 @@
 
 ;; Copyright (C) 2002-2004, 2006-2020 Free Software Foundation, Inc.
 
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
+;; URL: https://www.emacswiki.org/emacs/ErcNickserv
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-sound.el b/lisp/erc/erc-sound.el
index 20c4581..96d41a6 100644
--- a/lisp/erc/erc-sound.el
+++ b/lisp/erc/erc-sound.el
@@ -2,7 +2,8 @@
 
 ;; Copyright (C) 2002-2003, 2006-2020 Free Software Foundation, Inc.
 
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
+;; URL: https://www.emacswiki.org/emacs/ErcSound
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
index 1ff44af..1c0635c 100644
--- a/lisp/erc/erc-speedbar.el
+++ b/lisp/erc/erc-speedbar.el
@@ -4,7 +4,8 @@
 
 ;; Author: Mario Lang <address@hidden>
 ;; Contributor: Eric M. Ludlam <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
+;; URL: https://www.emacswiki.org/emacs/ErcSpeedbar
 
 ;; This file is part of GNU Emacs.
 
@@ -89,9 +90,8 @@ nil            - Do not sort users"
   "Additional menu-items to add to speedbar frame.")
 
 ;; Make sure our special speedbar major mode is loaded
-(if (featurep 'speedbar)
-    (erc-install-speedbar-variables)
-  (add-hook 'speedbar-load-hook 'erc-install-speedbar-variables))
+(with-eval-after-load 'speedbar
+  (erc-install-speedbar-variables))
 
 ;;; ERC hierarchy display method
 ;;;###autoload
diff --git a/lisp/erc/erc-spelling.el b/lisp/erc/erc-spelling.el
index 565185d..4632329 100644
--- a/lisp/erc/erc-spelling.el
+++ b/lisp/erc/erc-spelling.el
@@ -3,9 +3,9 @@
 ;; Copyright (C) 2005-2020 Free Software Foundation, Inc.
 
 ;; Author: Jorgen Schaefer <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: irc
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcSpelling
+;; URL: https://www.emacswiki.org/emacs/ErcSpelling
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el
index c93402f..3717dc0 100644
--- a/lisp/erc/erc-stamp.el
+++ b/lisp/erc/erc-stamp.el
@@ -3,9 +3,9 @@
 ;; Copyright (C) 2002-2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm, processes, timestamp
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcStamp
+;; URL: https://www.emacswiki.org/emacs/ErcStamp
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el
index 6691a9e..f8c80d2 100644
--- a/lisp/erc/erc-track.el
+++ b/lisp/erc/erc-track.el
@@ -3,9 +3,9 @@
 ;; Copyright (C) 2002-2020 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm, faces
-;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?ErcChannelTracking
+;; URL: https://www.emacswiki.org/emacs/ErcChannelTracking
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/erc/erc-truncate.el b/lisp/erc/erc-truncate.el
index 2c34ebd..9de33ff 100644
--- a/lisp/erc/erc-truncate.el
+++ b/lisp/erc/erc-truncate.el
@@ -3,7 +3,8 @@
 ;; Copyright (C) 2003-2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Andreas Fuchs <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
+;; URL: https://www.emacswiki.org/emacs/ErcTruncation
 ;; Keywords: IRC, chat, client, Internet, logging
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-xdcc.el b/lisp/erc/erc-xdcc.el
index 3ca4e5b..61087de 100644
--- a/lisp/erc/erc-xdcc.el
+++ b/lisp/erc/erc-xdcc.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2003-2004, 2006-2020 Free Software Foundation, Inc.
 
 ;; Author: Mario Lang <address@hidden>
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: comm, processes
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 264093b..a467551 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -10,7 +10,7 @@
 ;;               Gergely Nagy (address@hidden)
 ;;               David Edmondson (address@hidden)
 ;;               Kelvin White (address@hidden)
-;; Maintainer: address@hidden
+;; Maintainer: Amin Bandali <address@hidden>
 ;; Keywords: IRC, chat, client, Internet
 
 ;; Version: 5.3
diff --git a/lisp/expand.el b/lisp/expand.el
index 1417c90..77e4fc2 100644
--- a/lisp/expand.el
+++ b/lisp/expand.el
@@ -55,10 +55,8 @@
 ;;
 ;;   you can also init some post-process hooks :
 ;;
-;; (add-hook 'expand-load-hook
-;;       (lambda ()
-;;         (add-hook 'expand-expand-hook 'indent-according-to-mode)
-;;         (add-hook 'expand-jump-hook 'indent-according-to-mode)))
+;; (add-hook 'expand-expand-hook 'indent-according-to-mode)
+;; (add-hook 'expand-jump-hook 'indent-according-to-mode)
 ;;
 ;; Remarks:
 ;;
@@ -78,6 +76,8 @@
   "Hooks run when `expand.el' is loaded."
   :type 'hook
   :group 'expand)
+(make-obsolete-variable 'expand-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defcustom expand-expand-hook nil
   "Hooks run when an abbrev made by `expand-add-abbrevs' is expanded."
diff --git a/lisp/ezimage.el b/lisp/ezimage.el
index dab7a53..dcedd8a 100644
--- a/lisp/ezimage.el
+++ b/lisp/ezimage.el
@@ -270,4 +270,4 @@ See `ezimage-expand-image-button-alist' for details."
 
 (provide 'ezimage)
 
-;;; sb-image.el ends here
+;;; ezimage.el ends here
diff --git a/lisp/ffap.el b/lisp/ffap.el
index 66ef082..ead79b4 100644
--- a/lisp/ffap.el
+++ b/lisp/ffap.el
@@ -1080,7 +1080,7 @@ If a given RFC isn't in these then `ffap-rfc-path' is 
offered."
     ;; Slightly controversial decisions:
     ;; * strip trailing "@", ":" and enclosing "{"/"}".
     ;; * no commas (good for latex)
-    (file "--:\\\\${}+<>@-Z_[:alpha:]~*?" "{<@" "@>;.,!:}")
+    (file "--:\\\\${}+<>@-Z_[:alpha:]~*?#" "{<@" "@>;.,!:}")
     ;; An url, or maybe an email/news message-id:
     (url "--:=&?$+@-Z_[:alpha:]~#,%;*()!'" "^[0-9a-zA-Z]" ":;.,!?")
     ;; Find a string that does *not* contain a colon:
diff --git a/lisp/filesets.el b/lisp/filesets.el
index 9834bcf..1ec0d24 100644
--- a/lisp/filesets.el
+++ b/lisp/filesets.el
@@ -1645,10 +1645,10 @@ Replace <file-name> or <<file-name>> with filename."
                                      (dolist (this args txt)
                                        (setq txt
                                              (concat txt
+                                                     (if (equal txt "") "" " ")
                                                      (filesets-run-cmd--repl-fn
                                                       this
                                                       (lambda (this)
-                                                        (if (equal txt "") "" 
" ")
                                                         (format "%s" 
this))))))))
                                   (cmd (concat fn " " args)))
                              (filesets-cmd-show-result
diff --git a/lisp/finder.el b/lisp/finder.el
index 96359b0..dc14b27 100644
--- a/lisp/finder.el
+++ b/lisp/finder.el
@@ -394,13 +394,6 @@ FILE should be in a form suitable for passing to 
`locate-library'."
     (erase-buffer)
     (insert str)
     (goto-char (point-min))
-    (delete-blank-lines)
-    (goto-char (point-max))
-    (delete-blank-lines)
-    (goto-char (point-min))
-    (while (re-search-forward "^;+ ?" nil t)
-      (replace-match "" nil nil))
-    (goto-char (point-min))
     (while (re-search-forward "\\<\\([-[:alnum:]]+\\.el\\)\\>" nil t)
       (if (locate-library (match-string 1))
           (make-text-button (match-beginning 1) (match-end 1)
diff --git a/lisp/frame.el b/lisp/frame.el
index c533e5a..16ee758 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -2725,6 +2725,9 @@ See also `toggle-frame-maximized'."
         line-prefix
         wrap-prefix
         truncate-lines
+        mode-line-format
+        header-line-format
+        tab-line-format
         display-line-numbers
         display-line-numbers-width
         display-line-numbers-current-absolute
diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el
index 9f22b7df..80bf21b 100644
--- a/lisp/gnus/gnus-agent.el
+++ b/lisp/gnus/gnus-agent.el
@@ -799,7 +799,7 @@ be a select method."
   (let ((gnus-command-method method)
        (gnus-agent nil))
     (when (file-exists-p (gnus-agent-lib-file "flags"))
-      (set-buffer (get-buffer-create " *Gnus Agent flag synchronize*"))
+      (set-buffer (gnus-get-buffer-create " *Gnus Agent flag synchronize*"))
       (erase-buffer)
       (nnheader-insert-file-contents (gnus-agent-lib-file "flags"))
       (cond ((null gnus-plugged)
diff --git a/lisp/gnus/gnus-bookmark.el b/lisp/gnus/gnus-bookmark.el
index ea4af2d..1b00bbb 100644
--- a/lisp/gnus/gnus-bookmark.el
+++ b/lisp/gnus/gnus-bookmark.el
@@ -242,7 +242,7 @@ So the cdr of each bookmark is an alist too.")
     (save-window-excursion
       ;; Avoid warnings?
       ;; (message "Saving Gnus bookmarks to file %s..." 
gnus-bookmark-default-file)
-      (set-buffer (get-buffer-create  " *Gnus bookmarks*"))
+      (set-buffer (gnus-get-buffer-create  " *Gnus bookmarks*"))
       (erase-buffer)
       (gnus-bookmark-insert-file-format-version-stamp)
       (pp gnus-bookmark-alist (current-buffer))
@@ -357,8 +357,8 @@ deletion, or > if it is flagged for displaying."
   (interactive)
   (gnus-bookmark-maybe-load-default-file)
   (if (called-interactively-p 'any)
-      (switch-to-buffer (get-buffer-create "*Gnus Bookmark List*"))
-    (set-buffer (get-buffer-create "*Gnus Bookmark List*")))
+      (switch-to-buffer (gnus-get-buffer-create "*Gnus Bookmark List*"))
+    (set-buffer (gnus-get-buffer-create "*Gnus Bookmark List*")))
   (let ((inhibit-read-only t)
        alist name start end)
     (erase-buffer)
@@ -648,7 +648,7 @@ reposition and try again, else return nil."
        (details gnus-bookmark-bookmark-details)
        detail)
     (save-excursion
-      (pop-to-buffer (get-buffer-create "*Gnus Bookmark Annotation*") t)
+      (pop-to-buffer (gnus-get-buffer-create "*Gnus Bookmark Annotation*") t)
       (erase-buffer)
       (while details
        (setq detail (pop details))
diff --git a/lisp/gnus/gnus-cloud.el b/lisp/gnus/gnus-cloud.el
index cecfaef..4d8764b 100644
--- a/lisp/gnus/gnus-cloud.el
+++ b/lisp/gnus/gnus-cloud.el
@@ -243,10 +243,10 @@ Use old data if FORCE-OLDER is not nil."
                 (when (or (not gnus-cloud-interactive)
                           (gnus-y-or-n-p
                            (format "%s has older different info in the cloud 
as of %s, update it here? "
-                                   group date))))
-                (gnus-message 2 "Installing cloud update of group %s" group)
-                (gnus-set-info group contents)
-                (gnus-group-update-group group)))
+                                  group date)))
+                 (gnus-message 2 "Installing cloud update of group %s" group)
+                 (gnus-set-info group contents)
+                 (gnus-group-update-group group))))
           (gnus-error 1 "Sorry, group %s is not subscribed" group))
       (gnus-error 1 "Sorry, could not update newsrc for group %s (invalid data 
%S)"
                   group elem))))
diff --git a/lisp/gnus/gnus-draft.el b/lisp/gnus/gnus-draft.el
index 1b25d24..3a9bf2a 100644
--- a/lisp/gnus/gnus-draft.el
+++ b/lisp/gnus/gnus-draft.el
@@ -248,7 +248,7 @@ If DONT-POP is nil, display the buffer after setting it up."
       (let ((article narticle))
         (message-mail nil nil nil nil
                       (if dont-pop
-                          (lambda (buf) (set-buffer (get-buffer-create buf)))))
+                          (lambda (buf) (set-buffer (gnus-get-buffer-create 
buf)))))
         (let ((inhibit-read-only t))
           (erase-buffer))
         (if (not (gnus-request-restore-buffer article group))
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index b89f040..da7db58 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -3761,10 +3761,10 @@ group line."
      (newsrc
       ;; Toggle subscription flag.
       (gnus-group-change-level
-       newsrc (if level level (if (<= (gnus-info-level (nth 1 newsrc))
-                                     gnus-level-subscribed)
-                                 (1+ gnus-level-subscribed)
-                               gnus-level-default-subscribed)))
+       newsrc (or level (if (<= (gnus-info-level (nth 1 newsrc))
+                               gnus-level-subscribed)
+                           (1+ gnus-level-subscribed)
+                         gnus-level-default-subscribed)))
       (unless silent
        (gnus-group-update-group group)))
      ((and (stringp group)
@@ -3773,7 +3773,7 @@ group line."
       ;; Add new newsgroup.
       (gnus-group-change-level
        group
-       (if level level gnus-level-default-subscribed)
+       (or level gnus-level-default-subscribed)
        (or (and (member group gnus-zombie-list)
                gnus-level-zombie)
           gnus-level-killed)
diff --git a/lisp/gnus/gnus-icalendar.el b/lisp/gnus/gnus-icalendar.el
index ee556a3..305e17f 100644
--- a/lisp/gnus/gnus-icalendar.el
+++ b/lisp/gnus/gnus-icalendar.el
@@ -814,7 +814,7 @@ These will be used to retrieve the RSVP information from 
ical events."
         (let ((subject (concat (capitalize (symbol-name status))
                                ": " (gnus-icalendar-event:summary event))))
 
-          (with-current-buffer (get-buffer-create gnus-icalendar-reply-bufname)
+          (with-current-buffer (gnus-get-buffer-create 
gnus-icalendar-reply-bufname)
             (delete-region (point-min) (point-max))
             (insert reply)
             (fold-icalendar-buffer)
diff --git a/lisp/gnus/gnus-int.el b/lisp/gnus/gnus-int.el
index c304f57..60ebc07 100644
--- a/lisp/gnus/gnus-int.el
+++ b/lisp/gnus/gnus-int.el
@@ -253,7 +253,7 @@ If it is down, start it up (again)."
 
 (defun gnus-backend-trace (type form)
   (when gnus-backend-trace
-    (with-current-buffer (get-buffer-create "*gnus trace*")
+    (with-current-buffer (gnus-get-buffer-create "*gnus trace*")
       (buffer-disable-undo)
       (goto-char (point-max))
       (insert (format-time-string "%H:%M:%S")
diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el
index 466a627..daaea39 100644
--- a/lisp/gnus/gnus-msg.el
+++ b/lisp/gnus/gnus-msg.el
@@ -1985,13 +1985,14 @@ process-mark several articles, they will all be 
attached."
                                       buffers t nil nil (car buffers))))
       (gnus-summary-mail-other-window)
       (setq destination (current-buffer)))
+    (gnus-summary-expand-window)
     (gnus-summary-iterate n
       (gnus-summary-select-article)
-      (set-buffer destination)
-      ;; Attach at the end of the buffer.
-      (save-excursion
-       (goto-char (point-max))
-       (message-forward-make-body-mime gnus-original-article-buffer)))
+      (with-current-buffer destination
+       ;; Attach at the end of the buffer.
+       (save-excursion
+        (goto-char (point-max))
+        (message-forward-make-body-mime gnus-original-article-buffer))))
     (gnus-configure-windows 'message t)))
 
 (provide 'gnus-msg)
diff --git a/lisp/gnus/gnus-srvr.el b/lisp/gnus/gnus-srvr.el
index d58bd7a..095e054 100644
--- a/lisp/gnus/gnus-srvr.el
+++ b/lisp/gnus/gnus-srvr.el
@@ -309,7 +309,7 @@ The following commands are available:
   ;; `gnus-server-buffer' selected as the current buffer, but not always (I
   ;; bumped into it when starting from a dedicated *Group* frame, and
   ;; gnus-configure-windows opened *Server* into its own dedicated frame).
-  (with-current-buffer (get-buffer-create gnus-server-buffer)
+  (with-current-buffer (gnus-get-buffer-create gnus-server-buffer)
     (gnus-server-mode)
     (gnus-server-prepare)))
 
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 6131926..1fd2575 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -1256,19 +1256,19 @@ INFO-LIST), otherwise it's a list in the format of the
 `gnus-newsrc-hashtb' entries.  LEVEL is the new level of the
 group, OLDLEVEL is the old level and PREVIOUS is the group (a
 string name) to insert this group before."
-  (let (group info active num)
-    ;; Glean what info we can from the arguments.
-    (if (consp entry)
-       (setq group (if fromkilled (nth 1 entry) (car (nth 1 entry))))
-      (setq group entry))
+  ;; Glean what info we can from the arguments.
+  (let ((group (if (consp entry)
+                  (if fromkilled (nth 1 entry) (car (nth 1 entry)))
+                entry))
+       info active num)
     (when (and (stringp entry)
               oldlevel
               (< oldlevel gnus-level-zombie))
       (setq entry (gnus-group-entry entry)))
-    (if (and (not oldlevel)
-            (consp entry))
-       (setq oldlevel (gnus-info-level (nth 1 entry)))
-      (setq oldlevel (or oldlevel gnus-level-killed)))
+    (setq oldlevel (if (and (not oldlevel)
+                           (consp entry))
+                      (gnus-info-level (nth 1 entry))
+                    (or oldlevel gnus-level-killed)))
 
     ;; This table is used for completion, so put a dummy entry there.
     (unless (gethash group gnus-active-hashtb)
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index a59e8b3..65a0263 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -3124,7 +3124,7 @@ follow up an article, type `\\[gnus-summary-followup]'.  
To mail a reply to the
 of an article, type `\\[gnus-summary-reply]'.
 
 There are approx. one gazillion commands you can execute in this
-buffer; read the info pages for more information (`\\[gnus-info-find-node]').
+buffer; read the Info manual for more information (`\\[gnus-info-find-node]').
 
 The following commands are available:
 
@@ -12310,7 +12310,7 @@ no matter what the properties `:decode' and `:headers' 
are."
                                          (buffer-string))))))
       (put 'gnus-summary-save-in-pipe :headers headers))
     (unless (zerop (length result))
-      (if (with-current-buffer (get-buffer-create result-buffer)
+      (if (with-current-buffer (gnus-get-buffer-create result-buffer)
            (erase-buffer)
            (insert result)
            (prog1
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index 23c62b4..eb0fd25 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -950,7 +950,7 @@ FILENAME exists and is Babyl format."
       (setq rmail-default-rmail-file filename) ; 22
     (setq rmail-default-file filename))        ; 23
   (let ((artbuf (current-buffer))
-       (tmpbuf (get-buffer-create " *Gnus-output*"))
+       (tmpbuf (gnus-get-buffer-create " *Gnus-output*"))
         ;; Babyl rmail.el defines this, mbox does not.
         (babyl (fboundp 'rmail-insert-rmail-file-header)))
     (save-excursion
@@ -1036,7 +1036,7 @@ FILENAME exists and is Babyl format."
   (require 'nnmail)
   (setq filename (expand-file-name filename))
   (let ((artbuf (current-buffer))
-       (tmpbuf (get-buffer-create " *Gnus-output*")))
+       (tmpbuf (gnus-get-buffer-create " *Gnus-output*")))
     (save-excursion
       ;; Create the file, if it doesn't exist.
       (when (and (not (get-file-buffer filename))
@@ -1457,7 +1457,7 @@ CHOICE is a list of the choice char and help message at 
IDX."
          (setq tchar (read-char))
          (when (not (assq tchar choice))
            (setq tchar nil)
-           (setq buf (get-buffer-create "*Gnus Help*"))
+           (setq buf (gnus-get-buffer-create "*Gnus Help*"))
            (pop-to-buffer buf)
            (fundamental-mode)
            (buffer-disable-undo)
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index f836ea6..caeab7f 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -660,7 +660,7 @@ be used directly.")
 (defun gnus-add-buffer ()
   "Add the current buffer to the list of Gnus buffers."
   (gnus-prune-buffers)
-  (push (current-buffer) gnus-buffers))
+  (cl-pushnew (current-buffer) gnus-buffers))
 
 (defmacro gnus-kill-buffer (buffer)
   "Kill BUFFER and remove from the list of Gnus buffers."
@@ -2821,7 +2821,7 @@ See Info node `(gnus)Formatting Variables'."
                (:constructor gnus-info-make
                 (group rank read &optional marks method params))
                (:constructor nil)
-               ;; FIMXE: gnus-newsrc-alist contains a list of those,
+              ;; FIXME: gnus-newsrc-alist contains a list of those,
                ;; so changing them to a real struct will take more work!
                (:type list))
   group rank read marks method params)
diff --git a/lisp/gnus/mail-source.el b/lisp/gnus/mail-source.el
index 52343d4..f5b6878 100644
--- a/lisp/gnus/mail-source.el
+++ b/lisp/gnus/mail-source.el
@@ -740,9 +740,11 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff 
bfile)
   (when delay
     (sleep-for delay)))
 
+(declare-function gnus-get-buffer-create "gnus" (name))
 (defun mail-source-call-script (script)
+  (require 'gnus)
   (let ((background nil)
-       (stderr (get-buffer-create " *mail-source-stderr*"))
+       (stderr (gnus-get-buffer-create " *mail-source-stderr*"))
        result)
     (when (string-match "& *$" script)
       (setq script (substring script 0 (match-beginning 0))
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index adefa0e..3abeec7 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -1986,6 +1986,7 @@ You must have the \"hashcash\" binary installed, see 
`hashcash-path'."
 (autoload 'gnus-delay-article "gnus-delay")
 (autoload 'gnus-extract-address-components "gnus-util")
 (autoload 'gnus-find-method-for-group "gnus")
+(autoload 'gnus-get-buffer-create "gnus")
 (autoload 'gnus-group-name-charset "gnus-group")
 (autoload 'gnus-group-name-decode "gnus-group")
 (autoload 'gnus-groups-from-server "gnus")
@@ -7310,7 +7311,7 @@ If ARG, allow editing of the cancellation message."
        ;; Make control message.
        (if arg
            (message-news)
-         (setq buf (set-buffer (get-buffer-create " *message cancel*"))))
+         (setq buf (set-buffer (gnus-get-buffer-create " *message cancel*"))))
        (erase-buffer)
        (insert "Newsgroups: " newsgroups "\n"
                "From: " from "\n"
@@ -7731,7 +7732,7 @@ is for the internal use."
          gcc beg)
       ;; We first set up a normal mail buffer.
       (unless (message-mail-user-agent)
-       (set-buffer (get-buffer-create " *message resend*"))
+       (set-buffer (gnus-get-buffer-create " *message resend*"))
        (let ((inhibit-read-only t))
          (erase-buffer)))
       (let ((message-this-is-mail t)
diff --git a/lisp/gnus/mm-archive.el b/lisp/gnus/mm-archive.el
index 6b4308e..71676c1 100644
--- a/lisp/gnus/mm-archive.el
+++ b/lisp/gnus/mm-archive.el
@@ -24,6 +24,7 @@
 
 (require 'mm-decode)
 (autoload 'gnus-recursive-directory-files "gnus-util")
+(autoload 'gnus-get-buffer-create "gnus")
 (autoload 'mailcap-extension-to-mime "mailcap")
 
 (defvar mm-archive-decoders
@@ -56,7 +57,7 @@
                         (append (cdr decoder) (list dir)))
                  (delete-file file))
              (apply 'call-process-region (point-min) (point-max) (car decoder)
-                    nil (get-buffer-create "*tnef*")
+                    nil (gnus-get-buffer-create "*tnef*")
                     nil (append (cdr decoder) (list dir)))))
          `("multipart/mixed"
            ,handle
diff --git a/lisp/gnus/mml-smime.el b/lisp/gnus/mml-smime.el
index 3cc463d5..4754f37 100644
--- a/lisp/gnus/mml-smime.el
+++ b/lisp/gnus/mml-smime.el
@@ -154,14 +154,9 @@ Whether the passphrase is cached at all is controlled by
          (write-region (point-min) (point-max) file))
        (push file certfiles)
        (push file tmpfiles)))
-    (if (smime-encrypt-buffer certfiles)
-       (progn
-         (while (setq tmp (pop tmpfiles))
-           (delete-file tmp))
-         t)
-      (while (setq tmp (pop tmpfiles))
-       (delete-file tmp))
-      nil))
+    (smime-encrypt-buffer certfiles)
+    (while (setq tmp (pop tmpfiles))
+      (delete-file tmp)))
   (goto-char (point-max)))
 
 (defvar gnus-extract-address-components)
diff --git a/lisp/gnus/mml2015.el b/lisp/gnus/mml2015.el
index 1e72f68..d1d150a 100644
--- a/lisp/gnus/mml2015.el
+++ b/lisp/gnus/mml2015.el
@@ -293,6 +293,8 @@ If set, it overrides the setting of 
`mml2015-sign-with-sender'."
                   (substring alg (match-end 0))
                 alg))))
 
+(autoload 'gnus-get-buffer-create "gnus")
+
 (defun mml2015-mailcrypt-verify (handle ctl)
   (catch 'error
     (let (part)
@@ -330,7 +332,7 @@ If set, it overrides the setting of 
`mml2015-sign-with-sender'."
              (replace-match "-----BEGIN PGP SIGNATURE-----" t t))
          (if (re-search-forward "^-----END PGP [^-]+-----\r?$" nil t)
              (replace-match "-----END PGP SIGNATURE-----" t t)))
-       (let ((mc-gpg-debug-buffer (get-buffer-create " *gnus gpg debug*")))
+       (let ((mc-gpg-debug-buffer (gnus-get-buffer-create " *gnus gpg 
debug*")))
          (unless (condition-case err
                      (prog1
                          (funcall mml2015-verify-function)
@@ -359,7 +361,7 @@ If set, it overrides the setting of 
`mml2015-sign-with-sender'."
       handle)))
 
 (defun mml2015-mailcrypt-clear-verify ()
-  (let ((mc-gpg-debug-buffer (get-buffer-create " *gnus gpg debug*")))
+  (let ((mc-gpg-debug-buffer (gnus-get-buffer-create " *gnus gpg debug*")))
     (if (condition-case err
            (prog1
                (funcall mml2015-verify-function)
@@ -725,6 +727,8 @@ If set, it overrides the setting of 
`mml2015-sign-with-sender'."
 (autoload 'epg-expand-group "epg-config")
 (autoload 'epa-select-keys "epa")
 
+(autoload 'gnus-create-image "gnus-util")
+
 (defun mml2015-epg-key-image (key-id)
   "Return the image of a key, if any."
   (with-temp-buffer
@@ -949,7 +953,6 @@ If set, it overrides the setting of 
`mml2015-sign-with-sender'."
 ;;; General wrapper
 
 (autoload 'gnus-buffer-live-p "gnus-util")
-(autoload 'gnus-get-buffer-create "gnus")
 
 (defun mml2015-clean-buffer ()
   (if (gnus-buffer-live-p mml2015-result-buffer)
diff --git a/lisp/gnus/nnbabyl.el b/lisp/gnus/nnbabyl.el
index 6890f1d..cb22933 100644
--- a/lisp/gnus/nnbabyl.el
+++ b/lisp/gnus/nnbabyl.el
@@ -293,7 +293,7 @@
 
 (deffoo nnbabyl-request-move-article
     (article group server accept-form &optional last move-is-internal)
-  (let ((buf (get-buffer-create " *nnbabyl move*"))
+  (let ((buf (gnus-get-buffer-create " *nnbabyl move*"))
        result)
     (and
      (nnbabyl-request-article article group server)
diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el
index 24a3df1..ac394ae 100644
--- a/lisp/gnus/nndiary.el
+++ b/lisp/gnus/nndiary.el
@@ -597,7 +597,7 @@ all.  This may very well take some time.")
 
 (deffoo nndiary-request-move-article
     (article group server accept-form &optional last move-is-internal)
-  (let ((buf (get-buffer-create " *nndiary move*"))
+  (let ((buf (gnus-get-buffer-create " *nndiary move*"))
        result)
     (nndiary-possibly-change-directory group server)
     (nndiary-update-file-alist)
@@ -831,7 +831,7 @@ all.  This may very well take some time.")
 
 ;; Find an article number in the current group given the Message-ID.
 (defun nndiary-find-group-number (id)
-  (with-current-buffer (get-buffer-create " *nndiary id*")
+  (with-current-buffer (gnus-get-buffer-create " *nndiary id*")
     (let ((alist nndiary-group-alist)
          number)
       ;; We want to look through all .overview files, but we want to
@@ -999,8 +999,8 @@ all.  This may very well take some time.")
 
 (defun nndiary-open-nov (group)
   (or (cdr (assoc group nndiary-nov-buffer-alist))
-      (let ((buffer (get-buffer-create (format " *nndiary overview %s*"
-                                              group))))
+      (let ((buffer (gnus-get-buffer-create
+                     (format " *nndiary overview %s*" group))))
        (with-current-buffer buffer
          (set (make-local-variable 'nndiary-nov-buffer-file-name)
               (expand-file-name
@@ -1086,7 +1086,7 @@ all.  This may very well take some time.")
 (defun nndiary-generate-nov-file (dir files)
   (let* ((dir (file-name-as-directory dir))
         (nov (concat dir nndiary-nov-file-name))
-        (nov-buffer (get-buffer-create " *nov*"))
+        (nov-buffer (gnus-get-buffer-create " *nov*"))
         chars file headers)
     ;; Init the nov buffer.
     (with-current-buffer nov-buffer
diff --git a/lisp/gnus/nndoc.el b/lisp/gnus/nndoc.el
index 0ba6391..36b67a8 100644
--- a/lisp/gnus/nndoc.el
+++ b/lisp/gnus/nndoc.el
@@ -347,7 +347,7 @@ from the document.")
               (file-exists-p nndoc-address)
               (not (file-directory-p nndoc-address))))
       (push (cons group (setq nndoc-current-buffer
-                             (get-buffer-create
+                             (gnus-get-buffer-create
                               (concat " *nndoc " group "*"))))
            nndoc-group-alist)
       (setq nndoc-dissection-alist nil)
diff --git a/lisp/gnus/nndraft.el b/lisp/gnus/nndraft.el
index 3ee86a6..e5dda99 100644
--- a/lisp/gnus/nndraft.el
+++ b/lisp/gnus/nndraft.el
@@ -231,7 +231,7 @@ are generated if and only if they are also in 
`message-draft-headers'."
 (deffoo nndraft-request-move-article (article group server accept-form
                                      &optional last move-is-internal)
   (nndraft-possibly-change-group group)
-  (let ((buf (get-buffer-create " *nndraft move*"))
+  (let ((buf (gnus-get-buffer-create " *nndraft move*"))
        result)
     (and
      (nndraft-request-article article group server)
@@ -325,7 +325,7 @@ are generated if and only if they are also in 
`message-draft-headers'."
   (save-excursion
     (prog1
        (progn
-         (set-buffer (get-buffer-create " *draft tmp*"))
+         (set-buffer (gnus-get-buffer-create " *draft tmp*"))
          (setq buffer-file-name file)
          (make-auto-save-file-name))
       (kill-buffer (current-buffer)))))
diff --git a/lisp/gnus/nneething.el b/lisp/gnus/nneething.el
index 9e19051..9f1fdba 100644
--- a/lisp/gnus/nneething.el
+++ b/lisp/gnus/nneething.el
@@ -381,7 +381,7 @@ included.")
 
 (defun nneething-get-head (file)
   "Either find the head in FILE or make a head for FILE."
-  (with-current-buffer (get-buffer-create nneething-work-buffer)
+  (with-current-buffer (gnus-get-buffer-create nneething-work-buffer)
     (setq case-fold-search nil)
     (buffer-disable-undo)
     (erase-buffer)
diff --git a/lisp/gnus/nnfolder.el b/lisp/gnus/nnfolder.el
index 342ac48..d1eeb04 100644
--- a/lisp/gnus/nnfolder.el
+++ b/lisp/gnus/nnfolder.el
@@ -465,7 +465,7 @@ all.  This may very well take some time.")
 (deffoo nnfolder-request-move-article (article group server accept-form
                                               &optional last move-is-internal)
   (save-excursion
-    (let ((buf (get-buffer-create " *nnfolder move*"))
+    (let ((buf (gnus-get-buffer-create " *nnfolder move*"))
          result)
       (and
        (nnfolder-request-article article group server)
@@ -1096,7 +1096,7 @@ This command does not work if you use short group names."
 
 (defun nnfolder-open-nov (group)
   (or (cdr (assoc group nnfolder-nov-buffer-alist))
-      (let ((buffer (get-buffer-create (format " *nnfolder overview %s*" 
group))))
+      (let ((buffer (gnus-get-buffer-create (format " *nnfolder overview %s*" 
group))))
        (with-current-buffer buffer
          (set (make-local-variable 'nnfolder-nov-buffer-file-name)
               (nnfolder-group-nov-pathname group))
diff --git a/lisp/gnus/nnheader.el b/lisp/gnus/nnheader.el
index bf3a5c1..199d524 100644
--- a/lisp/gnus/nnheader.el
+++ b/lisp/gnus/nnheader.el
@@ -502,10 +502,12 @@ the line could be found."
   "Coding system used in file backends of Gnus.")
 (defvar nnheader-callback-function nil)
 
+(autoload 'gnus-get-buffer-create "gnus")
+
 (defun nnheader-init-server-buffer ()
   "Initialize the Gnus-backend communication buffer."
   (unless (gnus-buffer-live-p nntp-server-buffer)
-    (setq nntp-server-buffer (get-buffer-create " *nntpd*")))
+    (setq nntp-server-buffer (gnus-get-buffer-create " *nntpd*")))
   (with-current-buffer nntp-server-buffer
     (erase-buffer)
     (mm-enable-multibyte)
@@ -630,7 +632,7 @@ the line could be found."
 
 (defun nnheader-set-temp-buffer (name &optional noerase)
   "Set-buffer to an empty (possibly new) buffer called NAME with undo 
disabled."
-  (set-buffer (get-buffer-create name))
+  (set-buffer (gnus-get-buffer-create name))
   (buffer-disable-undo)
   (unless noerase
     (erase-buffer))
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index c383e01..3c4e75e 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -1937,7 +1937,7 @@ Return the server's response to the SELECT or EXAMINE 
command."
 (defun nnimap-log-buffer ()
   (let ((name "*imap log*"))
     (or (get-buffer name)
-        (with-current-buffer (get-buffer-create name)
+        (with-current-buffer (gnus-get-buffer-create name)
          (setq-local window-point-insertion-type t)
           (current-buffer)))))
 
diff --git a/lisp/gnus/nnir.el b/lisp/gnus/nnir.el
index 823bc2b..0f364d6 100644
--- a/lisp/gnus/nnir.el
+++ b/lisp/gnus/nnir.el
@@ -1234,7 +1234,7 @@ Windows NT 4.0."
       (when (equal "" qstring)
         (error "swish++: You didn't enter anything"))
 
-      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (set-buffer (gnus-get-buffer-create nnir-tmp-buffer))
       (erase-buffer)
 
       (if groupspec
@@ -1316,7 +1316,7 @@ Tested with swish-e-2.0.1 on Windows NT 4.0."
       (when (equal "" qstring)
         (error "swish-e: You didn't enter anything"))
 
-      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (set-buffer (gnus-get-buffer-create nnir-tmp-buffer))
       (erase-buffer)
 
       (message "Doing swish-e query %s..." query)
@@ -1401,7 +1401,7 @@ Tested with swish-e-2.0.1 on Windows NT 4.0."
         (setq groupspec
              (regexp-opt
               (mapcar (lambda (x) (gnus-group-real-name x)) group))))
-      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (set-buffer (gnus-get-buffer-create nnir-tmp-buffer))
       (erase-buffer)
       (message "Doing hyrex-search query %s..." query)
       (let* ((cp-list
@@ -1480,7 +1480,7 @@ Tested with Namazu 2.0.6 on a GNU/Linux system."
           score group article
           (process-environment (copy-sequence process-environment)))
       (setenv "LC_MESSAGES" "C")
-      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (set-buffer (gnus-get-buffer-create nnir-tmp-buffer))
       (erase-buffer)
       (let* ((cp-list
               `( ,nnir-namazu-program
@@ -1561,7 +1561,7 @@ construct path: search terms (see the variable
       (when (equal "" qstring)
         (error "notmuch: You didn't enter anything"))
 
-      (set-buffer (get-buffer-create nnir-tmp-buffer))
+      (set-buffer (gnus-get-buffer-create nnir-tmp-buffer))
       (erase-buffer)
 
       (if groups
@@ -1635,7 +1635,7 @@ construct path: search terms (see the variable
                 (message "Searching %s using find-grep..."
                          (or group server))
                 (save-window-excursion
-                  (set-buffer (get-buffer-create nnir-tmp-buffer))
+                  (set-buffer (gnus-get-buffer-create nnir-tmp-buffer))
                   (if (> gnus-verbose 6)
                       (pop-to-buffer (current-buffer)))
                   (cd directory) ; Using relative paths simplifies
diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el
index d64d0ed..6e01b5c 100644
--- a/lisp/gnus/nnmail.el
+++ b/lisp/gnus/nnmail.el
@@ -1047,7 +1047,7 @@ will be copied over from that buffer."
                                  (list (list group ""))
                                nnmail-split-methods)))
     ;; Insert the incoming file.
-    (with-current-buffer (get-buffer-create nnmail-article-buffer)
+    (with-current-buffer (gnus-get-buffer-create nnmail-article-buffer)
       (erase-buffer)
       (if (bufferp incoming)
          (insert-buffer-substring incoming)
@@ -1574,7 +1574,7 @@ See the documentation for the variable 
`nnmail-split-fancy' for details."
       ()                               ; The buffer is open.
     (with-current-buffer
        (setq nnmail-cache-buffer
-            (get-buffer-create " *nnmail message-id cache*"))
+            (gnus-get-buffer-create " *nnmail message-id cache*"))
       (gnus-add-buffer)
       (when (file-exists-p nnmail-message-id-cache-file)
        (nnheader-insert-file-contents nnmail-message-id-cache-file))
@@ -2065,7 +2065,7 @@ Doesn't change point."
   (when nnmail-split-tracing
     (push split nnmail-split-trace))
   (when nnmail-debug-splitting
-    (with-current-buffer (get-buffer-create "*nnmail split*")
+    (with-current-buffer (gnus-get-buffer-create "*nnmail split*")
       (goto-char (point-max))
       (insert (format-time-string "%FT%T")
              " "
diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el
index b0e79d4..bf1ac31 100644
--- a/lisp/gnus/nnmaildir.el
+++ b/lisp/gnus/nnmaildir.el
@@ -269,15 +269,15 @@ This variable is set by `nnmaildir-request-article'.")
      ,@body))
 (defmacro nnmaildir--with-work-buffer (&rest body)
   (declare (debug (body)))
-  `(with-current-buffer (get-buffer-create " *nnmaildir work*")
+  `(with-current-buffer (gnus-get-buffer-create " *nnmaildir work*")
      ,@body))
 (defmacro nnmaildir--with-nov-buffer (&rest body)
   (declare (debug (body)))
-  `(with-current-buffer (get-buffer-create " *nnmaildir nov*")
+  `(with-current-buffer (gnus-get-buffer-create " *nnmaildir nov*")
      ,@body))
 (defmacro nnmaildir--with-move-buffer (&rest body)
   (declare (debug (body)))
-  `(with-current-buffer (get-buffer-create " *nnmaildir move*")
+  `(with-current-buffer (gnus-get-buffer-create " *nnmaildir move*")
      ,@body))
 
 (defsubst nnmaildir--subdir (dir subdir)
diff --git a/lisp/gnus/nnmairix.el b/lisp/gnus/nnmairix.el
index b332921..dcecfcf 100644
--- a/lisp/gnus/nnmairix.el
+++ b/lisp/gnus/nnmairix.el
@@ -1249,7 +1249,7 @@ Marks propagation has to be enabled for this to work."
 If THREADS is non-nil, enable full threads."
   (let ((args (cons (car command) '(nil t nil))))
     (with-current-buffer
-       (get-buffer-create nnmairix-mairix-output-buffer)
+       (gnus-get-buffer-create nnmairix-mairix-output-buffer)
       (erase-buffer)
       (when (> (length command) 1)
        (setq args (append args (cdr command))))
@@ -1267,7 +1267,7 @@ If THREADS is non-nil, enable full threads."
   "Call mairix binary with COMMAND and QUERY in raw mode."
   (let ((args (cons (car command) '(nil t nil))))
     (with-current-buffer
-       (get-buffer-create nnmairix-mairix-output-buffer)
+       (gnus-get-buffer-create nnmairix-mairix-output-buffer)
       (erase-buffer)
       (when (> (length command) 1)
         (setq args (append args (cdr command))))
@@ -1404,7 +1404,7 @@ TYPE is either `nov' or `headers'."
   (nnheader-message 7 "nnmairix: Rewriting headers...")
   (cond
    ((eq type 'nov)
-    (let ((buf (get-buffer-create " *nnmairix buffer*"))
+    (let ((buf (gnus-get-buffer-create " *nnmairix buffer*"))
          (corr (not (zerop numc)))
          (name (buffer-name nntp-server-buffer))
          header cur xref)
diff --git a/lisp/gnus/nnmbox.el b/lisp/gnus/nnmbox.el
index eb8fcf3..a191f88 100644
--- a/lisp/gnus/nnmbox.el
+++ b/lisp/gnus/nnmbox.el
@@ -280,7 +280,7 @@
 
 (deffoo nnmbox-request-move-article
     (article group server accept-form &optional last move-is-internal)
-  (let ((buf (get-buffer-create " *nnmbox move*"))
+  (let ((buf (gnus-get-buffer-create " *nnmbox move*"))
        result)
     (and
      (nnmbox-request-article article group server)
diff --git a/lisp/gnus/nnmh.el b/lisp/gnus/nnmh.el
index c075f29..d2f63bd 100644
--- a/lisp/gnus/nnmh.el
+++ b/lisp/gnus/nnmh.el
@@ -296,7 +296,7 @@ as unread by Gnus.")
 
 (deffoo nnmh-request-move-article (article group server accept-form
                                           &optional last move-is-internal)
-  (let ((buf (get-buffer-create " *nnmh move*"))
+  (let ((buf (gnus-get-buffer-create " *nnmh move*"))
        result)
     (and
      (nnmh-deletable-article-p group article)
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el
index 6c7b25b..2c39ab8 100644
--- a/lisp/gnus/nnml.el
+++ b/lisp/gnus/nnml.el
@@ -361,7 +361,7 @@ non-nil.")
 
 (deffoo nnml-request-move-article
     (article group server accept-form &optional last move-is-internal)
-  (let ((buf (get-buffer-create " *nnml move*"))
+  (let ((buf (gnus-get-buffer-create " *nnml move*"))
        (file-name-coding-system nnmail-pathname-coding-system)
        result)
     (nnml-possibly-change-directory group server)
@@ -572,7 +572,7 @@ non-nil.")
 
 ;; Find an article number in the current group given the Message-ID.
 (defun nnml-find-group-number (id server)
-  (with-current-buffer (get-buffer-create " *nnml id*")
+  (with-current-buffer (gnus-get-buffer-create " *nnml id*")
     (let ((alist nnml-group-alist)
          number)
       ;; We want to look through all .overview files, but we want to
@@ -772,11 +772,10 @@ article number.  This function is called narrowed to an 
article."
        headers))))
 
 (defun nnml-get-nov-buffer (group &optional incrementalp)
-  (let ((buffer (get-buffer-create (format " *nnml %soverview %s*"
-                                           (if incrementalp
-                                               "incremental "
-                                             "")
-                                           group)))
+  (let ((buffer (gnus-get-buffer-create
+                 (format " *nnml %soverview %s*"
+                        (if incrementalp "incremental " "")
+                        group)))
         (file-name-coding-system nnmail-pathname-coding-system))
     (with-current-buffer buffer
       (set (make-local-variable 'nnml-nov-buffer-file-name)
@@ -873,7 +872,7 @@ Unless no-active is non-nil, update the active file too."
 (defun nnml-generate-nov-file (dir files)
   (let* ((dir (file-name-as-directory dir))
         (nov (concat dir nnml-nov-file-name))
-        (nov-buffer (get-buffer-create " *nov*"))
+        (nov-buffer (gnus-get-buffer-create " *nov*"))
         chars file headers)
     (with-current-buffer nov-buffer
       ;; Init the nov buffer.
diff --git a/lisp/gnus/nnrss.el b/lisp/gnus/nnrss.el
index fa4d22f..116d7ee 100644
--- a/lisp/gnus/nnrss.el
+++ b/lisp/gnus/nnrss.el
@@ -739,7 +739,7 @@ Read the file and attempt to subscribe to each Feed in the 
file."
   "OPML subscription export.
 Export subscriptions to a buffer in OPML Format."
   (interactive)
-  (with-current-buffer (get-buffer-create "*OPML Export*")
+  (with-current-buffer (gnus-get-buffer-create "*OPML Export*")
     (set-buffer-file-coding-system 'utf-8)
     (insert "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
            "<!-- OPML generated by Emacs Gnus' nnrss.el -->\n"
diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el
index 6ce8724..6be6d11 100644
--- a/lisp/gnus/nntp.el
+++ b/lisp/gnus/nntp.el
@@ -309,7 +309,7 @@ backend doesn't catch this error.")
 
 (defun nntp-record-command (string)
   "Record the command STRING."
-  (with-current-buffer (get-buffer-create "*nntp-log*")
+  (with-current-buffer (gnus-get-buffer-create "*nntp-log*")
     (goto-char (point-max))
     (insert (format-time-string "%Y%m%dT%H%M%S.%3N")
            " " nntp-address " " string "\n")))
diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el
index e1290a9..54c2f7b 100644
--- a/lisp/gnus/nnvirtual.el
+++ b/lisp/gnus/nnvirtual.el
@@ -97,7 +97,7 @@ component group will show up when you enter the virtual 
group.")
       (if (stringp (car articles))
          'headers
        (let ((vbuf (nnheader-set-temp-buffer
-                    (get-buffer-create " *virtual headers*")))
+                    (gnus-get-buffer-create " *virtual headers*")))
              (carticles (nnvirtual-partition-sequence articles))
              (sysname (system-name))
              cgroup carticle article result prefix)
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index afa5c9b..2b7534b 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -1564,6 +1564,103 @@ BUFFER should be a buffer or a buffer name."
          (insert "\nThe parent category table is:")
          (describe-vector table 'help-describe-category-set))))))
 
+(defun help-fns-find-keymap-name (keymap)
+  "Find the name of the variable with value KEYMAP.
+Return nil if KEYMAP is not a valid keymap, or if there is no
+variable with value KEYMAP."
+  (when (keymapp keymap)
+    (let ((name (catch 'found-keymap
+                  (mapatoms (lambda (symb)
+                              (when (and (boundp symb)
+                                         (eq (symbol-value symb) keymap)
+                                         (not (eq symb 'keymap))
+                                         (throw 'found-keymap symb)))))
+                  nil)))
+      ;; Follow aliasing.
+      (or (ignore-errors (indirect-variable name)) name))))
+
+(defun help-fns--most-relevant-active-keymap ()
+  "Return the name of the most relevant active keymap.
+The heuristic to determine which keymap is most likely to be
+relevant to a user follows this order:
+
+1. 'keymap' text property at point
+2. 'local-map' text property at point
+3. the `current-local-map'
+
+This is used to set the default value for the interactive prompt
+in `describe-keymap'.  See also `Searching the Active Keymaps'."
+  (help-fns-find-keymap-name (or (get-char-property (point) 'keymap)
+                         (if (get-text-property (point) 'local-map)
+                             (get-char-property (point) 'local-map)
+                           (current-local-map)))))
+
+;;;###autoload
+(defun describe-keymap (keymap)
+  "Describe key bindings in KEYMAP.
+When called interactively, prompt for a variable that has a
+keymap value."
+  (interactive
+   (let* ((km (help-fns--most-relevant-active-keymap))
+          (val (completing-read
+                (format "Keymap (default %s): " km)
+                obarray
+                (lambda (m) (and (boundp m) (keymapp (symbol-value m))))
+                t nil 'keymap-name-history
+                (symbol-name km))))
+     (unless (equal val "")
+       (setq km (intern val)))
+     (unless (and km (keymapp (symbol-value km)))
+       (user-error "Not a keymap: %s" km))
+     (list km)))
+  (let (used-gentemp)
+    (unless (and (symbolp keymap)
+                 (boundp keymap)
+                 (keymapp (symbol-value keymap)))
+      (when (not (keymapp keymap))
+        (if (symbolp keymap)
+            (error "Not a keymap variable: %S" keymap)
+          (error "Not a keymap")))
+      (let ((sym nil))
+        (unless sym
+          (setq sym (cl-gentemp "KEYMAP OBJECT (no variable) "))
+          (setq used-gentemp t)
+          (set sym keymap))
+        (setq keymap sym)))
+    ;; Follow aliasing.
+    (setq keymap (or (ignore-errors (indirect-variable keymap)) keymap))
+    (help-setup-xref (list #'describe-keymap keymap)
+                     (called-interactively-p 'interactive))
+    (let* ((name (symbol-name keymap))
+           (doc (documentation-property keymap 'variable-documentation))
+           (file-name (find-lisp-object-file-name keymap 'defvar)))
+      (with-help-window (help-buffer)
+        (with-current-buffer standard-output
+          (unless used-gentemp
+            (princ (format-message "%S is a keymap variable" keymap))
+            (if (not file-name)
+                (princ ".\n\n")
+              (princ (format-message
+                      " defined in `%s'.\n\n"
+                      (if (eq file-name 'C-source)
+                          "C source code"
+                        (file-name-nondirectory file-name))))
+              (save-excursion
+                (re-search-backward (substitute-command-keys
+                                     "`\\([^`']+\\)'")
+                                    nil t)
+                (help-xref-button 1 'help-variable-def
+                                  keymap file-name))))
+          (when (and (not (equal "" doc)) doc)
+            (princ "Documentation:\n")
+            (princ (format-message "%s\n\n" doc)))
+          ;; Use `insert' instead of `princ', so control chars (e.g. \377)
+          ;; insert correctly.
+          (insert (substitute-command-keys (concat "\\{" name "}"))))))
+    ;; Cleanup.
+    (when used-gentemp
+      (makunbound keymap))))
+
 
 ;;; Replacements for old lib-src/ programs.  Don't seem especially useful.
 
diff --git a/lisp/hexl.el b/lisp/hexl.el
index 2535d58..58518e7 100644
--- a/lisp/hexl.el
+++ b/lisp/hexl.el
@@ -701,10 +701,7 @@ With prefix arg N, puts point N bytes of the way from the 
true beginning."
 (defun hexl-end-of-line ()
   "Goto end of line in Hexl mode."
   (interactive)
-  (hexl-goto-address (let ((address (logior (hexl-current-address) 15)))
-                      (if (> address hexl-max-address)
-                          (setq address hexl-max-address))
-                      address)))
+  (hexl-goto-address (min hexl-max-address (logior (hexl-current-address) 
15))))
 
 (defun hexl-scroll-down (arg)
   "Scroll hexl buffer window upward ARG lines; or near full window if no ARG."
@@ -749,7 +746,7 @@ If there's no byte at the target address, move to the first 
or last line."
   "Go to end of 1KB boundary."
   (interactive)
   (hexl-goto-address
-   (max hexl-max-address (logior (hexl-current-address) 1023))))
+   (min hexl-max-address (logior (hexl-current-address) 1023))))
 
 (defun hexl-beginning-of-512b-page ()
   "Go to beginning of 512 byte boundary."
@@ -760,7 +757,7 @@ If there's no byte at the target address, move to the first 
or last line."
   "Go to end of 512 byte boundary."
   (interactive)
   (hexl-goto-address
-   (max hexl-max-address (logior (hexl-current-address) 511))))
+   (min hexl-max-address (logior (hexl-current-address) 511))))
 
 (defun hexl-quoted-insert (arg)
   "Read next input character and insert it.
@@ -935,7 +932,7 @@ CH must be a unibyte character whose value is between 0 and 
255."
        (goto-char ascii-position)
        (delete-char 1)
        (insert (hexl-printable-character ch))
-       (or (eq address hexl-max-address)
+       (or (= address hexl-max-address)
            (setq address (1+ address)))
        (hexl-goto-address address)
        (if at-ascii-position
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el
index 851b25f..c9a7488 100644
--- a/lisp/ibuffer.el
+++ b/lisp/ibuffer.el
@@ -339,6 +339,8 @@ directory, like `default-directory'."
 (defcustom ibuffer-load-hook nil
   "Hook run when Ibuffer is loaded."
   :type 'hook)
+(make-obsolete-variable 'ibuffer-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defcustom ibuffer-marked-face 'warning
   "Face used for displaying marked buffers."
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index e7e8cbf..a1a67e2 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -448,13 +448,14 @@ Usually run by inclusion in `minibuffer-setup-hook'."
        with end = (icomplete--field-end)
        with all = (completion-all-sorted-completions beg end)
        for fn in (cond ((and minibuffer-default
+                             (stringp minibuffer-default) ; bug#38992
                              (= (icomplete--field-end) (icomplete--field-beg)))
-                        ;; When we have a non-nil default and no input
-                        ;; whatsoever: we want to make sure that default
-                        ;; is bubbled to the top so that
+                        ;; When we have a non-nil string default and
+                        ;; no input whatsoever: we want to make sure
+                        ;; that default is bubbled to the top so that
                         ;; `icomplete-force-complete-and-exit' will
-                        ;; select it (do that even if the match doesn't
-                        ;; match the completion perfectly.
+                        ;; select it (do that even if the match
+                        ;; doesn't match the completion perfectly.
                         `(,(lambda (comp)
                              (equal minibuffer-default comp))
                           ,(lambda (comp)
@@ -462,6 +463,12 @@ Usually run by inclusion in `minibuffer-setup-hook'."
                        ((and fido-mode
                              (not minibuffer-default)
                              (eq (icomplete--category) 'file))
+                        ;; `fido-mode' has some extra file-sorting
+                        ;; semantics even if there isn't a default,
+                        ;; which is to bubble "./" to the top if it
+                        ;; exists.  This makes M-x dired RET RET go to
+                        ;; the directory of current file, which is
+                        ;; what vanilla Emacs and `ido-mode' both do.
                         `(,(lambda (comp)
                              (string= "./" comp)))))
        thereis (cl-loop
diff --git a/lisp/ido.el b/lisp/ido.el
index 83b88e4..355be5e 100644
--- a/lisp/ido.el
+++ b/lisp/ido.el
@@ -4492,6 +4492,8 @@ For details of keybindings, see `ido-find-file'."
        (ido-tidy))
       (throw 'ido contents))))
 
+(defvar ido--overlay nil)
+
 (defun ido-exhibit ()
   "Post command hook for Ido."
   ;; Find matching files and display a list in the minibuffer.
@@ -4726,7 +4728,13 @@ For details of keybindings, see `ido-find-file'."
        (let ((inf (ido-completions contents)))
          (setq ido-show-confirm-message nil)
          (ido-trace "inf" inf)
-         (insert inf))
+          (when ido--overlay
+            (delete-overlay ido--overlay))
+          (let ((o (make-overlay (point-max) (point-max) nil t t)))
+            (when (> (length inf) 0)
+              (put-text-property 0 1 'cursor t inf))
+            (overlay-put o 'after-string inf)
+            (setq ido--overlay o)))
        ))))
 
 (defun ido-completions (name)
diff --git a/lisp/image-dired.el b/lisp/image-dired.el
index 7774b82..768e941 100644
--- a/lisp/image-dired.el
+++ b/lisp/image-dired.el
@@ -1980,20 +1980,12 @@ With prefix argument ARG, display image in its original 
size."
       (clear-image-cache thumb))))
 
 (defun image-dired-rotate-thumbnail-left ()
-  "Rotate thumbnail left (counter clockwise) 90 degrees.
-The result of the rotation is displayed in the image display area
-and a confirmation is needed before the original image files is
-overwritten.  This confirmation can be turned off using
-`image-dired-rotate-original-ask-before-overwrite'."
+  "Rotate thumbnail left (counter clockwise) 90 degrees."
   (interactive)
   (image-dired-rotate-thumbnail "270"))
 
 (defun image-dired-rotate-thumbnail-right ()
-  "Rotate thumbnail counter right (clockwise) 90 degrees.
-The result of the rotation is displayed in the image display area
-and a confirmation is needed before the original image files is
-overwritten.  This confirmation can be turned off using
-`image-dired-rotate-original-ask-before-overwrite'."
+  "Rotate thumbnail counter right (clockwise) 90 degrees."
   (interactive)
   (image-dired-rotate-thumbnail "90"))
 
@@ -2035,12 +2027,20 @@ overwritten.  This confirmation can be turned off using
           (image-dired-display-image file))))))
 
 (defun image-dired-rotate-original-left ()
-  "Rotate original image left (counter clockwise) 90 degrees."
+  "Rotate original image left (counter clockwise) 90 degrees.
+The result of the rotation is displayed in the image display area
+and a confirmation is needed before the original image files is
+overwritten.  This confirmation can be turned off using
+`image-dired-rotate-original-ask-before-overwrite'."
   (interactive)
   (image-dired-rotate-original "270"))
 
 (defun image-dired-rotate-original-right ()
-  "Rotate original image right (clockwise) 90 degrees."
+  "Rotate original image right (clockwise) 90 degrees.
+The result of the rotation is displayed in the image display area
+and a confirmation is needed before the original image files is
+overwritten.  This confirmation can be turned off using
+`image-dired-rotate-original-ask-before-overwrite'."
   (interactive)
   (image-dired-rotate-original "90"))
 
diff --git a/lisp/info.el b/lisp/info.el
index 7a11bb3..3015e60 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -3780,20 +3780,8 @@ Build a menu of the possible matches."
     ;; there is no "nxml.el" (it's nxml-mode.el).
     ;; But package.el makes the same assumption.
     ;; I think nxml is the only exception - maybe it should be just be renamed.
-    (let ((str (ignore-errors (lm-commentary (find-library-name nodename)))))
-      (if (null str)
-         (insert "Can’t find package description.\n\n")
-       (insert
-        (with-temp-buffer
-          (insert str)
-          (goto-char (point-min))
-          (delete-blank-lines)
-          (goto-char (point-max))
-          (delete-blank-lines)
-          (goto-char (point-min))
-          (while (re-search-forward "^;+ ?" nil t)
-            (replace-match "" nil nil))
-          (buffer-string))))))))
+    (insert (or (ignore-errors (lm-commentary (find-library-name nodename)))
+                (insert "Can’t find package description.\n\n"))))))
 
 ;;;###autoload
 (defun info-finder (&optional keywords)
@@ -5135,9 +5123,8 @@ first line or header line, and for breadcrumb links.")
   "Additional menu-items to add to speedbar frame.")
 
 ;; Make sure our special speedbar major mode is loaded
-(if (featurep 'speedbar)
-    (Info-install-speedbar-variables)
-  (add-hook 'speedbar-load-hook 'Info-install-speedbar-variables))
+(with-eval-after-load 'speedbar
+  (Info-install-speedbar-variables))
 
 ;;; Info hierarchy display method
 ;;;###autoload
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index c86b1da..5436aaa 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -283,8 +283,42 @@ wrong, use this command again to toggle back to the right 
mode."
   (interactive)
   (view-file (expand-file-name "HELLO" data-directory)))
 
+(defvar mule-cmds--prefixed-command-next-coding-system nil)
+(defvar mule-cmds--prefixed-command-last-coding-system nil)
+
+(defun mule-cmds--prefixed-command-pch ()
+  (if (not mule-cmds--prefixed-command-next-coding-system)
+      (progn
+        (remove-hook 'pre-command-hook #'mule-cmds--prefixed-command-pch)
+        (remove-hook 'prefix-command-echo-keystrokes-functions
+                     #'mule-cmds--prefixed-command-echo)
+        (remove-hook 'prefix-command-preserve-state-hook
+                     #'mule-cmds--prefixed-command-preserve))
+    (setq this-command
+          (let ((cmd this-command)
+                (coding-system mule-cmds--prefixed-command-next-coding-system))
+            (lambda ()
+              (interactive)
+              (setq this-command cmd)
+              (let ((coding-system-for-read coding-system)
+                   (coding-system-for-write coding-system)
+                   (coding-system-require-warning t))
+               (call-interactively cmd)))))
+    (setq mule-cmds--prefixed-command-last-coding-system
+          mule-cmds--prefixed-command-next-coding-system)
+    (setq mule-cmds--prefixed-command-next-coding-system nil)))
+
+(defun mule-cmds--prefixed-command-echo ()
+  (when mule-cmds--prefixed-command-next-coding-system
+    (format "With coding-system %S"
+            mule-cmds--prefixed-command-next-coding-system)))
+
+(defun mule-cmds--prefixed-command-preserve ()
+  (setq mule-cmds--prefixed-command-next-coding-system
+        mule-cmds--prefixed-command-last-coding-system))
+
 (defun universal-coding-system-argument (coding-system)
-  "Execute an I/O command using the specified coding system."
+  "Execute an I/O command using the specified CODING-SYSTEM."
   (interactive
    (let ((default (and buffer-file-coding-system
                       (not (eq (coding-system-type buffer-file-coding-system)
@@ -295,41 +329,13 @@ wrong, use this command again to toggle back to the right 
mode."
                (format "Coding system for following command (default %s): " 
default)
              "Coding system for following command: ")
            default))))
-  ;; FIXME: This "read-key-sequence + call-interactively" loop is trying to
-  ;; reproduce the normal command loop, but this "can't" be done faithfully so
-  ;; it necessarily suffers from breakage in corner cases (e.g. it fails to run
-  ;; pre/post-command-hook, doesn't properly set this-command/last-command, it
-  ;; doesn't handle keyboard macros, ...).
-  (let* ((keyseq (read-key-sequence
-                 (format "Command to execute with %s:" coding-system)))
-        (cmd (key-binding keyseq)))
-    ;; read-key-sequence ignores quit, so make an explicit check.
-    (if (equal last-input-event (nth 3 (current-input-mode)))
-       (keyboard-quit))
-    (when (memq cmd '(universal-argument digit-argument))
-      (call-interactively cmd)
-
-      ;; Process keys bound in `universal-argument-map'.
-      (while (progn
-              (setq keyseq (read-key-sequence nil t)
-                    cmd (key-binding keyseq t))
-              (memq cmd '(negative-argument digit-argument
-                          universal-argument-more)))
-       (setq current-prefix-arg prefix-arg prefix-arg nil)
-       ;; Have to bind `last-command-event' here so that
-       ;; `digit-argument', for instance, can compute the
-       ;; `prefix-arg'.
-       (setq last-command-event (aref keyseq 0))
-       (call-interactively cmd)))
-
-    (let ((coding-system-for-read coding-system)
-         (coding-system-for-write coding-system)
-         (coding-system-require-warning t))
-      (setq current-prefix-arg prefix-arg prefix-arg nil)
-      ;; Have to bind `last-command-event' e.g. for `self-insert-command'.
-      (setq last-command-event (aref keyseq 0))
-      (message "")
-      (call-interactively cmd))))
+  (prefix-command-preserve-state)
+  (setq mule-cmds--prefixed-command-next-coding-system coding-system)
+  (add-hook 'pre-command-hook #'mule-cmds--prefixed-command-pch)
+  (add-hook 'prefix-command-echo-keystrokes-functions
+            #'mule-cmds--prefixed-command-echo)
+  (add-hook 'prefix-command-preserve-state-hook
+            #'mule-cmds--prefixed-command-preserve))
 
 (defun set-default-coding-systems (coding-system)
   "Set default value of various coding systems to CODING-SYSTEM.
@@ -700,8 +706,8 @@ DEFAULT is the coding system to use by default in the 
query."
       ;; buffer is displayed.
       (when (and unsafe (not (stringp from)))
        (pop-to-buffer bufname)
-       (goto-char (apply 'min (mapcar #'(lambda (x) (car (cadr x)))
-                                      unsafe))))
+       (goto-char (apply #'min (mapcar (lambda (x) (or (car (cadr x)) 
(point-max)))
+                                       unsafe))))
       ;; Then ask users to select one from CODINGS while showing
       ;; the reason why none of the defaults are not used.
       (with-output-to-temp-buffer "*Warning*"
@@ -1402,13 +1408,13 @@ The commands `describe-input-method' and 
`list-input-methods' need
 these duplicated values to show some information about input methods
 without loading the relevant Quail packages.
 \n(fn INPUT-METHOD LANG-ENV ACTIVATE-FUNC TITLE DESCRIPTION &rest ARGS)"
-  (if (symbolp lang-env)
-      (setq lang-env (symbol-name lang-env))
-    (setq lang-env (purecopy lang-env)))
-  (if (symbolp input-method)
-      (setq input-method (symbol-name input-method))
-    (setq input-method (purecopy input-method)))
-  (setq args (mapcar 'purecopy args))
+  (setq lang-env (if (symbolp lang-env)
+                     (symbol-name lang-env)
+                   (purecopy lang-env)))
+  (setq input-method (if (symbolp input-method)
+                         (symbol-name input-method)
+                       (purecopy input-method)))
+  (setq args (mapcar #'purecopy args))
   (let ((info (cons lang-env args))
        (slot (assoc input-method input-method-alist)))
     (if slot
diff --git a/lisp/international/titdic-cnv.el b/lisp/international/titdic-cnv.el
index 2a80d75..eec20ee 100644
--- a/lisp/international/titdic-cnv.el
+++ b/lisp/international/titdic-cnv.el
@@ -1,4 +1,4 @@
-;;; titdic-cnv.el --- convert cxterm dictionary (TIT format) to Quail package 
-*- coding: utf-8-emacs; lexical-binding:t -*-
+;;; titdic-cnv.el --- convert cxterm dictionary (TIT format) to Quail package 
-*- coding:iso-2022-7bit; lexical-binding:t -*-
 
 ;; Copyright (C) 1997-1998, 2000-2020 Free Software Foundation, Inc.
 ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
@@ -83,9 +83,9 @@
 ;; how to select a translation from a list of candidates.
 
 (defvar quail-cxterm-package-ext-info
-  '(("chinese-4corner" "四角")
-    ("chinese-array30" "30")
-    ("chinese-ccdospy" "缩拼"
+  '(("chinese-4corner" "$(0(?-F(B")
+    ("chinese-array30" "$(0#R#O(B")
+    ("chinese-ccdospy" "$AKuF4(B"
      "Pinyin base input method for Chinese charset GB2312 (`chinese-gb2312').
 
 Pinyin is the standard Roman transliteration method for Chinese.
@@ -94,10 +94,10 @@ method `chinese-py'.
 
 This input method works almost the same way as `chinese-py'.  The
 difference is that you type a single key for these Pinyin spelling.
-    Pinyin:  zh  en  eng ang ch  an  ao  ai  ong sh  ing  yu(ü)
+    Pinyin:  zh  en  eng ang ch  an  ao  ai  ong sh  ing  yu($A(9(B)
     keyseq:   a   f   g   h   i   j   k   l   s   u   y   v
 For example:
-    Chinese:  啊    果    中    文    光    玉    全
+    Chinese:  $A0!(B    $A9{(B    $AVP(B    $AND(B    $A9b(B    
$ASq(B    $AH+(B
     Pinyin:   a    guo   zhong  wen  guang  yu   quan
     Keyseq:   a1   guo4   as1   wf4  guh1  yu..6 qvj6
 
@@ -106,14 +106,14 @@ For example:
 For double-width GB2312 characters corresponding to ASCII, use the
 input method `chinese-qj'.")
 
-    ("chinese-ecdict" "英漢"
+    ("chinese-ecdict" "$(05CKH(B"
 "In this input method, you enter a Chinese (Big5) character or word
 by typing the corresponding English word.  For example, if you type
-\"computer\", \"電腦\" is input.
+\"computer\", \"$(0IZH+(B\" is input.
 
 \\<quail-translation-docstring>")
 
-    ("chinese-etzy" "倚注"
+    ("chinese-etzy" "$(06/0D(B"
 "Zhuyin base input method for Chinese Big5 characters (`chinese-big5-1',
 `chinese-big5-2').
 
@@ -122,20 +122,20 @@ compose one Chinese character.
 
 In this input method, you enter a Chinese character by first typing
 keys corresponding to Zhuyin symbols (see the above table) followed by
-SPC, 1, 2, 3, or 4 specifying a tone (SPC:陰平, 1:輕聲, 2:陽平, 3: 上聲,
-4:去聲).
+SPC, 1, 2, 3, or 4 specifying a tone (SPC:$(0?v(N(B, 1:$(0M=Vy(B, 
2:$(0Dm(N(B, 3: $(0&9Vy(B,
+4:$(0(+Vy(B).
 
 \\<quail-translation-docstring>")
 
-    ("chinese-punct-b5" "標B"
+    ("chinese-punct-b5" "$(0O:(BB"
      "Input method for Chinese punctuation and symbols of Big5
 \(`chinese-big5-1' and `chinese-big5-2').")
 
-    ("chinese-punct" "标G"
+    ("chinese-punct" "$A1j(BG"
      "Input method for Chinese punctuation and symbols of GB2312
 \(`chinese-gb2312').")
 
-    ("chinese-py-b5" "拼B"
+    ("chinese-py-b5" "$(03<(BB"
      "Pinyin base input method for Chinese Big5 characters
 \(`chinese-big5-1', `chinese-big5-2').
 
@@ -153,28 +153,28 @@ method `chinese-qj-b5'.
 The input method `chinese-py' and `chinese-tonepy' are also Pinyin
 based, but for the character set GB2312 (`chinese-gb2312').")
 
-    ("chinese-qj-b5" "全B")
+    ("chinese-qj-b5" "$(0)A(BB")
 
-    ("chinese-qj" "全G")
+    ("chinese-qj" "$AH+(BG")
 
-    ("chinese-sw" "首尾"
+    ("chinese-sw" "$AJWN2(B"
 "Radical base input method for Chinese charset GB2312 (`chinese-gb2312').
 
 In this input method, you enter a Chinese character by typing two
-keys.  The first key corresponds to the first (首) radical, the second
-key corresponds to the last (尾) radical.  The correspondence of keys
+keys.  The first key corresponds to the first ($AJW(B) radical, the second
+key corresponds to the last ($AN2(B) radical.  The correspondence of keys
 and radicals is as below:
 
  first radical:
  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
- 心 冖 尸 丶 火 口 扌 氵 讠 艹 亻 木 礻 饣 月 纟 石 王 八 丿 日 辶 犭 竹 一 人
+ $APD(B $AZ"(B $AJ,(B $AX<(B $A;p(B $A?Z(B $A^P(B $Ac_(B 
$AZ%(B $A\3(B $AXi(B $AD>(B $Alj(B $Ab;(B $ATB(B $Afy(B 
$AJ/(B $AMu(B $A0K(B $AX/(B $AHU(B $AeA(B $Aak(B $AVq(B 
$AR;(B $AHK(B
  last radical:
  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
- 又 山 土 刀 阝 口 衣 疋 大 丁 厶 灬 十 歹 冂 门 今 丨 女 乙 囗 小 厂 虫 弋 卜
+ $ASV(B $AI=(B $AMA(B $A56(B $AZb(B $A?Z(B $ARB(B $Aqb(B 
$A4s(B $A6!(B $A[L(B $Ala(B $AJ.(B $A4u(B $AXg(B $ACE(B 
$A=q(B $AX-(B $AE.(B $ARR(B $A`m(B $AP!(B $A3'(B $A3f(B 
$A_.(B $A27(B
 
 \\<quail-translation-docstring>")
 
-    ("chinese-tonepy" "调拼"
+    ("chinese-tonepy" "$A5wF4(B"
      "Pinyin base input method for Chinese charset GB2312 (`chinese-gb2312').
 
 Pinyin is the standard roman transliteration method for Chinese.
@@ -183,18 +183,18 @@ method `chinese-py'.
 
 This input method works almost the same way as `chinese-py'.  The
 difference is that you must type 1..5 after each Pinyin spelling to
-specify a tone (1:阴平, 2:阳平, 3:上声, 4下声, 5:轻声).
+specify a tone (1:$ARuF=(B, 2:$AQtF=(B, 3:$AIOIy(B, 4$AOBIy(B, 
5:$AGaIy(B).
 
 \\<quail-translation-docstring>
 
-For instance, to input 你, you type \"n i 3 3\", the first \"n i\" is
+For instance, to input $ADc(B, you type \"n i 3 3\", the first \"n i\" is
 a Pinyin, the next \"3\" specifies tone, and the last \"3\" selects
 the third character from the candidate list.
 
 For double-width GB2312 characters corresponding to ASCII, use the
 input method `chinese-qj'.")
 
-    ("chinese-zozy" "零注"
+    ("chinese-zozy" "$(0I\0D(B"
 "Zhuyin base input method for Chinese Big5 characters (`chinese-big5-1',
 `chinese-big5-2').
 
@@ -203,8 +203,8 @@ compose a Chinese character.
 
 In this input method, you enter a Chinese character by first typing
 keys corresponding to Zhuyin symbols (see the above table) followed by
-SPC, 6, 3, 4, or 7 specifying a tone (SPC:陰平, 6:陽平, 3:上聲, 4:去聲,
-7:輕聲).
+SPC, 6, 3, 4, or 7 specifying a tone (SPC:$(0?v(N(B, 6:$(0Dm(N(B, 
3:$(0&9Vy(B, 4:$(0(+Vy(B,
+7:$(0M=Vy(B).
 
 \\<quail-translation-docstring>")))
 
@@ -354,7 +354,7 @@ SPC, 6, 3, 4, or 7 specifying a tone (SPC:陰平, 6:陽平, 3:上聲, 
4:去聲,
       (princ (nth 2 (assoc tit-encode tit-encode-list)))
       (princ "\" \"")
       (princ (or title
-                (if (string-match "[:∷:【]+\\([^:∷:】]+\\)" tit-prompt)
+                (if (string-match 
"[:$A!K$(0!(!J(B]+\\([^:$A!K$(0!(!K(B]+\\)" tit-prompt)
                     (substring tit-prompt (match-beginning 1) (match-end 1))
                   tit-prompt)))
       (princ "\"\n"))
@@ -580,7 +580,7 @@ To get complete usage, invoke \"emacs -batch -f 
batch-titdic-convert -h\"."
 ;;    )
 
 (defvar quail-misc-package-ext-info
-  '(("chinese-b5-tsangchi" "倉B"
+  '(("chinese-b5-tsangchi" "$(06A(BB"
      "cangjie-table.b5" big5 "tsang-b5.el"
      tsang-b5-converter
      "\
@@ -590,7 +590,7 @@ To get complete usage, invoke \"emacs -batch -f 
batch-titdic-convert -h\"."
 ;; # unmodified versions is granted without royalty provided
 ;; # this notice is preserved.")
 
-    ("chinese-b5-quick" "簡B"
+    ("chinese-b5-quick" "$(0X|(BB"
      "cangjie-table.b5" big5 "quick-b5.el"
      quick-b5-converter
      "\
@@ -600,7 +600,7 @@ To get complete usage, invoke \"emacs -batch -f 
batch-titdic-convert -h\"."
 ;; # unmodified versions is granted without royalty provided
 ;; # this notice is preserved.")
 
-    ("chinese-cns-tsangchi" "倉C"
+    ("chinese-cns-tsangchi" "$(GT?(BC"
      "cangjie-table.cns" iso-2022-cn-ext "tsang-cns.el"
      tsang-cns-converter
      "\
@@ -610,7 +610,7 @@ To get complete usage, invoke \"emacs -batch -f 
batch-titdic-convert -h\"."
 ;; # unmodified versions is granted without royalty provided
 ;; # this notice is preserved.")
 
-    ("chinese-cns-quick" "簡C"
+    ("chinese-cns-quick" "$(Gv|(BC"
      "cangjie-table.cns" iso-2022-cn-ext "quick-cns.el"
      quick-cns-converter
      "\
@@ -620,7 +620,7 @@ To get complete usage, invoke \"emacs -batch -f 
batch-titdic-convert -h\"."
 ;; # unmodified versions is granted without royalty provided
 ;; # this notice is preserved.")
 
-    ("chinese-py" "拼G"
+    ("chinese-py" "$AF4(BG"
      "pinyin.map" cn-gb-2312 "PY.el"
      py-converter
      "\
@@ -648,7 +648,7 @@ To get complete usage, invoke \"emacs -batch -f 
batch-titdic-convert -h\"."
 ;; You should have received a copy of the GNU General Public License along with
 ;; CCE.  If not, see <https://www.gnu.org/licenses/>.")
 
-    ("chinese-ziranma" "自然"
+    ("chinese-ziranma" "$AWTH;(B"
      "ziranma.cin" cn-gb-2312 "ZIRANMA.el"
      ziranma-converter
      "\
@@ -676,7 +676,7 @@ To get complete usage, invoke \"emacs -batch -f 
batch-titdic-convert -h\"."
 ;; You should have received a copy of the GNU General Public License along with
 ;; CCE.  If not, see <https://www.gnu.org/licenses/>.")
 
-    ("chinese-ctlau" "刘粤"
+    ("chinese-ctlau" "$AAuTA(B"
      "CTLau.html" cn-gb-2312 "CTLau.el"
      ctlau-gb-converter
      "\
@@ -701,7 +701,7 @@ To get complete usage, invoke \"emacs -batch -f 
batch-titdic-convert -h\"."
 ;; # You should have received a copy of the GNU General Public License
 ;; # along with this program.  If not, see <https://www.gnu.org/licenses/>.")
 
-    ("chinese-ctlaub" "劉粵"
+    ("chinese-ctlaub" "$(0N,Gn(B"
      "CTLau-b5.html" big5 "CTLau-b5.el"
      ctlau-b5-converter
      "\
@@ -731,38 +731,38 @@ To get complete usage, invoke \"emacs -batch -f 
batch-titdic-convert -h\"."
 ;; dictionary in the buffer DICBUF.  The input method name of the
 ;; Quail package is NAME, and the title string is TITLE.
 
-;; TSANG-P is non-nil, generate 倉頡 input method.  Otherwise
-;; generate 簡易 (simple version of 倉頡).  If BIG5-P is non-nil, the
+;; TSANG-P is non-nil, generate $(06AQo(B input method.  Otherwise
+;; generate $(0X|/y(B (simple version of $(06AQo(B).  If BIG5-P is 
non-nil, the
 ;; input method is for inputting Big5 characters.  Otherwise the input
 ;; method is for inputting CNS characters.
 
 (defun tsang-quick-converter (dicbuf tsang-p big5-p)
-  (let ((fulltitle (if tsang-p (if big5-p "倉頡" "倉頡")
-                    (if big5-p "簡易" "簡易")))
+  (let ((fulltitle (if tsang-p (if big5-p "$(06AQo(B" "$(GT?on(B")
+                    (if big5-p "$(0X|/y(B" "$(Gv|Mx(B")))
        dic)
     (goto-char (point-max))
     (if big5-p
-       (insert (format "\"中文輸入【%s】BIG5
+       (insert (format "\"$(0&d'GTT&,!J(B%s$(0!K(BBIG5
 
-       漢語%s輸入鍵盤
+       $(0KHM$(B%s$(0TT&,WoOu(B
 
-   [Q 手] [W 田] [E 水] [R 口] [T 廿] [Y 卜] [U 山] [I 戈] [O 人] [P 心]
+   [Q $(0'D(B] [W $(0(q(B] [E $(0'V(B] [R $(0&H(B] [T $(0'>(B] [Y 
$(0&4(B] [U $(0&U(B] [I $(0'B(B] [O $(0&*(B] [P $(0'A(B]
 
-    [A 日] [S 尸] [D 木] [F 火] [G 土] [H 竹] [J 十] [L 中]
+    [A $(0'K(B] [S $(0&T(B] [D $(0'N(B] [F $(0'W(B] [G $(0&I(B] [H 
$(0*M(B] [J $(0&3(B] [L $(0&d(B]
 
-      [Z  ] [X 難] [C 金] [V 女] [B 月] [N 弓] [M 一]
+      [Z  ] [X $(0[E(B] [C $(01[(B] [V $(0&M(B] [B $(0'M(B] [N 
$(0&_(B] [M $(0&"(B]
 
 \\\\<quail-translation-docstring>\"\n"
                        fulltitle fulltitle))
-      (insert (format "\"中文輸入【%s】CNS
+      (insert (format "\"$(GDcEFrSD+!J(B%s$(G!K(BCNS
 
-       漢語%s輸入鍵盤
+       $(GiGk#(B%s$(GrSD+uomu(B
 
-   [Q 手] [W 田] [E 水] [R 口] [T 廿] [Y 卜] [U 山] [I 戈] [O 人] [P 心]
+   [Q $(GEC(B] [W $(GFp(B] [E $(GEU(B] [R $(GDG(B] [T $(GE=(B] [Y 
$(GD3(B] [U $(GDT(B] [I $(GEA(B] [O $(GD)(B] [P $(GE@(B]
 
-    [A 日] [S 尸] [D 木] [F 火] [G 土] [H 竹] [J 十] [L 中]
+    [A $(GEJ(B] [S $(GDS(B] [D $(GEM(B] [F $(GEV(B] [G $(GDH(B] [H 
$(GHL(B] [J $(GD2(B] [L $(GDc(B]
 
-      [Z  ] [X 難] [C 金] [V 女] [B 月] [N 弓] [M 一]
+      [Z  ] [X $(GyE(B] [C $(GOZ(B] [V $(GDL(B] [B $(GEL(B] [N 
$(GD^(B] [M $(GD!(B]
 
 \\\\<quail-translation-docstring>\"\n"
                      fulltitle fulltitle)))
@@ -798,35 +798,35 @@ To get complete usage, invoke \"emacs -batch -f 
batch-titdic-convert -h\"."
     (setq dic (sort dic (function (lambda (x y) (string< (car x ) (car y))))))
     (dolist (elt dic)
       (insert (format "(%S\t%S)\n" (car elt) (cdr elt))))
-    (let ((punctuation '((";" ";﹔,、﹐﹑" ";﹔,、﹐﹑")
-                        (":" ":︰﹕.。‧﹒·" ":︰﹕.。・﹒·")
-                        ("'" "’‘" "’‘")
-                        ("\"" "”“〝〞〃" "”“〝〞〃")
-                        ("\\" "\﹨╲" "\﹨╲")
-                        ("|" "|︱︳∣" "︱︲��|")
-                        ("/" "/∕╱" "/∕╱")
-                        ("?" "?﹖" "?﹖")
-                        ("<" "〈<﹤︿∠" "〈<﹤︿∠")
-                        (">" "〉>﹥﹀" "〉>﹦﹀")
-                        ("[" "〔【﹝︹︻「『﹁﹃" "〔【﹝︹︻「『﹁﹃")
-                        ("]" "〕】﹞︺︼」』﹂﹄" "〕】﹞︺︼」』﹂﹄")
-                        ("{" "{﹛︷ " "{﹛︷ ")
-                        ("}" "}﹜︸" "}﹜︸")
-                        ("`" "‵′" "′‵")
-                        ("~" "~﹋﹌︴﹏" "∼﹋﹌����")
-                        ("!" "!﹗" "!﹗")
-                        ("@" "@﹫" "@﹫")
-                        ("#" "#﹟" "#﹟")
-                        ("$" "$﹩" "$﹩")
-                        ("%" "%﹪" "%﹪")
-                        ("&" "&﹠" "&﹠")
-                        ("*" "*﹡※☆★" "*﹡※☆★")
-                        ("(" "(﹙︵" "(﹙︵")
-                        (")" ")﹚︶" ")﹚︶")
-                        ("-" "–—¯ ̄-﹣" "—–‾��-﹣")
-                        ("_" "_ˍ" "_��")
-                        ("=" "=﹦" "=﹥")
-                        ("+" "+﹢" "+﹢"))))
+    (let ((punctuation '((";" "$(0!'!2!"!#!.!/(B" "$(G!'!2!"!#!.!/(B")
+                        (":" "$(0!(!+!3!%!$!&!0!1(B" 
"$(G!(!+!3!%!$!&!0!1(B")
+                        ("'" "$(0!e!d(B" "$(G!e!d(B")
+                        ("\"" "$(0!g!f!h!i!q(B" "$(G!g!f!h!i!q(B")
+                        ("\\" "$(0"`"b#M(B" "$(G"`"b#M(B")
+                        ("|" "$(0!6!8!:"^(B" "$(G!6!8!:"^(B")
+                        ("/" "$(0"_"a#L(B" "$(G"_"a#L(B")
+                        ("?" "$(0!)!4(B" "$(G!)!4(B")
+                        ("<" "$(0!R"6"A!T"H(B" "$(G!R"6"A!T"H(B")
+                        (">" "$(0!S"7"B!U(B" "$(G!S"7"B!U(B")
+                        ("[" "$(0!F!J!b!H!L!V!Z!X!\(B" 
"$(G!F!J!b!H!L!V!Z!X!\(B")
+                        ("]" "$(0!G!K!c!I!M!W![!Y!](B" 
"$(G!G!K!c!I!M!W![!Y!](B")
+                        ("{" "$(0!B!`!D(B " "$(G!B!`!D(B ")
+                        ("}" "$(0!C!a!E(B" "$(G!C!a!E(B")
+                        ("`" "$(0!j!k(B" "$(G!j!k(B")
+                        ("~" "$(0"D"+",!<!=(B" "$(G"D"+",!<!=(B")
+                        ("!" "$(0!*!5(B" "$(G!*!5(B")
+                        ("@" "$(0"i"n(B" "$(G"i"n(B")
+                        ("#" "$(0!l"-(B" "$(G!l"-(B")
+                        ("$" "$(0"c"l(B" "$(G"c"l(B")
+                        ("%" "$(0"h"m(B" "$(G"h"m(B")
+                        ("&" "$(0!m".(B" "$(G!m".(B")
+                        ("*" "$(0!n"/!o!w!x(B" "$(G!n"/!o!w!x(B")
+                        ("(" "$(0!>!^!@(B" "$(G!>!^!@(B")
+                        (")" "$(0!?!_!A(B" "$(G!?!_!A(B")
+                        ("-" "$(0!7!9"#"$"1"@(B" "$(G!7!9"#"$"1"@(B")
+                        ("_" "$(0"%"&(B" "$(G"%"&(B")
+                        ("=" "$(0"8"C(B" "$(G"8"C(B")
+                        ("+" "$(0"0"?(B" "$(G"0"?(B"))))
     (dolist (elt punctuation)
       (insert (format "(%S %S)\n" (concat "z" (car elt))
                      (if big5-p (nth 1 elt) (nth 2 elt))))))
@@ -850,11 +850,11 @@ To get complete usage, invoke \"emacs -batch -f 
batch-titdic-convert -h\"."
 
 (defun py-converter (dicbuf)
   (goto-char (point-max))
-  (insert (format "%S\n" "汉字输入∷拼音∷
+  (insert (format "%S\n" "$A::WVJdHk!KF4Rt!K(B
 
-       拼音方案
+       $AF4Rt7=08(B
 
- 小写英文字母代表「拼音」符号, \"u(yu) 则用 u: 表示∶
+ $AP!P4S"NDWVD84z1m!8F4Rt!97{:E#,(B \"u(yu) $ATrSC(B u: $A1mJ>!C(B
 
 Pinyin base input method for Chinese charset GB2312 (`chinese-gb2312').
 
@@ -868,14 +868,14 @@ character.  The sequence is made by the combination of 
the initials
           iang ing iong u ua uo uai ui uan un uan ueng yu yue yuan yun
 
   (Note: In the correct Pinyin writing, the sequence \"yu\" in the last
-   four finals should be written by the character u-umlaut `ü'.)
+   four finals should be written by the character u-umlaut `$A(9(B'.)
 
 With this input method, you enter a Chinese character by first
 entering its pinyin spelling.
 
 \\<quail-translation-docstring>
 
-For instance, to input 你, you type \"n i C-n 3\".  The first \"n i\"
+For instance, to input $ADc(B, you type \"n i C-n 3\".  The first \"n i\"
 is a Pinyin, \"C-n\" selects the next group of candidates (each group
 contains at most 10 characters), \"3\" select the third character in
 that group.
@@ -958,22 +958,22 @@ method `chinese-tonepy' with which you must specify tones 
by digits
                 table)))
     (setq dic (sort dic (function (lambda (x y) (string< (car x) (car y))))))
     (goto-char (point-max))
-    (insert (format "%S\n" "汉字输入∷【自然】∷
-
-                            键盘对照表:
- ┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓
- ┃Q  ┃W  ┃E  ┃R  ┃T  ┃Y  ┃Ush┃Ich┃O  ┃P  ┃
- ┃  iu┃  ua┃   e┃ uan┃  ue┃ uai┃   u┃   i┃   o┃  un┃
- ┃    ┃  ia┃    ┃ van┃  ve┃ ing┃    ┃    ┃  uo┃  vn┃
- ┗┳━┻┳━┻┳━┻┳━┻┳━┻┳━┻┳━┻┳━┻┳━┻┳━┛
-   ┃A  ┃S  ┃D  ┃F  ┃G  ┃H  ┃J  ┃K  ┃L  ┃
-   ┃   a┃iong┃uang┃  en┃ eng┃ ang┃  an┃  ao┃  ai┃
-   ┃    ┃ ong┃iang┃    ┃  ng┃    ┃    ┃    ┃    ┃
-   ┗┳━┻┳━┻┳━┻┳━┻┳━┻┳━┻┳━┻┳━┻┳━┻┳━━┓
-     ┃Z  ┃X  ┃C  ┃Vzh┃B  ┃N  ┃M  ┃,  ┃.  ┃ / ┃
-     ┃  ei┃  ie┃ iao┃  ui┃  ou┃  in┃ ian┃前页┃后页┃符号┃
-     ┃    ┃    ┃    ┃   v┃    ┃    ┃    ┃    ┃    ┃    ┃
-     ┗━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┛
+    (insert (format "%S\n" "$A::WVJdHk!K!>WTH;!?!K(B
+
+                            $A<|EL6TUU1m(B:
+ $A)3)%)%)W)%)%)W)%)%)W)%)%)W)%)%)W)%)%)W)%)%)W)%)%)W)%)%)W)%)%)7(B
+ $A)'#Q(B  $A)'#W(B  $A)'#E(B  $A)'#R(B  $A)'#T(B  $A)'#Y(B  
$A)'#U(Bsh$A)'#I(Bch$A)'#O(B  $A)'#P(B  $A)'(B
+ $A)'(B  iu$A)'(B  ua$A)'(B   e$A)'(B uan$A)'(B  ue$A)'(B 
uai$A)'(B   u$A)'(B   i$A)'(B   o$A)'(B  un$A)'(B
+ $A)'(B    $A)'(B  ia$A)'(B    $A)'(B van$A)'(B  ve$A)'(B 
ing$A)'(B    $A)'(B    $A)'(B  uo$A)'(B  vn$A)'(B
+ $A);)W)%)_)W)%)_)W)%)_)W)%)_)W)%)_)W)%)_)W)%)_)W)%)_)W)%)_)W)%)?(B
+   $A)'#A(B  $A)'#S(B  $A)'#D(B  $A)'#F(B  $A)'#G(B  $A)'#H(B  
$A)'#J(B  $A)'#K(B  $A)'#L(B  $A)'(B
+   $A)'(B   a$A)'(Biong$A)'(Buang$A)'(B  en$A)'(B eng$A)'(B 
ang$A)'(B  an$A)'(B  ao$A)'(B  ai$A)'(B
+   $A)'(B    $A)'(B ong$A)'(Biang$A)'(B    $A)'(B  ng$A)'(B    
$A)'(B    $A)'(B    $A)'(B    $A)'(B
+   $A);)W)%)_)W)%)_)W)%)_)W)%)_)W)%)_)W)%)_)W)%)_)W)%)_)W)%)_)W)%)%)7(B
+     $A)'#Z(B  $A)'#X(B  $A)'#C(B  $A)'#V(Bzh$A)'#B(B  $A)'#N(B  
$A)'#M(B  $A)'#,(B  $A)'#.(B  $A)'(B $A#/(B $A)'(B
+     $A)'(B  ei$A)'(B  ie$A)'(B iao$A)'(B  ui$A)'(B  ou$A)'(B  
in$A)'(B ian$A)'G0R3)':sR3)'7{:E)'(B
+     $A)'(B    $A)'(B    $A)'(B    $A)'(B   v$A)'(B    $A)'(B    
$A)'(B    $A)'(B    $A)'(B    $A)'(B    $A)'(B
+     $A);)%)%)_)%)%)_)%)%)_)%)%)_)%)%)_)%)%)_)%)%)_)%)%)_)%)%)_)%)%)?(B
 
 
 Pinyin base input method for Chinese GB2312 characters (`chinese-gb2312').
@@ -985,34 +985,34 @@ method `chinese-py'.
 Unlike the standard spelling of Pinyin, in this input method all
 initials and finals are assigned to single keys (see the above table).
 For instance, the initial \"ch\" is assigned to the key `i', the final
-\"iu\" is assigned to the key `q', and tones 1, 2, 3, 4, and 轻声 are
+\"iu\" is assigned to the key `q', and tones 1, 2, 3, 4, and $AGaIy(B are
 assigned to the keys `q', `w', `e', `r', `t' respectively.
 
 \\<quail-translation-docstring>
 
 To input one-letter words, you type 4 keys, the first two for the
 Pinyin of the letter, next one for tone, and the last one is always a
-quote (').  For instance, \"vsq'\" input 中.  Exceptions are these
+quote (').  For instance, \"vsq'\" input $AVP(B.  Exceptions are these
 letters.  You can input them just by typing a single key.
 
-       Character: 按 不 次 的 二 发 个 和 出 及 可 了 没
+       Character: $A04(B $A2;(B $A4N(B $A5D(B $A6~(B $A7"(B 
$A8v(B $A:M(B $A3v(B $A<0(B $A?I(B $AAK(B $AC;(B
        Key:       a  b  c  d  e  f  g  h  i  j  k  l  m
-       Character: 你 欧 片 七 人 三 他 是 着 我 小 一 在
+       Character: $ADc(B $AE7(B $AF,(B $AF_(B $AHK(B $AH}(B 
$AK{(B $AJG(B $AWE(B $ANR(B $AP!(B $AR;(B $ATZ(B
        Key:       n  o  p  q  r  s  t  u  v  w  x  y  z
 
 To input two-letter words, you have two ways.  One way is to type 4
 keys, two for the first Pinyin, two for the second Pinyin.  For
-instance, \"vsgo\" inputs 中国.  Another way is to type 3 keys: 2
+instance, \"vsgo\" inputs $AVP9z(B.  Another way is to type 3 keys: 2
 initials of two letters, and quote (').  For instance, \"vg'\" also
-inputs 中国.
+inputs $AVP9z(B.
 
 To input three-letter words, you type 4 keys: initials of three
-letters, and the last is quote (').  For instance, \"bjy'2\" inputs 北
-京鸭 (the last `2' is to select one of the candidates).
+letters, and the last is quote (').  For instance, \"bjy'2\" inputs $A11(B
+$A>)Q<(B (the last `2' is to select one of the candidates).
 
 To input words of more than three letters, you type 4 keys, initials
 of the first three letters and the last letter.  For instance,
-\"bjdt\" inputs 北京电视台.
+\"bjdt\" inputs $A11>)5gJSL((B.
 
 To input symbols and punctuation, type `/' followed by one of `a' to
 `z', then select one of the candidates."))
@@ -1059,7 +1059,7 @@ To input symbols and punctuation, type `/' followed by 
one of `a' to
     ;; which the file is converted have no Big5 equivalent.  Go
     ;; through and delete them.
     (goto-char pos)
-    (while (search-forward "□" nil t)
+    (while (search-forward "$(0!{(B" nil t)
       (delete-char -1))
     ;; Uppercase keys in dictionary need to be downcased.  Backslashes
     ;; at the beginning of keys need to be turned into double
@@ -1083,31 +1083,31 @@ To input symbols and punctuation, type `/' followed by 
one of `a' to
 
 (defun ctlau-gb-converter (dicbuf)
   (ctlau-converter dicbuf
-"汉字输入∷刘锡祥式粤音∷
+"$A::WVJdHk!KAuN}OiJ=TARt!K(B
 
- 刘锡祥式粤语注音方案
+ $AAuN}OiJ=TASoW"Rt7=08(B
  Sidney Lau's Cantonese transcription scheme as described in his book
  \"Elementary Cantonese\", The Government Printer, Hong Kong, 1972.
- This file was prepared by Fung Fung Lee (李枫峰).
+ This file was prepared by Fung Fung Lee ($A@n7c7e(B).
  Originally converted from CTCPS3.tit
  Last modified: June 2, 1993.
 
  Some infrequent GB characters are accessed by typing \\, followed by
- the Cantonese romanization of the respective radical (部首)."))
+ the Cantonese romanization of the respective radical ($A2?JW(B)."))
 
 (defun ctlau-b5-converter (dicbuf)
   (ctlau-converter dicbuf
-"漢字輸入:劉錫祥式粵音:
+"$(0KH)tTT&,!(N,Tg>A*#Gn5x!((B
 
- 劉錫祥式粵語注音方案
+ $(0N,Tg>A*#GnM$0D5x'J7{(B
  Sidney Lau's Cantonese transcription scheme as described in his book
  \"Elementary Cantonese\", The Government Printer, Hong Kong, 1972.
- This file was prepared by Fung Fung Lee (李楓峰).
+ This file was prepared by Fung Fung Lee ($(0,XFS76(B).
  Originally converted from CTCPS3.tit
  Last modified: June 2, 1993.
 
  Some infrequent characters are accessed by typing \\, followed by
- the Cantonese romanization of the respective radical (部首)."))
+ the Cantonese romanization of the respective radical ($(0?f5}(B)."))
 
 (declare-function dos-8+3-filename "dos-fns.el" (filename))
 
diff --git a/lisp/isearch.el b/lisp/isearch.el
index c987393..ddf9190 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -1225,6 +1225,9 @@ used to set the value of `isearch-regexp-function'."
        isearch-pre-scroll-point nil
        isearch-pre-move-point nil
 
+       isearch-lazy-count-current nil
+       isearch-lazy-count-total nil
+
        ;; Save the original value of `minibuffer-message-timeout', and
        ;; set it to nil so that isearch's messages don't get timed out.
        isearch-original-minibuffer-message-timeout minibuffer-message-timeout
@@ -3776,7 +3779,7 @@ by other Emacs features."
                                 isearch-lazy-highlight-window-end))))))
     ;; something important did indeed change
     (lazy-highlight-cleanup t (not (equal isearch-string ""))) ;stop old timer
-    (when isearch-lazy-count
+    (when (and isearch-lazy-count isearch-mode (null isearch-message-function))
       (when (or (equal isearch-string "")
                 ;; Check if this place was reached by a condition above
                 ;; other than changed window boundaries (that shouldn't
@@ -3794,7 +3797,7 @@ by other Emacs features."
         (clrhash isearch-lazy-count-hash)
         (setq isearch-lazy-count-current nil
               isearch-lazy-count-total nil)
-        (funcall (or isearch-message-function #'isearch-message))))
+        (isearch-message)))
     (setq isearch-lazy-highlight-window-start-changed nil)
     (setq isearch-lazy-highlight-window-end-changed nil)
     (setq isearch-lazy-highlight-error isearch-error)
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index 67475eb..2246e5f 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -4751,6 +4751,75 @@ and runs the normal hook `command-history-hook'." t nil)
 ;;; Generated autoloads from emacs-lisp/cl-generic.el
 (push (purecopy '(cl-generic 1 0)) package--builtin-versions)
 
+(autoload 'cl-defgeneric "cl-generic" "\
+Create a generic function NAME.
+DOC-STRING is the base documentation for this class.  A generic
+function has no body, as its purpose is to decide which method body
+is appropriate to use.  Specific methods are defined with `cl-defmethod'.
+With this implementation the ARGS are currently ignored.
+OPTIONS-AND-METHODS currently understands:
+- (:documentation DOCSTRING)
+- (declare DECLARATIONS)
+- (:argument-precedence-order &rest ARGS)
+- (:method [QUALIFIERS...] ARGS &rest BODY)
+DEFAULT-BODY, if present, is used as the body of a default method.
+
+\(fn NAME ARGS [DOC-STRING] [OPTIONS-AND-METHODS...] &rest DEFAULT-BODY)" nil 
t)
+
+(function-put 'cl-defgeneric 'lisp-indent-function '2)
+
+(function-put 'cl-defgeneric 'doc-string-elt '3)
+
+(autoload 'cl-generic-define "cl-generic" "\
+
+
+\(fn NAME ARGS OPTIONS)" nil nil)
+
+(autoload 'cl-defmethod "cl-generic" "\
+Define a new method for generic function NAME.
+I.e. it defines the implementation of NAME to use for invocations where the
+values of the dispatch arguments match the specified TYPEs.
+The dispatch arguments have to be among the mandatory arguments, and
+all methods of NAME have to use the same set of arguments for dispatch.
+Each dispatch argument and TYPE are specified in ARGS where the corresponding
+formal argument appears as (VAR TYPE) rather than just VAR.
+
+The optional second argument QUALIFIER is a specifier that
+modifies how the method is combined with other methods, including:
+   :before  - Method will be called before the primary
+   :after   - Method will be called after the primary
+   :around  - Method will be called around everything else
+The absence of QUALIFIER means this is a \"primary\" method.
+The set of acceptable qualifiers and their meaning is defined
+\(and can be extended) by the methods of `cl-generic-combine-methods'.
+
+ARGS can also include so-called context specializers, introduced by
+`&context' (which should appear right after the mandatory arguments,
+before any &optional or &rest).  They have the form (EXPR TYPE) where
+EXPR is an Elisp expression whose value should match TYPE for the
+method to be applicable.
+
+The set of acceptable TYPEs (also called \"specializers\") is defined
+\(and can be extended) by the various methods of `cl-generic-generalizers'.
+
+\(fn NAME [QUALIFIER] ARGS &rest [DOCSTRING] BODY)" nil t)
+
+(function-put 'cl-defmethod 'doc-string-elt '3)
+
+(function-put 'cl-defmethod 'lisp-indent-function 'defun)
+
+(autoload 'cl-generic-define-method "cl-generic" "\
+
+
+\(fn NAME QUALIFIERS ARGS USES-CNM FUNCTION)" nil nil)
+
+(autoload 'cl-find-method "cl-generic" "\
+
+
+\(fn GENERIC QUALIFIERS SPECIALIZERS)" nil nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"cl-generic" '("cl-")))
+
 ;;;***
 
 ;;;### (autoloads nil "cl-indent" "emacs-lisp/cl-indent.el" (0 0
@@ -7334,7 +7403,10 @@ exists.  If NO-ASYNC is non-nil, call diff synchronously.
 
 When called interactively with a prefix argument, prompt
 interactively for diff switches.  Otherwise, the switches
-specified in the variable `diff-switches' are passed to the diff command.
+specified in the variable `diff-switches' are passed to the
+diff command.
+
+Non-interactively, OLD and NEW may each be a file or a buffer.
 
 \(fn OLD NEW &optional SWITCHES NO-ASYNC)" t nil)
 
@@ -7358,6 +7430,23 @@ This requires the external program `diff' to be in your 
`exec-path'.
 
 \(fn &optional BUFFER)" t nil)
 
+(autoload 'diff-buffers "diff" "\
+Find and display the differences between OLD and NEW buffers.
+
+When called interactively, read NEW, then OLD, using the
+minibuffer.  The default for NEW is the current buffer, and the
+default for OLD is the most recently selected other buffer.
+If NO-ASYNC is non-nil, call diff synchronously.
+
+When called interactively with a prefix argument, prompt
+interactively for diff switches.  Otherwise, the switches
+specified in the variable `diff-switches' are passed to the
+diff command.
+
+OLD and NEW may each be a buffer or a buffer name.
+
+\(fn OLD NEW &optional SWITCHES NO-ASYNC)" t nil)
+
 (if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"diff" '("diff-")))
 
 ;;;***
@@ -7537,7 +7626,6 @@ Hooks (use \\[describe-variable] to see their 
documentation):
   `dired-before-readin-hook'
   `dired-after-readin-hook'
   `dired-mode-hook'
-  `dired-load-hook'
 
 Keybindings:
 \\{dired-mode-map}
@@ -8876,7 +8964,7 @@ an EDE controlled project.
 ;;;;;;  "cedet/ede/cpp-root.el" (0 0 0 0))
 ;;; Generated autoloads from cedet/ede/cpp-root.el
 
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ede/cpp-root" '("ede-c")))
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ede/cpp-root" '("ede-cpp-root-")))
 
 ;;;***
 
@@ -11576,6 +11664,17 @@ see `eudc-inline-expansion-servers'.
 
 \(fn &optional REPLACE)" t nil)
 
+(autoload 'eudc-query-with-words "eudc" "\
+Query the directory server, and return the matching responses.
+The variable `eudc-inline-query-format' controls how to associate the
+individual QUERY-WORDS with directory attribute names.
+After querying the server for the given string, the expansion specified by
+`eudc-inline-expansion-format' is applied to the matches before returning 
them.inserted in the buffer at point.
+Multiple servers can be tried with the same query until one finds a match,
+see `eudc-inline-expansion-servers'.
+
+\(fn QUERY-WORDS)" nil nil)
+
 (autoload 'eudc-query-form "eudc" "\
 Display a form to query the directory server.
 If given a non-nil argument GET-FIELDS-FROM-SERVER, the function first
@@ -13442,7 +13541,7 @@ and choose the directory as the fortune-file.
 Minimum set of parameters to filter for live (on-session) framesets.
 DO NOT MODIFY.  See `frameset-filter-alist' for a full description.")
 
-(defvar frameset-persistent-filter-alist (nconc '((background-color . 
frameset-filter-sanitize-color) (buffer-list . :never) (buffer-predicate . 
:never) (buried-buffer-list . :never) (client . :never) (delete-before . 
:never) (font . frameset-filter-font-param) (foreground-color . 
frameset-filter-sanitize-color) (frameset--text-pixel-height . :save) 
(frameset--text-pixel-width . :save) (fullscreen . 
frameset-filter-shelve-param) (GUI:font . frameset-filter-unshelve-param) 
(GUI:fullscreen [...]
+(defvar frameset-persistent-filter-alist (nconc '((background-color . 
frameset-filter-sanitize-color) (buffer-list . :never) (buffer-predicate . 
:never) (buried-buffer-list . :never) (client . :never) (delete-before . 
:never) (font . frameset-filter-font-param) (font-backend . :never) 
(foreground-color . frameset-filter-sanitize-color) 
(frameset--text-pixel-height . :save) (frameset--text-pixel-width . :save) 
(fullscreen . frameset-filter-shelve-param) (GUI:font . frameset-filter-unshelv 
[...]
 Parameters to filter for persistent framesets.
 DO NOT MODIFY.  See `frameset-filter-alist' for a full description.")
 
@@ -14663,9 +14762,6 @@ Add NUM into sorted LIST by side effect.
 (autoload 'gnus-registry-initialize "gnus-registry" "\
 Initialize the Gnus registry." t nil)
 
-(autoload 'gnus-registry-install-hooks "gnus-registry" "\
-Install the registry hooks." t nil)
-
 (if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"gnus-registry" '("gnus-")))
 
 ;;;***
@@ -17041,7 +17137,6 @@ The main features of this mode are
 
 8. Hooks
    -----
-   Loading idlwave.el runs `idlwave-load-hook'.
    Turning on `idlwave-mode' runs `idlwave-mode-hook'.
 
 9. Documentation and Customization
@@ -18934,7 +19029,7 @@ one of the aforementioned options instead of using this 
mode.
 
 ;;;### (autoloads nil "jsonrpc" "jsonrpc.el" (0 0 0 0))
 ;;; Generated autoloads from jsonrpc.el
-(push (purecopy '(jsonrpc 1 0 8)) package--builtin-versions)
+(push (purecopy '(jsonrpc 1 0 9)) package--builtin-versions)
 
 (if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"jsonrpc" '("jrpc-default-request-timeout" "jsonrpc-")))
 
@@ -19714,7 +19809,7 @@ This function is suitable for execution in an init file.
 
 \(fn &optional ARG)" t nil)
 
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"lunar" '("calendar-lunar-phases" "diary-lunar-phases" "lunar-")))
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"lunar" '("calendar-lunar-phases" "diary-lunar-phases" "eclipse-check" 
"lunar-")))
 
 ;;;***
 
@@ -22700,6 +22795,13 @@ Many aspects this mode can be customized using
 
 ;;;***
 
+;;;### (autoloads nil "ob-eshell" "org/ob-eshell.el" (0 0 0 0))
+;;; Generated autoloads from org/ob-eshell.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ob-eshell" '("ob-eshell-session-live-p" "org-babel-")))
+
+;;;***
+
 ;;;### (autoloads nil "ob-eval" "org/ob-eval.el" (0 0 0 0))
 ;;; Generated autoloads from org/ob-eval.el
 
@@ -22777,14 +22879,6 @@ Many aspects this mode can be customized using
 
 ;;;***
 
-;;;### (autoloads "actual autoloads are elsewhere" "ob-keys" "org/ob-keys.el"
-;;;;;;  (0 0 0 0))
-;;; Generated autoloads from org/ob-keys.el
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ob-keys" '("org-babel-")))
-
-;;;***
-
 ;;;### (autoloads nil "ob-latex" "org/ob-latex.el" (0 0 0 0))
 ;;; Generated autoloads from org/ob-latex.el
 
@@ -22943,7 +23037,7 @@ Many aspects this mode can be customized using
 
 ;;;### (autoloads nil "ob-sed" "org/ob-sed.el" (0 0 0 0))
 ;;; Generated autoloads from org/ob-sed.el
-(push (purecopy '(ob-sed 0 1 0)) package--builtin-versions)
+(push (purecopy '(ob-sed 0 1 1)) package--builtin-versions)
 
 (if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ob-sed" '("org-babel-")))
 
@@ -23056,6 +23150,189 @@ startup file, `~/.emacs-octave'.
 
 ;;;***
 
+;;;### (autoloads nil "ol" "org/ol.el" (0 0 0 0))
+;;; Generated autoloads from org/ol.el
+
+(autoload 'org-next-link "ol" "\
+Move forward to the next link.
+If the link is in hidden text, expose it.  When SEARCH-BACKWARD
+is non-nil, move backward.
+
+\(fn &optional SEARCH-BACKWARD)" t nil)
+
+(autoload 'org-previous-link "ol" "\
+Move backward to the previous link.
+If the link is in hidden text, expose it." t nil)
+
+(autoload 'org-toggle-link-display "ol" "\
+Toggle the literal or descriptive display of links." t nil)
+
+(autoload 'org-store-link "ol" "\
+Store a link to the current location.
+\\<org-mode-map>
+This link is added to `org-stored-links' and can later be inserted
+into an Org buffer with `org-insert-link' (`\\[org-insert-link]').
+
+For some link types, a `\\[universal-argument]' prefix ARG is interpreted.  A 
single
+`\\[universal-argument]' negates `org-context-in-file-links' for file links or
+`org-gnus-prefer-web-links' for links to Usenet articles.
+
+A `\\[universal-argument] \\[universal-argument]' prefix ARG forces skipping 
storing functions that are not
+part of Org core.
+
+A `\\[universal-argument] \\[universal-argument] \\[universal-argument]' 
prefix ARG forces storing a link for each line in the
+active region.
+
+Assume the function is called interactively if INTERACTIVE? is
+non-nil.
+
+\(fn ARG &optional INTERACTIVE\\=\\?)" t nil)
+
+(autoload 'org-insert-link "ol" "\
+Insert a link.  At the prompt, enter the link.
+
+Completion can be used to insert any of the link protocol prefixes in use.
+
+The history can be used to select a link previously stored with
+`org-store-link'.  When the empty string is entered (i.e. if you just
+press `RET' at the prompt), the link defaults to the most recently
+stored link.  As `SPC' triggers completion in the minibuffer, you need to
+use `M-SPC' or `C-q SPC' to force the insertion of a space character.
+
+You will also be prompted for a description, and if one is given, it will
+be displayed in the buffer instead of the link.
+
+If there is already a link at point, this command will allow you to edit
+link and description parts.
+
+With a `\\[universal-argument]' prefix, prompts for a file to link to.  The 
file name can be
+selected using completion.  The path to the file will be relative to the
+current directory if the file is in the current directory or a subdirectory.
+Otherwise, the link will be the absolute path as completed in the minibuffer
+\(i.e. normally ~/path/to/file).  You can configure this behavior using the
+option `org-link-file-path-type'.
+
+With a `\\[universal-argument] \\[universal-argument]' prefix, enforce an 
absolute path even if the file is in
+the current directory or below.
+
+A `\\[universal-argument] \\[universal-argument] \\[universal-argument]' 
prefix negates `org-link-keep-stored-after-insertion'.
+
+If the LINK-LOCATION parameter is non-nil, this value will be used as
+the link location instead of reading one interactively.
+
+If the DESCRIPTION parameter is non-nil, this value will be used as the
+default description.  Otherwise, if `org-link-make-description-function'
+is non-nil, this function will be called with the link target, and the
+result will be the default link description.  When called non-interactively,
+don't allow to edit the default description.
+
+\(fn &optional COMPLETE-FILE LINK-LOCATION DESCRIPTION)" t nil)
+
+(autoload 'org-insert-all-links "ol" "\
+Insert all links in `org-stored-links'.
+When a universal prefix, do not delete the links from `org-stored-links'.
+When `ARG' is a number, insert the last N link(s).
+`PRE' and `POST' are optional arguments to define a string to
+prepend or to append.
+
+\(fn ARG &optional PRE POST)" t nil)
+
+(autoload 'org-insert-last-stored-link "ol" "\
+Insert the last link stored in `org-stored-links'.
+
+\(fn ARG)" t nil)
+
+(autoload 'org-insert-link-global "ol" "\
+Insert a link like Org mode does.
+This command can be called in any mode to insert a link in Org syntax." t nil)
+
+(autoload 'org-update-radio-target-regexp "ol" "\
+Find all radio targets in this file and update the regular expression.
+Also refresh fontification if needed." t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ol" 
'("org-")))
+
+;;;***
+
+;;;### (autoloads "actual autoloads are elsewhere" "ol-bbdb" "org/ol-bbdb.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from org/ol-bbdb.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ol-bbdb" '("org-bbdb-")))
+
+;;;***
+
+;;;### (autoloads nil "ol-bibtex" "org/ol-bibtex.el" (0 0 0 0))
+;;; Generated autoloads from org/ol-bibtex.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ol-bibtex" '("org-")))
+
+;;;***
+
+;;;### (autoloads nil "ol-docview" "org/ol-docview.el" (0 0 0 0))
+;;; Generated autoloads from org/ol-docview.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ol-docview" '("org-docview-")))
+
+;;;***
+
+;;;### (autoloads nil "ol-eshell" "org/ol-eshell.el" (0 0 0 0))
+;;; Generated autoloads from org/ol-eshell.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ol-eshell" '("org-eshell-")))
+
+;;;***
+
+;;;### (autoloads nil "ol-eww" "org/ol-eww.el" (0 0 0 0))
+;;; Generated autoloads from org/ol-eww.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ol-eww" '("org-eww-")))
+
+;;;***
+
+;;;### (autoloads nil "ol-gnus" "org/ol-gnus.el" (0 0 0 0))
+;;; Generated autoloads from org/ol-gnus.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ol-gnus" '("org-gnus-")))
+
+;;;***
+
+;;;### (autoloads nil "ol-info" "org/ol-info.el" (0 0 0 0))
+;;; Generated autoloads from org/ol-info.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ol-info" '("org-info-")))
+
+;;;***
+
+;;;### (autoloads "actual autoloads are elsewhere" "ol-irc" "org/ol-irc.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from org/ol-irc.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ol-irc" '("org-irc-")))
+
+;;;***
+
+;;;### (autoloads nil "ol-mhe" "org/ol-mhe.el" (0 0 0 0))
+;;; Generated autoloads from org/ol-mhe.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ol-mhe" '("org-mhe-")))
+
+;;;***
+
+;;;### (autoloads nil "ol-rmail" "org/ol-rmail.el" (0 0 0 0))
+;;; Generated autoloads from org/ol-rmail.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ol-rmail" '("org-rmail-")))
+
+;;;***
+
+;;;### (autoloads nil "ol-w3m" "org/ol-w3m.el" (0 0 0 0))
+;;; Generated autoloads from org/ol-w3m.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ol-w3m" '("org-w3m-")))
+
+;;;***
+
 ;;;### (autoloads nil "opascal" "progmodes/opascal.el" (0 0 0 0))
 ;;; Generated autoloads from progmodes/opascal.el
 
@@ -23095,7 +23372,7 @@ Coloring:
 
 ;;;### (autoloads nil "org" "org/org.el" (0 0 0 0))
 ;;; Generated autoloads from org/org.el
-(push (purecopy '(org 9 1 9)) package--builtin-versions)
+(push (purecopy '(org 9 3)) package--builtin-versions)
 
 (autoload 'org-babel-do-load-languages "org" "\
 Load the languages defined in `org-babel-load-languages'.
@@ -23105,9 +23382,9 @@ Load the languages defined in 
`org-babel-load-languages'.
 (autoload 'org-babel-load-file "org" "\
 Load Emacs Lisp source code blocks in the Org FILE.
 This function exports the source code using `org-babel-tangle'
-and then loads the resulting file using `load-file'.  With prefix
-arg (noninteractively: 2nd arg) COMPILE the tangled Emacs Lisp
-file to byte-code before it is loaded.
+and then loads the resulting file using `load-file'.  With
+optional prefix argument COMPILE, the tangled Emacs Lisp file is
+byte-compiled before it is loaded.
 
 \(fn FILE &optional COMPILE)" t nil)
 
@@ -23120,9 +23397,6 @@ FULL is given.
 
 \(fn &optional HERE FULL MESSAGE)" t nil)
 
-(autoload 'turn-on-orgtbl "org" "\
-Unconditionally turn on `orgtbl-mode'." nil nil)
-
 (autoload 'org-clock-persistence-insinuate "org" "\
 Set up hooks for clock persistence." nil nil)
 
@@ -23205,27 +23479,6 @@ With `\\[universal-argument]' prefix ARG, switch to 
startup visibility.
 With a numeric prefix, show all headlines up to that level.
 
 \(fn &optional ARG)" t nil)
-(put 'orgstruct-heading-prefix-regexp 'safe-local-variable 'stringp)
-
-(autoload 'orgstruct-mode "org" "\
-Toggle the minor mode `orgstruct-mode'.
-This mode is for using Org mode structure commands in other
-modes.  The following keys behave as if Org mode were active, if
-the cursor is on a headline, or on a plain list item (both as
-defined by Org mode).
-
-If called interactively, enable OrgStruct mode if ARG is positive, and
-disable it if ARG is zero or negative.  If called from Lisp, also
-enable the mode if ARG is omitted or nil, and toggle it if ARG is
-`toggle'; disable the mode otherwise.
-
-\(fn &optional ARG)" t nil)
-
-(autoload 'turn-on-orgstruct "org" "\
-Unconditionally turn on `orgstruct-mode'." nil nil)
-
-(autoload 'turn-on-orgstruct++ "org" "\
-Unconditionally turn on `orgstruct++-mode'." nil nil)
 
 (autoload 'org-run-like-in-org-mode "org" "\
 Run a command, pretending that the current buffer is in Org mode.
@@ -23235,39 +23488,46 @@ call CMD.
 
 \(fn CMD)" nil nil)
 
-(autoload 'org-store-link "org" "\
-Store an org-link to the current location.
-\\<org-mode-map>
-This link is added to `org-stored-links' and can later be inserted
-into an Org buffer with `org-insert-link' (`\\[org-insert-link]').
-
-For some link types, a `\\[universal-argument]' prefix ARG is interpreted.  A 
single
-`\\[universal-argument]' negates `org-context-in-file-links' for file links or
-`org-gnus-prefer-web-links' for links to Usenet articles.
+(autoload 'org-open-file "org" "\
+Open the file at PATH.
+First, this expands any special file name abbreviations.  Then the
+configuration variable `org-file-apps' is checked if it contains an
+entry for this file type, and if yes, the corresponding command is launched.
 
-A `\\[universal-argument] \\[universal-argument]' prefix ARG forces skipping 
storing functions that are not
-part of Org core.
+If no application is found, Emacs simply visits the file.
 
-A `\\[universal-argument] \\[universal-argument] \\[universal-argument]' 
prefix ARG forces storing a link for each line in the
-active region.
+With optional prefix argument IN-EMACS, Emacs will visit the file.
+With a double \\[universal-argument] \\[universal-argument] prefix arg, Org 
tries to avoid opening in Emacs
+and to use an external application to visit the file.
 
-\(fn ARG)" t nil)
+Optional LINE specifies a line to go to, optional SEARCH a string
+to search for.  If LINE or SEARCH is given, the file will be
+opened in Emacs, unless an entry from `org-file-apps' that makes
+use of groups in a regexp matches.
 
-(autoload 'org-insert-link-global "org" "\
-Insert a link like Org mode does.
-This command can be called in any mode to insert a link in Org syntax." t nil)
+If you want to change the way frames are used when following a
+link, please customize `org-link-frame-setup'.
 
-(autoload 'org-open-at-point-global "org" "\
-Follow a link or time-stamp like Org mode does.
-This command can be called in any mode to follow an external link
-or a time-stamp that has Org mode syntax.  Its behavior is
-undefined when called on internal links (e.g., fuzzy links).
-Raise an error when there is nothing to follow." t nil)
+If the file does not exist, throw an error.
 
-(autoload 'org-open-link-from-string "org" "\
-Open a link in the string S, as if it was in Org mode.
+\(fn PATH &optional IN-EMACS LINE SEARCH)" nil nil)
 
-\(fn S &optional ARG REFERENCE-BUFFER)" t nil)
+(autoload 'org-open-at-point-global "org" "\
+Follow a link or a time-stamp like Org mode does.
+Also follow links and emails as seen by `thing-at-point'.
+This command can be called in any mode to follow an external
+link or a time-stamp that has Org mode syntax.  Its behavior
+is undefined when called on internal links like fuzzy links.
+Raise a user error when there is nothing to follow." t nil)
+
+(autoload 'org-offer-links-in-entry "org" "\
+Offer links in the current entry and return the selected link.
+If there is only one link, return it.
+If NTH is an integer, return the NTH link found.
+If ZERO is a string, check also this string for a link, and if
+there is one, return it.
+
+\(fn BUFFER MARKER &optional NTH ZERO)" nil nil)
 
 (autoload 'org-switchb "org" "\
 Switch between Org buffers.
@@ -23301,7 +23561,7 @@ With prefix arg UNCOMPILED, load the uncompiled 
versions.
 (autoload 'org-customize "org" "\
 Call the customize function with org as argument." t nil)
 
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org" '("org" "turn-on-org-cdlatex")))
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org" '("org-" "turn-on-org-cdlatex")))
 
 ;;;***
 
@@ -23389,7 +23649,7 @@ todo         The todo keyword, if any
 tags         All tags including inherited ones, separated by colons
 date         The relevant date, like 2007-2-14
 time         The time, like 15:00-16:50
-extra        Sting with extra planning info
+extra        String with extra planning info
 priority-l   The priority letter if any was given
 priority-n   The computed numerical priority
 agenda-day   The day in the agenda where this is listed
@@ -23528,10 +23788,13 @@ Do we have a reason to ignore this TODO entry because 
it has a time stamp?
 \(fn &optional END)" nil nil)
 
 (autoload 'org-agenda-set-restriction-lock "org-agenda" "\
-Set restriction lock for agenda, to current subtree or file.
-Restriction will be the file if TYPE is `file', or if type is the
-universal prefix \\='(4), or if the cursor is before the first headline
-in the file.  Otherwise, restriction will be to the current subtree.
+Set restriction lock for agenda to current subtree or file.
+When in a restricted subtree, remove it.
+
+The restriction will span over the entire file if TYPE is `file',
+or if type is '(4), or if the cursor is before the first headline
+in the file. Otherwise, only apply the restriction to the current
+subtree.
 
 \(fn &optional TYPE)" t nil)
 
@@ -23582,7 +23845,7 @@ to override `appt-message-warning-time'.
 ;;;;;;  "org/org-archive.el" (0 0 0 0))
 ;;; Generated autoloads from org/org-archive.el
 
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-archive" '("org-")))
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-archive" '("org-a")))
 
 ;;;***
 
@@ -23594,18 +23857,11 @@ to override `appt-message-warning-time'.
 
 ;;;***
 
-;;;### (autoloads "actual autoloads are elsewhere" "org-bbdb" "org/org-bbdb.el"
-;;;;;;  (0 0 0 0))
-;;; Generated autoloads from org/org-bbdb.el
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-bbdb" '("org-bbdb-")))
-
-;;;***
-
-;;;### (autoloads nil "org-bibtex" "org/org-bibtex.el" (0 0 0 0))
-;;; Generated autoloads from org/org-bibtex.el
+;;;### (autoloads nil "org-attach-git" "org/org-attach-git.el" (0
+;;;;;;  0 0 0))
+;;; Generated autoloads from org/org-attach-git.el
 
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-bibtex" '("org-")))
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-attach-git" '("org-attach-git-")))
 
 ;;;***
 
@@ -23651,7 +23907,7 @@ of the day at point (if any) or the current HH:MM time.
 (autoload 'org-capture-import-remember-templates "org-capture" "\
 Set `org-capture-templates' to be similar to `org-remember-templates'." t nil)
 
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-capture" '("org-")))
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-capture" '("org-capture-")))
 
 ;;;***
 
@@ -23693,24 +23949,54 @@ column specification.
 
 (autoload 'org-dblock-write:columnview "org-colview" "\
 Write the column view table.
+
 PARAMS is a property list of parameters:
 
-:id       the :ID: property of the entry where the columns view
-         should be built.  When the symbol `local', call locally.
-         When `global' call column view with the cursor at the beginning
-         of the buffer (usually this means that the whole buffer switches
-         to column view).  When \"file:path/to/file.org\", invoke column
-         view at the start of that file.  Otherwise, the ID is located
-         using `org-id-find'.
-:hlines   When t, insert a hline before each item.  When a number, insert
-         a hline before each level <= that number.
-:indent   When non-nil, indent each ITEM field according to its level.
-:vlines   When t, make each column a colgroup to enforce vertical lines.
-:maxlevel When set to a number, don't capture headlines below this level.
-:skip-empty-rows
-         When t, skip rows where all specifiers other than ITEM are empty.
-:width    apply widths specified in columns format using <N> specifiers.
-:format   When non-nil, specify the column view format to use.
+`:id' (mandatory)
+
+    The ID property of the entry where the columns view should be
+    built.  When the symbol `local', call locally.  When `global'
+    call column view with the cursor at the beginning of the
+    buffer (usually this means that the whole buffer switches to
+    column view).  When \"file:path/to/file.org\", invoke column
+    view at the start of that file.  Otherwise, the ID is located
+    using `org-id-find'.
+
+`:exclude-tags'
+
+    List of tags to exclude from column view table.
+
+`:format'
+
+    When non-nil, specify the column view format to use.
+
+`:hlines'
+
+    When non-nil, insert a hline before each item.  When
+    a number, insert a hline before each level inferior or equal
+    to that number.
+
+`:indent'
+
+    When non-nil, indent each ITEM field according to its level.
+
+`:match'
+
+    When set to a string, use this as a tags/property match filter.
+
+`:maxlevel'
+
+    When set to a number, don't capture headlines below this level.
+
+`:skip-empty-rows'
+
+    When non-nil, skip rows where all specifiers other than ITEM
+    are empty.
+
+`:vlines'
+
+    When non-nil, make each column a column group to enforce
+    vertical lines.
 
 \(fn PARAMS)" nil nil)
 
@@ -23756,13 +24042,6 @@ Try very hard to provide sensible version strings." 
nil t)
 
 ;;;***
 
-;;;### (autoloads nil "org-docview" "org/org-docview.el" (0 0 0 0))
-;;; Generated autoloads from org/org-docview.el
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-docview" '("org-docview-")))
-
-;;;***
-
 ;;;### (autoloads nil "org-duration" "org/org-duration.el" (0 0 0
 ;;;;;;  0))
 ;;; Generated autoloads from org/org-duration.el
@@ -23834,20 +24113,6 @@ with \"H:MM:SS\" format, return `h:mm:ss'.  Otherwise, 
return
 
 ;;;***
 
-;;;### (autoloads nil "org-eshell" "org/org-eshell.el" (0 0 0 0))
-;;; Generated autoloads from org/org-eshell.el
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-eshell" '("org-eshell-")))
-
-;;;***
-
-;;;### (autoloads nil "org-eww" "org/org-eww.el" (0 0 0 0))
-;;; Generated autoloads from org/org-eww.el
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-eww" '("org-eww-")))
-
-;;;***
-
 ;;;### (autoloads nil "org-faces" "org/org-faces.el" (0 0 0 0))
 ;;; Generated autoloads from org/org-faces.el
 
@@ -23871,10 +24136,39 @@ with \"H:MM:SS\" format, return `h:mm:ss'.  
Otherwise, return
 
 ;;;***
 
-;;;### (autoloads nil "org-gnus" "org/org-gnus.el" (0 0 0 0))
-;;; Generated autoloads from org/org-gnus.el
+;;;### (autoloads nil "org-goto" "org/org-goto.el" (0 0 0 0))
+;;; Generated autoloads from org/org-goto.el
+
+(autoload 'org-goto-location "org-goto" "\
+Let the user select a location in current buffer.
+This function uses a recursive edit.  It returns the selected
+position or nil.
+
+\(fn &optional BUF HELP)" nil nil)
+
+(autoload 'org-goto "org-goto" "\
+Look up a different location in the current file, keeping current visibility.
+
+When you want look-up or go to a different location in a
+document, the fastest way is often to fold the entire buffer and
+then dive into the tree.  This method has the disadvantage, that
+the previous location will be folded, which may not be what you
+want.
+
+This command works around this by showing a copy of the current
+buffer in an indirect buffer, in overview mode.  You can dive
+into the tree in that copy, use org-occur and incremental search
+to find a location.  When pressing RET or `Q', the command
+returns to the original buffer in which the visibility is still
+unchanged.  After RET it will also jump to the location selected
+in the indirect buffer and expose the headline hierarchy above.
+
+With a prefix argument, use the alternative interface: e.g., if
+`org-goto-interface' is `outline' use `outline-path-completion'.
 
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-gnus" '("org-gnus-")))
+\(fn &optional ALTERNATIVE-INTERFACE)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-goto" '("org-goto-")))
 
 ;;;***
 
@@ -23901,13 +24195,6 @@ with \"H:MM:SS\" format, return `h:mm:ss'.  Otherwise, 
return
 
 ;;;***
 
-;;;### (autoloads nil "org-info" "org/org-info.el" (0 0 0 0))
-;;; Generated autoloads from org/org-info.el
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-info" '("org-info-")))
-
-;;;***
-
 ;;;### (autoloads nil "org-inlinetask" "org/org-inlinetask.el" (0
 ;;;;;;  0 0 0))
 ;;; Generated autoloads from org/org-inlinetask.el
@@ -23916,11 +24203,13 @@ with \"H:MM:SS\" format, return `h:mm:ss'.  
Otherwise, return
 
 ;;;***
 
-;;;### (autoloads "actual autoloads are elsewhere" "org-irc" "org/org-irc.el"
-;;;;;;  (0 0 0 0))
-;;; Generated autoloads from org/org-irc.el
+;;;### (autoloads nil "org-keys" "org/org-keys.el" (0 0 0 0))
+;;; Generated autoloads from org/org-keys.el
 
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-irc" '("org-irc-")))
+(autoload 'org-babel-describe-bindings "org-keys" "\
+Describe all keybindings behind `org-babel-key-prefix'." t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-keys" '("org-")))
 
 ;;;***
 
@@ -23968,13 +24257,6 @@ Load FILE with optional arguments NOERROR and 
MUSTSUFFIX.
 
 ;;;***
 
-;;;### (autoloads nil "org-mhe" "org/org-mhe.el" (0 0 0 0))
-;;; Generated autoloads from org/org-mhe.el
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-mhe" '("org-mhe-")))
-
-;;;***
-
 ;;;### (autoloads "actual autoloads are elsewhere" "org-mobile" 
"org/org-mobile.el"
 ;;;;;;  (0 0 0 0))
 ;;; Generated autoloads from org/org-mobile.el
@@ -23990,6 +24272,29 @@ Load FILE with optional arguments NOERROR and 
MUSTSUFFIX.
 
 ;;;***
 
+;;;### (autoloads nil "org-num" "org/org-num.el" (0 0 0 0))
+;;; Generated autoloads from org/org-num.el
+
+(autoload 'org-num-default-format "org-num" "\
+Default numbering display function.
+NUMBERING is a list of numbers.
+
+\(fn NUMBERING)" nil nil)
+
+(autoload 'org-num-mode "org-num" "\
+Dynamic numbering of headlines in an Org buffer.
+
+If called interactively, enable Org-Num mode if ARG is positive, and
+disable it if ARG is zero or negative.  If called from Lisp, also
+enable the mode if ARG is omitted or nil, and toggle it if ARG is
+`toggle'; disable the mode otherwise.
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-num" '("org-num-")))
+
+;;;***
+
 ;;;### (autoloads nil "org-pcomplete" "org/org-pcomplete.el" (0 0
 ;;;;;;  0 0))
 ;;; Generated autoloads from org/org-pcomplete.el
@@ -24014,13 +24319,6 @@ Load FILE with optional arguments NOERROR and 
MUSTSUFFIX.
 
 ;;;***
 
-;;;### (autoloads nil "org-rmail" "org/org-rmail.el" (0 0 0 0))
-;;; Generated autoloads from org/org-rmail.el
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-rmail" '("org-rmail-")))
-
-;;;***
-
 ;;;### (autoloads nil "org-src" "org/org-src.el" (0 0 0 0))
 ;;; Generated autoloads from org/org-src.el
 
@@ -24036,6 +24334,13 @@ Load FILE with optional arguments NOERROR and 
MUSTSUFFIX.
 
 ;;;***
 
+;;;### (autoloads nil "org-tempo" "org/org-tempo.el" (0 0 0 0))
+;;; Generated autoloads from org/org-tempo.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-tempo" '("org-tempo-")))
+
+;;;***
+
 ;;;### (autoloads "actual autoloads are elsewhere" "org-timer" 
"org/org-timer.el"
 ;;;;;;  (0 0 0 0))
 ;;; Generated autoloads from org/org-timer.el
@@ -24057,13 +24362,6 @@ Inserted by installing Org or when a release is made." 
nil nil)
 
 ;;;***
 
-;;;### (autoloads nil "org-w3m" "org/org-w3m.el" (0 0 0 0))
-;;; Generated autoloads from org/org-w3m.el
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"org-w3m" '("org-w3m-")))
-
-;;;***
-
 ;;;### (autoloads nil "outline" "outline.el" (0 0 0 0))
 ;;; Generated autoloads from outline.el
 (put 'outline-regexp 'safe-local-variable 'stringp)
@@ -24418,8 +24716,9 @@ matching parenthesis is highlighted in 
`show-paren-style' after
 
 (autoload 'parse-time-string "parse-time" "\
 Parse the time in STRING into (SEC MIN HOUR DAY MON YEAR DOW DST TZ).
-STRING should be something resembling an RFC 822 (or later) date-time, e.g.,
-\"Fri, 25 Mar 2016 16:24:56 +0100\", but this function is
+STRING should be an ISO 8601 time string, e.g., \"2020-01-15T16:12:21-08:00\",
+or something resembling an RFC 822 (or later) date-time, e.g.,
+\"Wed, 15 Jan 2020 16:12:21 -0800\".  This function is
 somewhat liberal in what format it accepts, and will attempt to
 return a \"likely\" value even for somewhat malformed strings.
 The values returned are identical to those of `decode-time', but
@@ -27123,11 +27422,11 @@ nil
     necessary to ensure that a postfix operator appended to it will
     apply to the whole expression.
 
-The optional argument KEEP-ORDER, if nil or omitted, allows the
-returned regexp to match the strings in any order.  If non-nil,
-the match is guaranteed to be performed in the order given, as if
-the strings were made into a regexp by joining them with the
-`\\|' operator.
+The optional argument KEEP-ORDER, if non-nil, forces the match to
+be performed in the order given, as if the strings were made into
+a regexp by joining them with the `\\|' operator.  If nil or
+omitted, the returned regexp is will always match the longest
+string possible.
 
 Up to reordering, the resulting regexp is equivalent to but
 usually more efficient than that of a simplified version:
@@ -28167,8 +28466,12 @@ CHAR           Match a literal character.
                 character, a string, a range as string \"A-Z\" or cons
                 (?A . ?Z), or a character class (see below).  Alias: in, char.
 \(not CHARSPEC)  Match one character not matched by CHARSPEC.  CHARSPEC
-                can be (any ...), (syntax ...), (category ...),
+                can be a character, single-char string, (any ...), (or ...),
+                (intersection ...), (syntax ...), (category ...),
                 or a character class.
+\(intersection CHARSET...) Match all CHARSETs.
+                CHARSET is (any...), (not...), (or...) or (intersection...),
+                a character or a single-char string.
 not-newline     Match any character except a newline.  Alias: nonl.
 anychar         Match any character.  Alias: anything.
 unmatchable     Never match anything at all.
@@ -28347,6 +28650,14 @@ For more details, see Info node `(elisp) Extending Rx'.
 
 ;;;***
 
+;;;### (autoloads nil "sasl-scram-sha256" "net/sasl-scram-sha256.el"
+;;;;;;  (0 0 0 0))
+;;; Generated autoloads from net/sasl-scram-sha256.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"sasl-scram-sha256" '("sasl-scram-sha")))
+
+;;;***
+
 ;;;### (autoloads nil "savehist" "savehist.el" (0 0 0 0))
 ;;; Generated autoloads from savehist.el
 (push (purecopy '(savehist 24)) package--builtin-versions)
@@ -28448,13 +28759,6 @@ file:
 
 ;;;***
 
-;;;### (autoloads nil "sb-image" "sb-image.el" (0 0 0 0))
-;;; Generated autoloads from sb-image.el
-
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"sb-image" '("defimage-speedbar" "speedbar-")))
-
-;;;***
-
 ;;;### (autoloads nil "scheme" "progmodes/scheme.el" (0 0 0 0))
 ;;; Generated autoloads from progmodes/scheme.el
 
@@ -29570,6 +29874,12 @@ If SEQUENCE is empty, return INITIAL-VALUE and 
FUNCTION is not called.
 
 \(fn FUNCTION SEQUENCE INITIAL-VALUE)" nil nil)
 
+(autoload 'seq-some "seq" "\
+Return non-nil if PRED is satisfied for at least one element of SEQUENCE.
+If so, return the first non-nil value returned by PRED.
+
+\(fn PRED SEQUENCE)" nil nil)
+
 (autoload 'seq-find "seq" "\
 Return the first element for which (PRED element) is non-nil in SEQUENCE.
 If no element is found, return DEFAULT.
@@ -29705,7 +30015,7 @@ These are active only in the minibuffer, when entering 
or editing a
 formula:
 \\{ses-mode-edit-map}" t nil)
 
-(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ses" '("1value" "noreturn" "ses")))
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"ses" '("ses")))
 
 ;;;***
 
@@ -30424,7 +30734,7 @@ values), despite potential performance issues, type 
\\[so-long-revert].
 
 Use \\[so-long-commentary] for more information.
 
-Use \\[so-long-customize] to configure the behaviour.
+Use \\[so-long-customize] to configure the behavior.
 
 \(fn)" t nil)
 
@@ -30461,7 +30771,7 @@ or call the function `global-so-long-mode'.")
 (custom-autoload 'global-so-long-mode "so-long" nil)
 
 (autoload 'global-so-long-mode "so-long" "\
-Toggle automated performance mitigations for files with long lines.
+Toggle automated performance mitigation for files with long lines.
 
 If called interactively, enable Global So-Long mode if ARG is
 positive, and disable it if ARG is zero or negative.  If called from
@@ -30480,7 +30790,7 @@ When such files are detected by `so-long-predicate', we 
invoke the selected
 
 Use \\[so-long-commentary] for more information.
 
-Use \\[so-long-customize] to configure the behaviour.
+Use \\[so-long-customize] to configure the behavior.
 
 \(fn &optional ARG)" t nil)
 
@@ -33326,7 +33636,7 @@ Return the symbol at point, or nil if none is found." 
nil nil)
 (autoload 'number-at-point "thingatpt" "\
 Return the number at point, or nil if none is found.
 Decimal numbers like \"14\" or \"-14.5\", as well as hex numbers
-like \"0xBEEF09\" or \"#xBEEF09\", are regognized." nil nil)
+like \"0xBEEF09\" or \"#xBEEF09\", are recognized." nil nil)
 
 (autoload 'list-at-point "thingatpt" "\
 Return the Lisp list at point, or nil if none is found.
@@ -33718,7 +34028,7 @@ Update the time stamp string(s) in the buffer.
 A template in a file can be automatically updated with a new time stamp
 every time you save the file.  Add this line to your init file:
     (add-hook \\='before-save-hook \\='time-stamp)
-or customize `before-save-hook' through Custom.
+or customize option `before-save-hook'.
 Normally the template must appear in the first 8 lines of a file and
 look like one of the following:
       Time-stamp: <>
@@ -34156,7 +34466,7 @@ the output buffer or changing the window configuration.
 
 ;;;### (autoloads nil "tramp" "net/tramp.el" (0 0 0 0))
 ;;; Generated autoloads from net/tramp.el
-(push (purecopy '(tramp 2 4 3 -1)) package--builtin-versions)
+(push (purecopy '(tramp 2 5 0 -1)) package--builtin-versions)
 
 (defvar tramp-mode t "\
 Whether Tramp is enabled.
@@ -34164,7 +34474,7 @@ If it is set to nil, all remote file names are used 
literally.")
 
 (custom-autoload 'tramp-mode "tramp" t)
 
-(defconst tramp-initial-file-name-regexp "\\`/.+:.*:" "\
+(defconst tramp-initial-file-name-regexp "\\`/[^/:]+:[^/:]*:" "\
 Value for `tramp-file-name-regexp' for autoload.
 It must match the initial `tramp-syntax' settings.")
 
@@ -34175,7 +34485,7 @@ names.  When calling 
`tramp-register-file-name-handlers', the
 initial value is overwritten by the car of `tramp-file-name-structure'.")
 
 (defvar tramp-ignored-file-name-regexp nil "\
-Regular expression matching file names that are not under Tramp’s control.")
+Regular expression matching file names that are not under Tramp's control.")
 
 (custom-autoload 'tramp-ignored-file-name-regexp "tramp" t)
 
@@ -34186,20 +34496,17 @@ match file names at root of the underlying local file 
system,
 like \"/sys\" or \"/C:\".")
 
 (defun tramp-autoload-file-name-handler (operation &rest args) "\
-Load Tramp file name handler, and perform OPERATION." 
(tramp-unload-file-name-handlers) (if tramp-mode (let ((default-directory 
temporary-file-directory)) (load "tramp" 'noerror 'nomessage))) (apply 
operation args))
+Load Tramp file name handler, and perform OPERATION." 
(tramp-unload-file-name-handlers) (when tramp-mode (let ((default-directory 
temporary-file-directory)) (load "tramp" 'noerror 'nomessage))) (apply 
operation args))
 
 (defun tramp-register-autoload-file-name-handlers nil "\
-Add Tramp file name handlers to `file-name-handler-alist' during autoload." 
(add-to-list 'file-name-handler-alist (cons tramp-autoload-file-name-regexp 
'tramp-autoload-file-name-handler)) (put 'tramp-autoload-file-name-handler 
'safe-magic t))
+Add Tramp file name handlers to `file-name-handler-alist' during autoload." 
(add-to-list 'file-name-handler-alist (cons tramp-autoload-file-name-regexp 
'tramp-autoload-file-name-handler)) (put #'tramp-autoload-file-name-handler 
'safe-magic t))
  (tramp-register-autoload-file-name-handlers)
 
 (defun tramp-unload-file-name-handlers nil "\
 Unload Tramp file name handlers from `file-name-handler-alist'." (dolist (fnh 
file-name-handler-alist) (when (and (symbolp (cdr fnh)) (string-prefix-p 
"tramp-" (symbol-name (cdr fnh)))) (setq file-name-handler-alist (delq fnh 
file-name-handler-alist)))))
 
-(defvar tramp-completion-mode nil "\
-If non-nil, external packages signal that they are in file name completion.")
-
-(autoload 'tramp-unload-tramp "tramp" "\
-Discard Tramp from loading remote files." t nil)
+(defun tramp-unload-tramp nil "\
+Discard Tramp from loading remote files." (interactive) (ignore-errors 
(unload-feature 'tramp 'force)))
 
 (if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"tramp" '("tramp-" "with-")))
 
@@ -34233,7 +34540,7 @@ Regular expression matching archive file names." 
'(concat "\\`" "\\(" ".+" "\\."
 (defalias 'tramp-archive-autoload-file-name-handler 
#'tramp-autoload-file-name-handler)
 
 (defun tramp-register-archive-file-name-handler nil "\
-Add archive file name handler to `file-name-handler-alist'." (when 
tramp-archive-enabled (add-to-list 'file-name-handler-alist (cons 
(tramp-archive-autoload-file-name-regexp) 
#'tramp-archive-autoload-file-name-handler)) (put 
'tramp-archive-autoload-file-name-handler 'safe-magic t)))
+Add archive file name handler to `file-name-handler-alist'." (when 
tramp-archive-enabled (add-to-list 'file-name-handler-alist (cons 
(tramp-archive-autoload-file-name-regexp) 
#'tramp-archive-autoload-file-name-handler)) (put 
#'tramp-archive-autoload-file-name-handler 'safe-magic t)))
 
 (add-hook 'after-init-hook #'tramp-register-archive-file-name-handler)
 
@@ -36240,7 +36547,7 @@ Key bindings:
 ;;;### (autoloads nil "verilog-mode" "progmodes/verilog-mode.el"
 ;;;;;;  (0 0 0 0))
 ;;; Generated autoloads from progmodes/verilog-mode.el
-(push (purecopy '(verilog-mode 2019 11 21 248091482)) 
package--builtin-versions)
+(push (purecopy '(verilog-mode 2019 12 17 268053413)) 
package--builtin-versions)
 
 (autoload 'verilog-mode "verilog-mode" "\
 Major mode for editing Verilog code.
@@ -38031,6 +38338,11 @@ Display the next buffer in the same window.
 
 \(fn &optional ARG)" t nil)
 
+(autoload 'windmove-display-new-tab "windmove" "\
+Display the next buffer in a new tab.
+
+\(fn &optional ARG)" t nil)
+
 (autoload 'windmove-display-default-keybindings "windmove" "\
 Set up keybindings for directional buffer display.
 Keys are bound to commands that display the next buffer in the specified
@@ -38344,13 +38656,32 @@ The argument has the same meaning as in `apropos'.
  (define-key ctl-x-4-map "." #'xref-find-definitions-other-window)
  (define-key ctl-x-5-map "." #'xref-find-definitions-other-frame)
 
-(autoload 'xref-collect-matches "xref" "\
-Collect matches for REGEXP inside FILES in DIR.
+(autoload 'xref-references-in-directory "xref" "\
+Find all references to SYMBOL in directory DIR.
+Return a list of xref values.
+
+This function uses the Semantic Symbol Reference API, see
+`semantic-symref-tool-alist' for details on which tools are used,
+and when.
+
+\(fn SYMBOL DIR)" nil nil)
+
+(autoload 'xref-matches-in-directory "xref" "\
+Find all matches for REGEXP in directory DIR.
+Return a list of xref values.
+Only files matching some of FILES and none of IGNORES are searched.
 FILES is a string with glob patterns separated by spaces.
-IGNORES is a list of glob patterns.
+IGNORES is a list of glob patterns for files to ignore.
 
 \(fn REGEXP FILES DIR IGNORES)" nil nil)
 
+(autoload 'xref-matches-in-files "xref" "\
+Find all matches for REGEXP in FILES.
+Return a list of xref values.
+FILES must be a list of absolute file names.
+
+\(fn REGEXP FILES)" nil nil)
+
 (if (fboundp 'register-definition-prefixes) (register-definition-prefixes 
"xref" '("xref-")))
 
 ;;;***
@@ -38555,25 +38886,25 @@ Zone out, completely." t nil)
 ;;;;;;  "mail/rmailmsc.el" "mail/rmailsort.el" "mail/rmailsum.el"
 ;;;;;;  "mail/undigest.el" "menu-bar.el" "mh-e/mh-gnus.el" 
"mh-e/mh-loaddefs.el"
 ;;;;;;  "minibuffer.el" "mouse.el" "net/tramp-loaddefs.el" "newcomment.el"
-;;;;;;  "obarray.el" "org/ob-core.el" "org/ob-keys.el" "org/ob-lob.el"
-;;;;;;  "org/ob-matlab.el" "org/ob-tangle.el" "org/ob.el" "org/org-archive.el"
-;;;;;;  "org/org-attach.el" "org/org-bbdb.el" "org/org-clock.el"
+;;;;;;  "obarray.el" "org/ob-core.el" "org/ob-lob.el" "org/ob-matlab.el"
+;;;;;;  "org/ob-tangle.el" "org/ob.el" "org/ol-bbdb.el" "org/ol-irc.el"
+;;;;;;  "org/org-archive.el" "org/org-attach.el" "org/org-clock.el"
 ;;;;;;  "org/org-datetree.el" "org/org-element.el" "org/org-feed.el"
 ;;;;;;  "org/org-footnote.el" "org/org-id.el" "org/org-indent.el"
-;;;;;;  "org/org-install.el" "org/org-irc.el" "org/org-mobile.el"
-;;;;;;  "org/org-plot.el" "org/org-table.el" "org/org-timer.el" 
"org/ox-ascii.el"
-;;;;;;  "org/ox-beamer.el" "org/ox-html.el" "org/ox-icalendar.el"
-;;;;;;  "org/ox-latex.el" "org/ox-man.el" "org/ox-md.el" "org/ox-odt.el"
-;;;;;;  "org/ox-org.el" "org/ox-publish.el" "org/ox-texinfo.el" "org/ox.el"
-;;;;;;  "progmodes/elisp-mode.el" "progmodes/prog-mode.el" "ps-mule.el"
-;;;;;;  "register.el" "replace.el" "rfn-eshadow.el" "select.el" "simple.el"
-;;;;;;  "startup.el" "subdirs.el" "subr.el" "tab-bar.el" "textmodes/fill.el"
-;;;;;;  "textmodes/page.el" "textmodes/paragraphs.el" "textmodes/reftex-auc.el"
-;;;;;;  "textmodes/reftex-cite.el" "textmodes/reftex-dcr.el" 
"textmodes/reftex-global.el"
-;;;;;;  "textmodes/reftex-index.el" "textmodes/reftex-parse.el" 
"textmodes/reftex-ref.el"
-;;;;;;  "textmodes/reftex-sel.el" "textmodes/reftex-toc.el" 
"textmodes/text-mode.el"
-;;;;;;  "uniquify.el" "vc/ediff-hook.el" "vc/vc-hooks.el" "version.el"
-;;;;;;  "widget.el" "window.el") (0 0 0 0))
+;;;;;;  "org/org-install.el" "org/org-mobile.el" "org/org-plot.el"
+;;;;;;  "org/org-table.el" "org/org-timer.el" "org/ox-ascii.el" 
"org/ox-beamer.el"
+;;;;;;  "org/ox-html.el" "org/ox-icalendar.el" "org/ox-latex.el"
+;;;;;;  "org/ox-man.el" "org/ox-md.el" "org/ox-odt.el" "org/ox-org.el"
+;;;;;;  "org/ox-publish.el" "org/ox-texinfo.el" "org/ox.el" 
"progmodes/elisp-mode.el"
+;;;;;;  "progmodes/prog-mode.el" "ps-mule.el" "register.el" "replace.el"
+;;;;;;  "rfn-eshadow.el" "select.el" "simple.el" "startup.el" "subdirs.el"
+;;;;;;  "subr.el" "tab-bar.el" "textmodes/fill.el" "textmodes/page.el"
+;;;;;;  "textmodes/paragraphs.el" "textmodes/reftex-auc.el" 
"textmodes/reftex-cite.el"
+;;;;;;  "textmodes/reftex-dcr.el" "textmodes/reftex-global.el" 
"textmodes/reftex-index.el"
+;;;;;;  "textmodes/reftex-parse.el" "textmodes/reftex-ref.el" 
"textmodes/reftex-sel.el"
+;;;;;;  "textmodes/reftex-toc.el" "textmodes/text-mode.el" "uniquify.el"
+;;;;;;  "vc/ediff-hook.el" "vc/vc-hooks.el" "version.el" "widget.el"
+;;;;;;  "window.el") (0 0 0 0))
 
 ;;;***
 
diff --git a/lisp/leim/quail/latin-ltx.el b/lisp/leim/quail/latin-ltx.el
index a9ea2bb..78ffca9 100644
--- a/lisp/leim/quail/latin-ltx.el
+++ b/lisp/leim/quail/latin-ltx.el
@@ -656,10 +656,34 @@ system, including many technical ones.  Examples:
  ("\\wp" ?℘)
  ("\\wr" ?≀)
 
- ("\\Bbb{N}" ?ℕ)                       ; AMS commands for blackboard bold
- ("\\Bbb{P}" ?ℙ)                       ; Also sometimes \mathbb.
+ ("\\Bbb{A}" ?𝔸)                       ; AMS commands for blackboard bold
+ ("\\Bbb{B}" ?𝔹)                       ; Also sometimes \mathbb.
+ ("\\Bbb{C}" ?ℂ)
+ ("\\Bbb{D}" ?𝔻)
+ ("\\Bbb{E}" ?𝔼)
+ ("\\Bbb{F}" ?𝔽)
+ ("\\Bbb{G}" ?𝔾)
+ ("\\Bbb{H}" ?ℍ)
+ ("\\Bbb{I}" ?𝕀)
+ ("\\Bbb{J}" ?𝕁)
+ ("\\Bbb{K}" ?𝕂)
+ ("\\Bbb{L}" ?𝕃)
+ ("\\Bbb{M}" ?𝕄)
+ ("\\Bbb{N}" ?ℕ)
+ ("\\Bbb{O}" ?𝕆)
+ ("\\Bbb{P}" ?ℙ)
+ ("\\Bbb{Q}" ?ℚ)
  ("\\Bbb{R}" ?ℝ)
+ ("\\Bbb{S}" ?𝕊)
+ ("\\Bbb{T}" ?𝕋)
+ ("\\Bbb{U}" ?𝕌)
+ ("\\Bbb{V}" ?𝕍)
+ ("\\Bbb{W}" ?𝕎)
+ ("\\Bbb{X}" ?𝕏)
+ ("\\Bbb{Y}" ?𝕐)
  ("\\Bbb{Z}" ?ℤ)
+ ("\\Bbb{1}" ?𝟙)
+ ("\\Bbb{2}" ?𝟚)
  ("--" ?–)
  ("---" ?—)
  ;; We used to use ~ for NBSP but that's inconvenient and may even look like
@@ -703,7 +727,9 @@ system, including many technical ones.  Examples:
  ("\\ldq" ?\“)
  ("\\rdq" ?\”)
  ("\\defs" ?≙)                         ; per fuzz/zed
- ;; ("\\sqrt[3]" ?∛)
+ ("\\sqrt" ?√)
+ ("\\sqrt[3]" ?∛)
+ ("\\sqrt[4]" ?∜)
  ("\\llbracket" ?\〚)                   ; stmaryrd
  ("\\rrbracket" ?\〛)
  ;; ("\\lbag" ?\〚)                     ; fuzz
diff --git a/lisp/loadup.el b/lisp/loadup.el
index 04ec5ca..97525b2 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -245,7 +245,9 @@
 (load "language/cham")
 
 (load "indent")
-(load "emacs-lisp/cl-generic")
+(let ((max-specpdl-size (max max-specpdl-size 1800)))
+  ;; A particularly demanding file to load; 1600 does not seem to be enough.
+  (load "emacs-lisp/cl-generic"))
 (load "minibuffer") ;Needs cl-generic (and define-minor-mode).
 (load "frame")
 (load "startup")
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el
index d798ffa..d79cea9 100644
--- a/lisp/mail/rmail.el
+++ b/lisp/mail/rmail.el
@@ -4392,9 +4392,8 @@ browsing, and moving of messages."
                  (text face mouse function &optional token prevline))
 
 ;; Make sure our special speedbar major mode is loaded
-(if (featurep 'speedbar)
-    (rmail-install-speedbar-variables)
-  (add-hook 'speedbar-load-hook 'rmail-install-speedbar-variables))
+(with-eval-after-load 'speedbar
+  (rmail-install-speedbar-variables))
 
 (defun rmail-speedbar-buttons (buffer)
   "Create buttons for BUFFER containing rmail messages.
diff --git a/lisp/mail/rmailsum.el b/lisp/mail/rmailsum.el
index 3ae2e40..cc55451 100644
--- a/lisp/mail/rmailsum.el
+++ b/lisp/mail/rmailsum.el
@@ -391,7 +391,7 @@ SUBJECT is a regular expression."
 (defun rmail-summary-by-senders (senders)
   "Display a summary of all messages whose \"From\" field matches SENDERS.
 SENDERS is a regular expression.  The default for SENDERS matches the
-sender of the current messsage."
+sender of the current message."
   (interactive
    (let* ((def (rmail-get-header "From"))
           ;; We quote the default argument, because if it contains regexp
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
index 90f9ef7..731da19 100644
--- a/lisp/menu-bar.el
+++ b/lisp/menu-bar.el
@@ -1476,6 +1476,18 @@ mail status in mode line"))
     (bindings--define-key menu [cursor-separator]
       menu-bar-separator)
 
+    (bindings--define-key menu [save-desktop]
+      (menu-bar-make-toggle
+       toggle-save-desktop-globally desktop-save-mode
+       "Save State between Sessions"
+       "Saving desktop state %s"
+       "Visit desktop of previous session when restarting Emacs"
+       (require 'desktop)
+       ;; Do it by name, to avoid a free-variable
+       ;; warning during byte compilation.
+       (set-default
+       'desktop-save-mode (not (symbol-value 'desktop-save-mode)))))
+
     (bindings--define-key menu [save-place]
       (menu-bar-make-toggle
        toggle-save-place-globally save-place-mode
@@ -1649,6 +1661,27 @@ mail status in mode line"))
 
     menu))
 
+(defvar menu-bar-shell-commands-menu
+  (let ((menu (make-sparse-keymap "Shell Commands")))
+    (bindings--define-key menu [interactive-shell]
+      '(menu-item "Run Shell Interactively" shell
+                  :help "Run a subshell interactively"))
+
+    (bindings--define-key menu [async-shell-command]
+      '(menu-item "Async Shell Command..." async-shell-command
+                  :help "Invoke a shell command asynchronously in background"))
+
+    (bindings--define-key menu [shell-on-region]
+      '(menu-item "Shell Command on Region..." shell-command-on-region
+                  :enable mark-active
+                  :help "Pass marked region to a shell command"))
+
+    (bindings--define-key menu [shell]
+      '(menu-item "Shell Command..." shell-command
+                  :help "Invoke a shell command and catch its output"))
+
+    menu))
+
 (defun menu-bar-read-mail ()
   "Read mail using `read-mail-command'."
   (interactive)
@@ -1740,16 +1773,14 @@ mail status in mode line"))
     (bindings--define-key menu [gdb]
       '(menu-item "Debugger (GDB)..." gdb
                   :help "Debug a program from within Emacs with GDB"))
-    (bindings--define-key menu [shell-on-region]
-      '(menu-item "Shell Command on Region..." shell-command-on-region
-                  :enable mark-active
-                  :help "Pass marked region to a shell command"))
-    (bindings--define-key menu [shell]
-      '(menu-item "Shell Command..." shell-command
-                  :help "Invoke a shell command and catch its output"))
     (bindings--define-key menu [compile]
       '(menu-item "Compile..." compile
                   :help "Invoke compiler or Make, view compilation errors"))
+
+    (bindings--define-key menu [shell-commands]
+      `(menu-item "Shell Commands"
+                  ,menu-bar-shell-commands-menu))
+
     (bindings--define-key menu [rgrep]
       '(menu-item "Recursive Grep..." rgrep
                   :help "Interactively ask for parameters and search 
recursively"))
diff --git a/lisp/mh-e/mh-show.el b/lisp/mh-e/mh-show.el
index 8871059..952579f 100644
--- a/lisp/mh-e/mh-show.el
+++ b/lisp/mh-e/mh-show.el
@@ -221,6 +221,8 @@ Sets the current buffer to the show buffer."
              ;; pgp.el uses this.
              (if (boundp 'write-contents-hooks) ;Emacs 19
                  (kill-local-variable 'write-contents-hooks))
+             (font-lock-mode -1)
+             (mh-show-mode)
              (if formfile
                  (mh-exec-lib-cmd-output "mhl" "-nobell" "-noclear"
                                          (if (stringp formfile)
@@ -232,7 +234,6 @@ Sets the current buffer to the show buffer."
                (mh-add-missing-mime-version-header)
                (setf (mh-buffer-data) (mh-make-buffer-data))
                (mh-mime-display))
-             (mh-show-mode)
              ;; Header cleanup
              (goto-char (point-min))
              (cond (clean-message-header
@@ -252,13 +253,11 @@ Sets the current buffer to the show buffer."
              (setq buffer-backed-up nil)
              (auto-save-mode 1)
              (set-mark nil)
-             (unwind-protect
-                 (when (and mh-decode-mime-flag (not formfile))
-                   (setq buffer-read-only nil)
-                   (mh-display-smileys)
-                   (mh-display-emphasis))
-               (setq buffer-read-only t))
+             (when (and mh-decode-mime-flag (not formfile))
+               (mh-display-smileys)
+               (mh-display-emphasis))
              (set-buffer-modified-p nil)
+             (setq buffer-read-only t)
              (setq mh-show-folder-buffer folder)
              (setq mode-line-buffer-identification
                    (list (format mh-show-buffer-mode-line-buffer-id
@@ -870,7 +869,6 @@ See also `mh-folder-mode'.
   (easy-menu-add mh-show-folder-menu)
   (make-local-variable 'mh-show-folder-buffer)
   (buffer-disable-undo)
-  (setq buffer-read-only t)
   (use-local-map mh-show-mode-map))
 
 
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index a8b2a98..0589211 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -766,7 +766,7 @@ and `clear-minibuffer-message' called automatically via
 (defun set-minibuffer-message (message)
   "Temporarily display MESSAGE at the end of the minibuffer.
 The text is displayed for `minibuffer-message-clear-timeout' seconds
-(if the value is a number), or until the next input event arrives,
+\(if the value is a number), or until the next input event arrives,
 whichever comes first.
 Unlike `minibuffer-message', this function is called automatically
 via `set-message-function'."
@@ -790,8 +790,14 @@ via `set-message-function'."
         ;; The current C cursor code doesn't know to use the overlay's
         ;; marker's stickiness to figure out whether to place the cursor
         ;; before or after the string, so let's spoon-feed it the pos.
-        (put-text-property 0 1 'cursor t message))
+        (put-text-property 0 1 'cursor 1 message))
       (overlay-put minibuffer-message-overlay 'after-string message)
+      ;; Make sure the overlay with the message is displayed before
+      ;; any other overlays in that position, in case they have
+      ;; resize-mini-windows set to nil and the other overlay strings
+      ;; are too long for the mini-window width.  This makes sure the
+      ;; temporary message will always be visible.
+      (overlay-put minibuffer-message-overlay 'priority 1100)
 
       (when (numberp minibuffer-message-clear-timeout)
         (setq minibuffer-message-timer
@@ -2737,8 +2743,13 @@ See `read-file-name' for the meaning of the arguments."
   (unless dir (setq dir (or default-directory "~/")))
   (unless (file-name-absolute-p dir) (setq dir (expand-file-name dir)))
   (unless default-filename
-    (setq default-filename (if initial (expand-file-name initial dir)
-                             buffer-file-name)))
+    (setq default-filename
+          (cond
+           ((null initial) buffer-file-name)
+           ;; Special-case "" because (expand-file-name "" "/tmp/") returns
+           ;; "/tmp" rather than "/tmp/" (bug#39057).
+           ((equal "" initial) dir)
+           (t (expand-file-name initial dir)))))
   ;; If dir starts with user's homedir, change that to ~.
   (setq dir (abbreviate-file-name dir))
   ;; Likewise for default-filename.
diff --git a/lisp/msb.el b/lisp/msb.el
index ebaf98c..15aeaa2 100644
--- a/lisp/msb.el
+++ b/lisp/msb.el
@@ -372,6 +372,8 @@ This is instead of the groups in `msb-menu-cond'."
   :type 'hook
   :set 'msb-custom-set
   :group 'msb)
+(make-obsolete-variable 'msb-after-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 ;;;
 ;;; Internal variables
diff --git a/lisp/net/dns.el b/lisp/net/dns.el
index cefe085..78d4827 100644
--- a/lisp/net/dns.el
+++ b/lisp/net/dns.el
@@ -258,10 +258,8 @@ If TCP-P, the first two bytes of the package with be the 
length field."
       (nreverse spec))))
 
 (defun dns-read-int32 ()
-  ;; Full 32 bit Integers can't be handled by 32-bit Emacsen.  If we
-  ;; use floats, it works.
-  (format "%.0f" (+ (* (dns-read-bytes 1) 16777216.0)
-                   (dns-read-bytes 3))))
+  (declare (obsolete nil "28.1"))
+  (number-to-string (dns-read-bytes 4)))
 
 (defun dns-read-type (string type)
   (let ((buffer (current-buffer))
@@ -286,11 +284,11 @@ If TCP-P, the first two bytes of the package with be the 
length field."
            ((eq type 'SOA)
             (list (list 'mname (dns-read-name buffer))
                   (list 'rname (dns-read-name buffer))
-                  (list 'serial (dns-read-int32))
-                  (list 'refresh (dns-read-int32))
-                  (list 'retry (dns-read-int32))
-                  (list 'expire (dns-read-int32))
-                  (list 'minimum (dns-read-int32))))
+                 (list 'serial (dns-read-bytes 4))
+                 (list 'refresh (dns-read-bytes 4))
+                 (list 'retry (dns-read-bytes 4))
+                 (list 'expire (dns-read-bytes 4))
+                 (list 'minimum (dns-read-bytes 4))))
            ((eq type 'SRV)
             (list (list 'priority (dns-read-bytes 2))
                   (list 'weight (dns-read-bytes 2))
diff --git a/lisp/net/nsm.el b/lisp/net/nsm.el
index e94947b..2d36c5e 100644
--- a/lisp/net/nsm.el
+++ b/lisp/net/nsm.el
@@ -311,9 +311,9 @@ See also: `network-security-protocol-checks' and 
`nsm-noninteractive'"
                                                   (map-values results)
                                                   "\n")
                                                  "\n")
-                                                "\n* ")))))
-                 (delete-process process)
-                 (setq process nil)))
+                                               "\n* "))))))
+       (delete-process process)
+       (setq process nil))
       (run-hook-with-args 'nsm-tls-post-check-functions
                           host port status settings results)))
   process)
@@ -371,7 +371,7 @@ Reference:
 Sheffer, Holz, Saint-Andre (May 2015).  \"Recommendations for Secure
 Use of Transport Layer Security (TLS) and Datagram Transport Layer
 Security (DTLS)\", \"(4.1.  General Guidelines)\"
-`https://tools.ietf.org/html/rfc7525\#section-4.1'"
+`https://tools.ietf.org/html/rfc7525#section-4.1'"
   (let ((kx (plist-get status :key-exchange)))
     (and (string-match "^\\bRSA\\b" kx)
          (format-message
@@ -468,7 +468,7 @@ Reference:
 
 GnuTLS authors (2018). \"GnuTLS Manual 4.3.3 Anonymous
 authentication\",
-`https://www.gnutls.org/manual/gnutls.html\#Anonymous-authentication'"
+`https://www.gnutls.org/manual/gnutls.html#Anonymous-authentication'"
   (let ((kx (plist-get status :key-exchange)))
     (and (string-match "\\bANON\\b" kx)
          (format-message
@@ -603,7 +603,7 @@ References:
 full SHA-1\", `https://shattered.io/static/shattered.pdf'
 [2]: Chromium Security Education TLS/SSL.  \"Deprecated and Removed
 Features (SHA-1 Certificate Signatures)\",
-`https://www.chromium.org/Home/chromium-security/education/tls\#TOC-SHA-1-Certificate-Signatures'
+`https://www.chromium.org/Home/chromium-security/education/tls#TOC-SHA-1-Certificate-Signatures'
 [3]: Jones J.C (2017).  \"The end of SHA-1 on the Public Web\",
 
`https://blog.mozilla.org/security/2017/02/23/the-end-of-sha-1-on-the-public-web/'
 [4]: Apple Support (2017).  \"Move to SHA-256 signed certificates to
diff --git a/lisp/net/sasl-scram-sha256.el b/lisp/net/sasl-scram-sha256.el
new file mode 100644
index 0000000..e50a032
--- /dev/null
+++ b/lisp/net/sasl-scram-sha256.el
@@ -0,0 +1,59 @@
+;;; sasl-scram-sha256.el --- SCRAM-SHA-256 module for the SASL client 
framework  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2020 Free Software Foundation, Inc.
+
+;; Author: Simon Josefsson <address@hidden>
+;; Package: sasl
+
+;; 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:
+
+;; Implement the SCRAM-SHA-256 mechanism from RFC 7677.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'sasl)
+(require 'hex-util)
+(require 'rfc2104)
+(require 'sasl-scram-rfc)
+
+;;; SCRAM-SHA-256
+
+(defconst sasl-scram-sha-256-steps
+  '(sasl-scram-client-first-message
+    sasl-scram-sha-256-client-final-message
+    sasl-scram-sha-256-authenticate-server))
+
+(defun sasl-scram-sha256 (object &optional start end binary)
+  (secure-hash 'sha256 object start end binary))
+
+(defun sasl-scram-sha-256-client-final-message (client step)
+  (sasl-scram--client-final-message
+   ;; HMAC-SHA256 uses block length 64 and hash length 32; see RFC 4634.
+   'sasl-scram-sha256 64 32 client step))
+
+(defun sasl-scram-sha-256-authenticate-server (client step)
+  (sasl-scram--authenticate-server
+   'sasl-scram-sha256 64 32 client step))
+
+(put 'sasl-scram-sha256 'sasl-mechanism
+     (sasl-make-mechanism "SCRAM-SHA-256" sasl-scram-sha-256-steps))
+
+(provide 'sasl-scram-sha256)
+
+;;; sasl-scram-sha256.el ends here
diff --git a/lisp/net/sasl.el b/lisp/net/sasl.el
index 4405c90..ab118e1 100644
--- a/lisp/net/sasl.el
+++ b/lisp/net/sasl.el
@@ -35,8 +35,8 @@
 ;;; Code:
 
 (defvar sasl-mechanisms
-  '("SCRAM-SHA-1" "CRAM-MD5" "DIGEST-MD5" "PLAIN" "LOGIN" "ANONYMOUS"
-    "NTLM"))
+  '("SCRAM-SHA-256" "SCRAM-SHA-1" "CRAM-MD5" "DIGEST-MD5" "PLAIN" "LOGIN"
+    "ANONYMOUS" "NTLM"))
 
 (defvar sasl-mechanism-alist
   '(("CRAM-MD5" sasl-cram)
@@ -45,6 +45,7 @@
     ("LOGIN" sasl-login)
     ("ANONYMOUS" sasl-anonymous)
     ("NTLM" sasl-ntlm)
+    ("SCRAM-SHA-256" sasl-scram-sha256)
     ("SCRAM-SHA-1" sasl-scram-rfc)))
 
 (defvar sasl-unique-id-function #'sasl-unique-id-function)
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index 241180d..55c189b 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -1265,7 +1265,9 @@ START, and END.  Note that START and END should be 
markers."
                           (format "%s (%s)" iri title)
                         iri))
         'follow-link t
-        'mouse-face 'highlight))
+         ;; Make separate regions not `eq' so that they'll get
+         ;; separate mouse highlights.
+        'mouse-face (list 'highlight)))
   ;; Don't overwrite any keymaps that are already in the buffer (i.e.,
   ;; image keymaps).
   (while (and start
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 5cfcb81..aa7fe14 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -181,10 +181,9 @@ It is used for TCP/IP devices."
   "Invoke the ADB handler for OPERATION.
 First arg specifies the OPERATION, second arg is a list of
 ARGUMENTS to pass to the OPERATION."
-  (let ((fn (assoc operation tramp-adb-file-name-handler-alist)))
-    (if fn
-       (save-match-data (apply (cdr fn) arguments))
-      (tramp-run-real-handler operation arguments))))
+  (if-let ((fn (assoc operation tramp-adb-file-name-handler-alist)))
+      (save-match-data (apply (cdr fn) arguments))
+    (tramp-run-real-handler operation arguments)))
 
 ;;;###tramp-autoload
 (tramp--with-startup
@@ -234,8 +233,7 @@ ARGUMENTS to pass to the OPERATION."
   "Like `file-truename' for Tramp files."
   ;; Preserve trailing "/".
   (funcall
-   (if (tramp-compat-directory-name-p filename)
-       #'file-name-as-directory #'identity)
+   (if (directory-name-p filename) #'file-name-as-directory #'identity)
    ;; Quote properly.
    (funcall
     (if (tramp-compat-file-name-quoted-p filename)
@@ -719,14 +717,14 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
        (when (and (not ok-if-already-exists) (file-exists-p newname))
          (tramp-error v 'file-already-exists newname))
        (when (and (file-directory-p newname)
-                  (not (tramp-compat-directory-name-p newname)))
+                  (not (directory-name-p newname)))
          (tramp-error v 'file-error "File is a directory %s" newname))
 
        (with-tramp-progress-reporter
            v 0 (format "Copying %s to %s" filename newname)
          (if (and t1 t2 (tramp-equal-remote filename newname))
-             (let ((l1 (tramp-compat-file-local-name filename))
-                   (l2 (tramp-compat-file-local-name newname)))
+             (let ((l1 (tramp-file-local-name filename))
+                   (l2 (tramp-file-local-name newname)))
                ;; We must also flush the cache of the directory,
                ;; because `file-attributes' reads the values from
                ;; there.
@@ -739,39 +737,37 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
                    (tramp-shell-quote-argument l2))
                 "Error copying %s to %s" filename newname))
 
-           (let ((tmpfile (file-local-copy filename)))
-
-             (if tmpfile
-                 ;; Remote filename.
-                 (condition-case err
-                     (rename-file tmpfile newname ok-if-already-exists)
-                   ((error quit)
-                    (delete-file tmpfile)
-                    (signal (car err) (cdr err))))
-
-               ;; Remote newname.
-               (when (and (file-directory-p newname)
-                          (tramp-compat-directory-name-p newname))
-                 (setq newname
-                       (expand-file-name
-                        (file-name-nondirectory filename) newname)))
-
-               (with-parsed-tramp-file-name newname nil
-                 (when (and (not ok-if-already-exists)
-                            (file-exists-p newname))
-                   (tramp-error v 'file-already-exists newname))
-
-                 ;; We must also flush the cache of the directory,
-                 ;; because `file-attributes' reads the values from
-                 ;; there.
-                 (tramp-flush-file-properties v localname)
-                 (when (tramp-adb-execute-adb-command
-                        v "push"
-                        (tramp-compat-file-name-unquote filename)
-                        (tramp-compat-file-name-unquote localname))
-                   (tramp-error
-                    v 'file-error
-                    "Cannot copy `%s' `%s'" filename newname)))))))))
+           (if-let ((tmpfile (file-local-copy filename)))
+               ;; Remote filename.
+               (condition-case err
+                   (rename-file tmpfile newname ok-if-already-exists)
+                 ((error quit)
+                  (delete-file tmpfile)
+                  (signal (car err) (cdr err))))
+
+             ;; Remote newname.
+             (when (and (file-directory-p newname)
+                        (directory-name-p newname))
+               (setq newname
+                     (expand-file-name
+                      (file-name-nondirectory filename) newname)))
+
+             (with-parsed-tramp-file-name newname nil
+               (when (and (not ok-if-already-exists)
+                          (file-exists-p newname))
+                 (tramp-error v 'file-already-exists newname))
+
+               ;; We must also flush the cache of the directory,
+               ;; because `file-attributes' reads the values from
+               ;; there.
+               (tramp-flush-file-properties v localname)
+               (when (tramp-adb-execute-adb-command
+                      v "push"
+                      (tramp-compat-file-name-unquote filename)
+                      (tramp-compat-file-name-unquote localname))
+                 (tramp-error
+                  v 'file-error
+                  "Cannot copy `%s' `%s'" filename newname))))))))
 
     ;; KEEP-DATE handling.
     (when keep-date
@@ -801,7 +797,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
        (when (and (not ok-if-already-exists) (file-exists-p newname))
          (tramp-error v 'file-already-exists newname))
        (when (and (file-directory-p newname)
-                  (not (tramp-compat-directory-name-p newname)))
+                  (not (directory-name-p newname)))
          (tramp-error v 'file-error "File is a directory %s" newname))
 
        (with-tramp-progress-reporter
@@ -809,8 +805,8 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
          (if (and t1 t2
                   (tramp-equal-remote filename newname)
                   (not (file-directory-p filename)))
-             (let ((l1 (tramp-compat-file-local-name filename))
-                   (l2 (tramp-compat-file-local-name newname)))
+             (let ((l1 (tramp-file-local-name filename))
+                   (l2 (tramp-file-local-name newname)))
                ;; We must also flush the cache of the directory, because
                ;; `file-attributes' reads the values from there.
                (tramp-flush-file-properties v l1)
@@ -846,7 +842,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
        (setq infile (expand-file-name infile))
        (if (tramp-equal-remote default-directory infile)
            ;; INFILE is on the same remote host.
-           (setq input (with-parsed-tramp-file-name infile nil localname))
+           (setq input (tramp-file-local-name infile))
          ;; INFILE must be copied to remote host.
          (setq input (tramp-make-tramp-temp-file v)
                tmpinput (tramp-make-tramp-file-name v input))
@@ -877,8 +873,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
          (setcar (cdr destination) (expand-file-name (cadr destination)))
          (if (tramp-equal-remote default-directory (cadr destination))
              ;; stderr is on the same remote host.
-             (setq stderr (with-parsed-tramp-file-name
-                              (cadr destination) nil localname))
+             (setq stderr (tramp-file-local-name (cadr destination)))
            ;; stderr must be copied to remote host.  The temporary
            ;; file must be deleted after execution.
            (setq stderr (tramp-make-tramp-temp-file v)
@@ -936,6 +931,8 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
 ;; We use BUFFER also as connection buffer during setup.  Because of
 ;; this, its original contents must be saved, and restored once
 ;; connection has been setup.
+;; The complete STDERR buffer is available only when the process has
+;; terminated.
 (defun tramp-adb-handle-make-process (&rest args)
   "Like `make-process' for Tramp files."
   (when args
@@ -969,17 +966,29 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
          (signal 'wrong-type-argument (list #'functionp sentinel)))
        (unless (or (null stderr) (bufferp stderr) (stringp stderr))
          (signal 'wrong-type-argument (list #'stringp stderr)))
+       (when (and (stringp stderr) (tramp-tramp-file-p stderr)
+                  (not (tramp-equal-remote default-directory stderr)))
+         (signal 'file-error (list "Wrong stderr" stderr)))
 
        (let* ((buffer
                (if buffer
                    (get-buffer-create buffer)
                  ;; BUFFER can be nil.  We use a temporary buffer.
                  (generate-new-buffer tramp-temp-buffer-name)))
+              ;; STDERR can also be a file name.
+              (tmpstderr
+               (and stderr
+                    (if (and (stringp stderr) (tramp-tramp-file-p stderr))
+                        (tramp-unquote-file-local-name stderr)
+                      (tramp-make-tramp-temp-file v))))
+              (remote-tmpstderr
+               (and tmpstderr (tramp-make-tramp-file-name v tmpstderr)))
               (program (car command))
               (args (cdr command))
               (command
-               (format "cd %s && exec %s"
+               (format "cd %s && exec %s %s"
                        (tramp-shell-quote-argument localname)
+                       (if tmpstderr (format "2>'%s'" tmpstderr) "")
                        (mapconcat #'tramp-shell-quote-argument
                                   (cons program args) " ")))
               (tramp-process-connection-type
@@ -1029,6 +1038,18 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
                        (ignore-errors
                          (set-process-query-on-exit-flag p (null noquery))
                          (set-marker (process-mark p) (point)))
+                       ;; We must flush them here already; otherwise
+                       ;; `rename-file', `delete-file' or
+                       ;; `insert-file-contents' will fail.
+                       (tramp-flush-connection-property v "process-name")
+                       (tramp-flush-connection-property v "process-buffer")
+                       ;; Copy tmpstderr file.
+                       (when (and (stringp stderr)
+                                  (not (tramp-tramp-file-p stderr)))
+                         (add-function
+                          :after (process-sentinel p)
+                          (lambda (_proc _msg)
+                            (rename-file remote-tmpstderr stderr))))
                        ;; Read initial output.  Remove the first line,
                        ;; which is the command echo.
                        (while
@@ -1037,6 +1058,23 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
                              (not (re-search-forward "[\n]" nil t)))
                          (tramp-accept-process-output p 0))
                        (delete-region (point-min) (point))
+                       ;; Provide error buffer.  This shows only
+                       ;; initial error messages; messages arriving
+                       ;; later on will be inserted when the process
+                       ;; is deleted.  The temporary file will exist
+                       ;; until the process is deleted.
+                       (when (bufferp stderr)
+                         (with-current-buffer stderr
+                           (insert-file-contents-literally
+                            remote-tmpstderr 'visit))
+                         ;; Delete tmpstderr file.
+                         (add-function
+                          :after (process-sentinel p)
+                          (lambda (_proc _msg)
+                            (with-current-buffer stderr
+                              (insert-file-contents-literally
+                               remote-tmpstderr 'visit nil nil 'replace))
+                            (delete-file remote-tmpstderr))))
                        ;; Return process.
                        p))))
 
@@ -1062,7 +1100,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
          (read (current-buffer)))
        ":" 'omit)))
    ;; The equivalent to `exec-directory'.
-   `(,(tramp-compat-file-local-name default-directory))))
+   `(,(tramp-file-local-name (expand-file-name default-directory)))))
 
 (defun tramp-adb-get-device (vec)
   "Return full host name from VEC to be used in shell execution.
diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el
index b9bf618..95cbfb8 100644
--- a/lisp/net/tramp-archive.el
+++ b/lisp/net/tramp-archive.el
@@ -350,7 +350,7 @@ arguments to pass to the OPERATION."
     (add-to-list 'file-name-handler-alist
                 (cons (tramp-archive-autoload-file-name-regexp)
                       #'tramp-archive-autoload-file-name-handler))
-    (put 'tramp-archive-autoload-file-name-handler 'safe-magic t))))
+    (put #'tramp-archive-autoload-file-name-handler 'safe-magic t))))
 
 ;;;###autoload
 (progn
@@ -366,7 +366,7 @@ arguments to pass to the OPERATION."
 (tramp-register-archive-file-name-handler)
 
 ;; Mark `operations' the handler is responsible for.
-(put 'tramp-archive-file-name-handler 'operations
+(put #'tramp-archive-file-name-handler 'operations
      (mapcar #'car tramp-archive-file-name-handler-alist))
 
 ;; `tramp-archive-file-name-handler' must be placed before `url-file-handler'.
@@ -517,13 +517,16 @@ offered."
   (declare (debug (form symbolp body))
            (indent 2))
   (let ((bindings
-         (mapcar (lambda (elem)
-                   `(,(if var (intern (format "%s-%s" var elem)) elem)
-                     (,(intern (format "tramp-file-name-%s" elem))
-                      ,(or var 'v))))
-                `,(cons
-                   'archive
-                   (delete 'hop (tramp-compat-tramp-file-name-slots))))))
+         (mapcar
+         (lambda (elem)
+            `(,(if var (intern (format "%s-%s" var elem)) elem)
+              (,(intern (format "tramp-file-name-%s" elem))
+               ,(or var 'v))))
+         (cons
+          'archive
+          (delete
+           'hop
+           (cdr (mapcar #'car (cl-struct-slot-info 'tramp-file-name))))))))
     `(let* ((,(or var 'v) (tramp-archive-dissect-file-name ,filename))
             ,@bindings)
        ;; We don't know which of those vars will be used, so we bind them all,
diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el
index d4f6aa0..92c9848 100644
--- a/lisp/net/tramp-cache.el
+++ b/lisp/net/tramp-cache.el
@@ -130,13 +130,8 @@ Returns DEFAULT if not set."
             (or (null remote-file-name-inhibit-cache)
                 (and (integerp remote-file-name-inhibit-cache)
                      (time-less-p
-                      ;; `current-time' can be nil once we get rid of Emacs 24.
-                      (current-time)
-                      (time-add
-                       (car value)
-                      ;; `seconds-to-time' can be removed once we get
-                      ;; rid of Emacs 24.
-                       (seconds-to-time remote-file-name-inhibit-cache))))
+                      nil
+                      (time-add (car value) remote-file-name-inhibit-cache)))
                 (and (consp remote-file-name-inhibit-cache)
                      (time-less-p
                       remote-file-name-inhibit-cache (car value)))))
@@ -146,7 +141,7 @@ Returns DEFAULT if not set."
     (tramp-message key 8 "%s %s %s" file property value)
     (when (>= tramp-verbose 10)
       (let* ((var (intern (concat "tramp-cache-get-count-" property)))
-            (val (or (bound-and-true-p var)
+            (val (or (numberp (bound-and-true-p var))
                      (progn
                        (add-hook 'tramp-cache-unload-hook
                                  (lambda () (makunbound var)))
@@ -170,7 +165,7 @@ Returns VALUE."
     (tramp-message key 8 "%s %s %s" file property value)
     (when (>= tramp-verbose 10)
       (let* ((var (intern (concat "tramp-cache-set-count-" property)))
-            (val (or (bound-and-true-p var)
+            (val (or (numberp (bound-and-true-p var))
                      (progn
                        (add-hook 'tramp-cache-unload-hook
                                  (lambda () (makunbound var)))
@@ -386,20 +381,15 @@ used to cache connection properties of the local machine."
       (maphash
        (lambda (key value)
         ;; Remove text properties from KEY and VALUE.
-        ;; `cl-struct-slot-*' functions exist since Emacs 25 only; we
-        ;; ignore errors.
         (when (tramp-file-name-p key)
-          ;; (dolist
-          ;;     (slot
-          ;;   (mapcar #'car (cdr (cl-struct-slot-info 'tramp-file-name))))
-          ;;   (when (stringp (cl-struct-slot-value 'tramp-file-name slot key))
-          ;;     (setf (cl-struct-slot-value 'tramp-file-name slot key)
-          ;;        (substring-no-properties
-          ;;         (cl-struct-slot-value 'tramp-file-name slot key))))))
-          (dotimes (i (length key))
-            (when (stringp (elt key i))
-              (setf (elt key i) (substring-no-properties (elt key i))))))
-        (when (stringp key)
+           (dolist
+               (slot
+                (mapcar #'car (cdr (cl-struct-slot-info 'tramp-file-name))))
+             (when (stringp (cl-struct-slot-value 'tramp-file-name slot key))
+               (setf (cl-struct-slot-value 'tramp-file-name slot key)
+                     (substring-no-properties
+                      (cl-struct-slot-value 'tramp-file-name slot key))))))
+         (when (stringp key)
           (setq key (substring-no-properties key)))
         (when (stringp value)
           (setq value (substring-no-properties value)))
@@ -474,7 +464,7 @@ used to cache connection properties of the local machine."
                  tramp-persistency-file-name))
             (error "\n"))
           ";; Tramp connection history.  Don't change this file.\n"
-          ";; You can delete it, forcing Tramp to reapply the checks.\n\n"
+          ";; Run `M-x tramp-cleanup-all-connections' instead.\n\n"
           (with-output-to-string
             (pp (read (format "(%s)" (tramp-cache-print cache)))))))))))
 
@@ -514,7 +504,7 @@ for all methods.  Resulting data are derived from 
connection history."
           tramp-cache-read-persistent-data)
   (condition-case err
       (with-temp-buffer
-       (insert-file-contents tramp-persistency-file-name)
+       (insert-file-contents-literally tramp-persistency-file-name)
        (let ((list (read (current-buffer)))
              (tramp-verbose 0)
              element key item)
diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el
index 9d1025b..b4dca23 100644
--- a/lisp/net/tramp-cmds.el
+++ b/lisp/net/tramp-cmds.el
@@ -358,7 +358,7 @@ The remote connection identified by SOURCE is flushed by
 
   ;; Append local file name if none is specified.
   (when (string-equal (file-remote-p target) target)
-    (setq target (concat target (file-remote-p source 'localname))))
+    (setq target (concat target (tramp-file-local-name source))))
   ;; Make them directory names.
   (setq source (directory-file-name source)
        target (directory-file-name target))
diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el
index 723b8cf..87bcd08 100644
--- a/lisp/net/tramp-compat.el
+++ b/lisp/net/tramp-compat.el
@@ -23,15 +23,15 @@
 
 ;;; Commentary:
 
-;; Tramp's main Emacs version for development is Emacs 27.  This
-;; package provides compatibility functions for Emacs 24, Emacs 25 and
-;; Emacs 26.
+;; Tramp's main Emacs version for development is Emacs 28.  This
+;; package provides compatibility functions for Emacs 25, Emacs 26 and
+;; Emacs 27.
 
 ;;; Code:
 
-;; In Emacs 24 and 25, `tramp-unload-file-name-handlers' is not
-;; autoloaded.  So we declare it here in order to avoid recursive
-;; load.  This will be overwritten in tramp.el.
+;; In Emacs 25, `tramp-unload-file-name-handlers' is not autoloaded.
+;; So we declare it here in order to avoid recursive load.  This will
+;; be overwritten in tramp.el.
 (defun tramp-unload-file-name-handlers () ".")
 
 (require 'auth-source)
@@ -41,6 +41,7 @@
 (require 'shell)
 (require 'subr-x)
 
+;; `temporary-file-directory' as function is introduced with Emacs 26.1.
 (declare-function tramp-handle-temporary-file-directory "tramp")
 
 ;; For not existing functions, obsolete functions, or functions with a
@@ -51,6 +52,8 @@
   `(when (functionp ,function)
      (with-no-warnings (funcall ,function ,@arguments))))
 
+(put #'tramp-compat-funcall 'tramp-suppress-trace t)
+
 (defsubst tramp-compat-temporary-file-directory ()
   "Return name of directory for temporary files.
 It is the default value of `temporary-file-directory'."
@@ -74,31 +77,7 @@ Add the extension of F, if existing."
       #'temporary-file-directory
     #'tramp-handle-temporary-file-directory))
 
-(defun tramp-compat-process-running-p (process-name)
-  "Return t if system process PROCESS-NAME is running for `user-login-name'."
-  (when (stringp process-name)
-    (cond
-     ;; GNU Emacs 22 on w32.
-     ((fboundp 'w32-window-exists-p)
-      (tramp-compat-funcall 'w32-window-exists-p process-name process-name))
-
-     ;; GNU Emacs 23+.
-     ((and (fboundp 'list-system-processes) (fboundp 'process-attributes))
-      (let (result)
-       (dolist (pid (tramp-compat-funcall 'list-system-processes) result)
-         (let ((attributes (process-attributes pid)))
-           (when (and (string-equal
-                        (cdr (assoc 'user attributes)) (user-login-name))
-                       (let ((comm (cdr (assoc 'comm attributes))))
-                         ;; The returned command name could be truncated
-                         ;; to 15 characters.  Therefore, we cannot check
-                         ;; for `string-equal'.
-                         (and comm (string-match-p
-                                    (concat "^" (regexp-quote comm))
-                                    process-name))))
-             (setq result t)))))))))
-
-;; `file-attribute-*' are introduced in Emacs 25.1.
+;; `file-attribute-*' are introduced in Emacs 26.1.
 
 (defalias 'tramp-compat-file-attribute-type
   (if (fboundp 'file-attribute-type)
@@ -180,24 +159,6 @@ and later, and is a float in Emacs 26 and earlier."
 This is a string of ten letters or dashes as in ls -l."
       (nth 8 attributes))))
 
-;; `format-message' is new in Emacs 25.1.
-(unless (fboundp 'format-message)
-  (defalias 'format-message #'format))
-
-;; `directory-name-p' is new in Emacs 25.1.
-(defalias 'tramp-compat-directory-name-p
-  (if (fboundp 'directory-name-p)
-      #'directory-name-p
-    (lambda (name)
-      "Return non-nil if NAME ends with a directory separator character."
-      (let ((len (length name))
-            (lastc ?.))
-       (if (> len 0)
-            (setq lastc (aref name (1- len))))
-       (or (= lastc ?/)
-            (and (memq system-type '(windows-nt ms-dos))
-                (= lastc ?\\)))))))
-
 ;; `file-missing' is introduced in Emacs 26.1.
 (defconst tramp-file-missing
   (if (get 'file-missing 'error-conditions) 'file-missing 'file-error)
@@ -265,13 +226,6 @@ NAME is unquoted."
        ((eq tramp-syntax 'sep) 'separate)
        (t tramp-syntax)))
 
-;; `cl-struct-slot-info' has been introduced with Emacs 25.
-(defmacro tramp-compat-tramp-file-name-slots ()
-  "Return a list of slot names."
-  (if (fboundp 'cl-struct-slot-info)
-      '(cdr (mapcar #'car (cl-struct-slot-info 'tramp-file-name)))
-    '(cdr (mapcar #'car (get 'tramp-file-name 'cl-struct-slots)))))
-
 ;; The signature of `tramp-make-tramp-file-name' has been changed.
 ;; Therefore, we cannot use `url-tramp-convert-url-to-tramp' prior
 ;; Emacs 26.1.  We use `temporary-file-directory' as indicator.
@@ -284,10 +238,9 @@ NAME is unquoted."
       #'exec-path
     (lambda ()
       "List of directories to search programs to run in remote subprocesses."
-      (let ((handler (find-file-name-handler default-directory 'exec-path)))
-       (if handler
-           (funcall handler 'exec-path)
-         exec-path)))))
+      (if-let ((handler (find-file-name-handler default-directory 'exec-path)))
+         (funcall handler 'exec-path)
+       exec-path))))
 
 ;; `time-equal-p' has appeared in Emacs 27.1.
 (defalias 'tramp-compat-time-equal-p
@@ -327,11 +280,11 @@ A nil value for either argument stands for the current 
time."
            (unload-feature 'tramp-loaddefs 'force)
            (unload-feature 'tramp-compat 'force)))
 
+(provide 'tramp-compat)
+
 ;;; TODO:
 ;;
-;; * Starting with Emacs 25.1, replace `tramp-message-show-message' by
-;;   the reverse of `inhibit-message'.
-
-(provide 'tramp-compat)
+;; * Starting with Emacs 27.1, there's no need to escape open
+;;   parentheses with a backslash in docstrings anymore.
 
 ;;; tramp-compat.el ends here
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 34a234c..2c117fe 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -49,11 +49,15 @@
 
 ;; The user option `tramp-gvfs-methods' contains the list of supported
 ;; connection methods.  Per default, these are "afp", "dav", "davs",
-;; "gdrive", "nextcloud" and "sftp".
+;; "gdrive", "media", "nextcloud" and "sftp".
 
 ;; "gdrive" and "nextcloud" connection methods require a respective
 ;; account in GNOME Online Accounts, with enabled "Files" service.
 
+;; The "media" connection method is responsible for media devices,
+;; like cell phones, tablets, cameras etc.  The device must already be
+;; connected via USB, before accessing it.
+
 ;; Other possible connection methods are "ftp", "http", "https" and
 ;; "smb".  When one of these methods is added to the list, the remote
 ;; access for that method is performed via GVFS instead of the native
@@ -121,16 +125,16 @@
         (autoload 'zeroconf-init "zeroconf")
         (tramp-compat-funcall 'dbus-get-unique-name :system)
         (tramp-compat-funcall 'dbus-get-unique-name :session)
-        (or (tramp-compat-process-running-p "gvfs-fuse-daemon")
-            (tramp-compat-process-running-p "gvfsd-fuse"))))
+        (or (tramp-process-running-p "gvfs-fuse-daemon")
+            (tramp-process-running-p "gvfsd-fuse"))))
   "Non-nil when GVFS is available.")
 
 ;;;###tramp-autoload
 (defcustom tramp-gvfs-methods
-  '("afp" "dav" "davs" "gdrive" "nextcloud" "sftp")
+  '("afp" "dav" "davs" "gdrive" "media" "nextcloud" "sftp")
   "List of methods for remote files, accessed with GVFS."
   :group 'tramp
-  :version "27.1"
+  :version "28.1"
   :type '(repeat (choice (const "afp")
                         (const "dav")
                         (const "davs")
@@ -138,10 +142,12 @@
                         (const "gdrive")
                         (const "http")
                         (const "https")
+                        (const "media")
                         (const "nextcloud")
                         (const "sftp")
                         (const "smb"))))
 
+;;;###tramp-autoload
 (defconst tramp-goa-methods '("gdrive" "nextcloud")
   "List of methods which require registration at GNOME Online Accounts.")
 
@@ -151,15 +157,23 @@
   (dolist (method tramp-goa-methods)
     (setq tramp-gvfs-methods (delete method tramp-gvfs-methods))))
 
-;; Add defaults for `tramp-default-user-alist' and `tramp-default-host-alist'.
 ;;;###tramp-autoload
-(tramp--with-startup
- (when (string-match "\\(.+\\)@\\(\\(?:gmail\\|googlemail\\)\\.com\\)"
-                    user-mail-address)
-   (add-to-list 'tramp-default-user-alist
-               `("\\`gdrive\\'" nil ,(match-string 1 user-mail-address)))
-   (add-to-list 'tramp-default-host-alist
-               '("\\`gdrive\\'" nil ,(match-string 2 user-mail-address)))))
+(defvar tramp-media-methods '("afc" "gphoto2" "mtp")
+  "List of GVFS methods which are covered by the \"media\" method.
+They are checked during start up via
+`tramp-gvfs-interface-remotevolumemonitor'.")
+
+(defsubst tramp-gvfs-service-volumemonitor (method)
+  "Return the well known name of the volume monitor responsible for METHOD."
+  (symbol-value
+   (intern-soft (format "tramp-gvfs-service-%s-volumemonitor" method))))
+
+;; Remove media methods if not supported.
+(when tramp-gvfs-enabled
+  (dolist (method tramp-media-methods)
+    (unless (member (tramp-gvfs-service-volumemonitor method)
+                   (dbus-list-known-names :session))
+      (setq tramp-media-methods (delete method tramp-media-methods)))))
 
 ;;;###tramp-autoload
 (defcustom tramp-gvfs-zeroconf-domain "local"
@@ -169,13 +183,15 @@
   :type 'string)
 
 ;; Add the methods to `tramp-methods', in order to allow minibuffer
-;; completion.
+;; completion.  Add defaults for `tramp-default-host-alist'.
 ;;;###tramp-autoload
 (when (featurep 'dbusbind)
   (tramp--with-startup
-   (dolist (elt tramp-gvfs-methods)
-     (unless (assoc elt tramp-methods)
-       (add-to-list 'tramp-methods (cons elt nil))))))
+   (dolist (method tramp-gvfs-methods)
+     (unless (assoc method tramp-methods)
+       (add-to-list 'tramp-methods `(,method)))
+     (when (member method tramp-goa-methods)
+       (add-to-list 'tramp-default-host-alist `(,method nil ""))))))
 
 (defconst tramp-gvfs-path-tramp (concat dbus-path-emacs "/Tramp")
   "The preceding object path for own objects.")
@@ -457,8 +473,209 @@ It has been changed in GVFS 1.14.")
 ;; </interface>
 
 ;; The basic structure for GNOME Online Accounts.  We use a list :type,
-;; in order to be compatible with Emacs 24 and 25.
-(cl-defstruct (tramp-goa-name (:type list) :named) method user host port)
+;; in order to be compatible with Emacs 25.
+(cl-defstruct (tramp-goa-account (:type list) :named) method user host port)
+
+;;;###tramp-autoload
+(defconst tramp-gvfs-service-afc-volumemonitor "org.gtk.vfs.AfcVolumeMonitor"
+  "The well known name of the AFC volume monitor.")
+
+;; This one is not needed yet.
+(defconst tramp-gvfs-service-goa-volumemonitor "org.gtk.vfs.GoaVolumeMonitor"
+  "The well known name of the GOA volume monitor.")
+
+;;;###tramp-autoload
+(defconst tramp-gvfs-service-gphoto2-volumemonitor
+  "org.gtk.vfs.GPhoto2VolumeMonitor"
+  "The well known name of the GPhoto2 volume monitor.")
+
+;;;###tramp-autoload
+(defconst tramp-gvfs-service-mtp-volumemonitor "org.gtk.vfs.MTPVolumeMonitor"
+  "The well known name of the MTP volume monitor.")
+
+(defconst tramp-gvfs-path-remotevolumemonitor
+  "/org/gtk/Private/RemoteVolumeMonitor"
+  "The object path of the remote volume monitor.")
+
+(defconst tramp-gvfs-interface-remotevolumemonitor
+  "org.gtk.Private.RemoteVolumeMonitor"
+  "The volume monitor interface.")
+
+;; <interface name='org.gtk.Private.RemoteVolumeMonitor'>
+;;   <method name="IsSupported">
+;;     <arg type='b' name='is_supported' direction='out'/>
+;;   </method>
+;;   <method name="List">
+;;     <arg type='a(ssssbbbbbbbbuasa{ss}sa{sv})' name='drives' 
direction='out'/>
+;;     <arg type='a(ssssssbbssa{ss}sa{sv})' name='volumes' direction='out'/>
+;;     <arg type='a(ssssssbsassa{sv})' name='mounts' direction='out'/>
+;;   </method>
+;;   <method name="CancelOperation">
+;;     <arg type='s' name='cancellation_id' direction='in'/>
+;;     <arg type='b' name='was_cancelled' direction='out'/>
+;;   </method>
+;;   <method name="MountUnmount">
+;;     <arg type='s' name='id' direction='in'/>
+;;     <arg type='s' name='cancellation_id' direction='in'/>
+;;     <arg type='u' name='unmount_flags' direction='in'/>
+;;     <arg type='s' name='mount_op_id' direction='in'/>
+;;   </method>
+;;   <method name="VolumeMount">
+;;     <arg type='s' name='id' direction='in'/>
+;;     <arg type='s' name='cancellation_id' direction='in'/>
+;;     <arg type='u' name='mount_flags' direction='in'/>
+;;     <arg type='s' name='mount_op_id' direction='in'/>
+;;   </method>
+;;   <method name="DriveEject">
+;;     <arg type='s' name='id' direction='in'/>
+;;     <arg type='s' name='cancellation_id' direction='in'/>
+;;     <arg type='u' name='unmount_flags' direction='in'/>
+;;     <arg type='s' name='mount_op_id' direction='in'/>
+;;   </method>
+;;   <method name="DrivePollForMedia">
+;;     <arg type='s' name='id' direction='in'/>
+;;     <arg type='s' name='cancellation_id' direction='in'/>
+;;   </method>
+;;   <method name="DriveStart">
+;;     <arg type='s' name='id' direction='in'/>
+;;     <arg type='s' name='cancellation_id' direction='in'/>
+;;     <arg type='u' name='flags' direction='in'/>
+;;     <arg type='s' name='mount_op_id' direction='in'/>
+;;   </method>
+;;   <method name="DriveStop">
+;;     <arg type='s' name='id' direction='in'/>
+;;     <arg type='s' name='cancellation_id' direction='in'/>
+;;     <arg type='u' name='unmount_flags' direction='in'/>
+;;     <arg type='s' name='mount_op_id' direction='in'/>
+;;   </method>
+;;   <method name="MountOpReply">
+;;     <arg type='s' name='mount_op_id' direction='in'/>
+;;     <arg type='i' name='result' direction='in'/>
+;;     <arg type='s' name='user_name' direction='in'/>
+;;     <arg type='s' name='domain' direction='in'/>
+;;     <arg type='s' name='encoded_password' direction='in'/>
+;;     <arg type='i' name='password_save' direction='in'/>
+;;     <arg type='i' name='choice' direction='in'/>
+;;     <arg type='b' name='anonymous' direction='in'/>
+;;   </method>
+;;   <signal name="DriveChanged">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='(ssssbbbbbbbbuasa{ss}sa{sv})' name='drive'/>
+;;   </signal>
+;;   <signal name="DriveConnected">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='(ssssbbbbbbbbuasa{ss}sa{sv})' name='drive'/>
+;;   </signal>
+;;   <signal name="DriveDisconnected">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='(ssssbbbbbbbbuasa{ss}sa{sv})' name='drive'/>
+;;   </signal>
+;;   <signal name="DriveEjectButton">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='(ssssbbbbbbbbuasa{ss}sa{sv})' name='drive'/>
+;;   </signal>
+;;   <signal name="DriveStopButton">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='(ssssbbbbbbbbuasa{ss}sa{sv})' name='drive'/>
+;;   </signal>
+;;   <signal name="VolumeChanged">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='(ssssssbbssa{ss}sa{sv})' name='volume'/>
+;;   </signal>
+;;   <signal name="VolumeAdded">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='(ssssssbbssa{ss}sa{sv})' name='volume'/>
+;;   </signal>
+;;   <signal name="VolumeRemoved">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='(ssssssbbssa{ss}sa{sv})' name='volume'/>
+;;   </signal>
+;;   <signal name="MountChanged">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='(ssssssbsassa{sv})' name='mount'/>
+;;   </signal>
+;;   <signal name="MountAdded">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='(ssssssbsassa{sv})' name='mount'/>
+;;   </signal>
+;;   <signal name="MountPreUnmount">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='(ssssssbsassa{sv})' name='mount'/>
+;;   </signal>
+;;   <signal name="MountRemoved">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='(ssssssbsassa{sv})' name='mount'/>
+;;   </signal>
+;;   <signal name="MountOpAskPassword">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='s' name='message_to_show'/>
+;;     <arg type='s' name='default_user'/>
+;;     <arg type='s' name='default_domain'/>
+;;     <arg type='u' name='flags'/>
+;;   </signal>
+;;   <signal name="MountOpAskQuestion">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='s' name='message_to_show'/>
+;;     <arg type='as' name='choices'/>
+;;   </signal>
+;;   <signal name="MountOpShowProcesses">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='s' name='message_to_show'/>
+;;     <arg type='ai' name='pid'/>
+;;     <arg type='as' name='choices'/>
+;;   </signal>
+;;   <signal name="MountOpShowUnmountProgress">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;     <arg type='s' name='message_to_show'/>
+;;     <arg type='x' name='time_left'/>
+;;     <arg type='x' name='bytes_left'/>
+;;   </signal>
+;;   <signal name="MountOpAborted">
+;;     <arg type='s' name='dbus_name'/>
+;;     <arg type='s' name='id'/>
+;;   </signal>
+;; </interface>
+
+;; STRUCT              volume
+;;   STRING              id
+;;   STRING              name
+;;   STRING              gicon_data
+;;   STRING              symbolic_gicon_data
+;;   STRING              uuid
+;;   STRING              activation_uri
+;;   BOOLEAN             can-mount
+;;   BOOLEAN             should-automount
+;;   STRING              drive-id
+;;   STRING              mount-id
+;;   ARRAY               identifiers
+;;     DICT
+;;       STRING                    key (unix-device, class, uuid, ...)
+;;       STRING                    value
+;;   STRING              sort_key
+;;   ARRAY               expansion
+;;     DICT
+;;       STRING                    key (always-call-mount, is-removable, ...)
+;;       VARIANT           value (boolean?)
+
+;; The basic structure for media devices.  We use a list :type, in
+;; order to be compatible with Emacs 25.
+(cl-defstruct (tramp-media-device (:type list) :named) method host port)
 
 ;; "gvfs-<command>" utilities have been deprecated in GVFS 1.31.1.  We
 ;; must use "gio <command>" tool instead.
@@ -470,6 +687,7 @@ It has been changed in GVFS 1.14.")
     ("gvfs-monitor-file" . "monitor")
     ("gvfs-mount" . "mount")
     ("gvfs-move" . "move")
+    ("gvfs-rename" . "rename")
     ("gvfs-rm" . "remove")
     ("gvfs-set-attribute" . "set")
     ("gvfs-trash" . "trash"))
@@ -625,10 +843,9 @@ First arg specifies the OPERATION, second arg is a list of 
arguments to
 pass to the OPERATION."
   (unless tramp-gvfs-enabled
     (tramp-user-error nil "Package `tramp-gvfs' not supported"))
-  (let ((fn (assoc operation tramp-gvfs-file-name-handler-alist)))
-    (if fn
-       (save-match-data (apply (cdr fn) args))
-      (tramp-run-real-handler operation args))))
+  (if-let ((fn (assoc operation tramp-gvfs-file-name-handler-alist)))
+      (save-match-data (apply (cdr fn) args))
+    (tramp-run-real-handler operation args)))
 
 ;;;###tramp-autoload
 (when (featurep 'dbusbind)
@@ -649,13 +866,12 @@ pass to the OPERATION."
   "Like `dbus-byte-array-to-string' but remove trailing \\0 if exists.
 Return nil for null BYTE-ARRAY."
   ;; The byte array could be a variant.  Take care.
-  (let ((byte-array
-        (if (and (consp byte-array) (atom (car byte-array)))
-            byte-array (car byte-array))))
-    (and byte-array
-        (dbus-byte-array-to-string
-         (if (and (consp byte-array) (zerop (car (last byte-array))))
-             (butlast byte-array) byte-array)))))
+  (when-let ((byte-array
+             (if (and (consp byte-array) (atom (car byte-array)))
+                 byte-array (car byte-array))))
+    (dbus-byte-array-to-string
+     (if (and (consp byte-array) (zerop (car (last byte-array))))
+        (butlast byte-array) byte-array))))
 
 (defun tramp-gvfs-stringify-dbus-message (message)
   "Convert a D-Bus MESSAGE into readable UTF8 strings, used for traces."
@@ -680,6 +896,8 @@ The call will be traced by Tramp with trace level 6."
     (tramp-message vec 6 "%s" result(tramp-gvfs-stringify-dbus-message result))
     result))
 
+(put #'tramp-dbus-function 'tramp-suppress-trace t)
+
 (defmacro with-tramp-dbus-call-method
   (vec synchronous bus service path interface method &rest args)
   "Apply a D-Bus call on bus BUS.
@@ -689,14 +907,13 @@ it is an asynchronous call, with `ignore' as callback 
function.
 
 The other arguments have the same meaning as with `dbus-call-method'
 or `dbus-call-method-asynchronously'."
+  (declare (indent 2) (debug t))
   `(let ((func (if ,synchronous
                   #'dbus-call-method #'dbus-call-method-asynchronously))
         (args (append (list ,bus ,service ,path ,interface ,method)
                       (if ,synchronous (list ,@args) (list 'ignore ,@args)))))
      (tramp-dbus-function ,vec func args)))
 
-(put 'with-tramp-dbus-call-method 'lisp-indent-function 2)
-(put 'with-tramp-dbus-call-method 'edebug-form-spec '(form symbolp body))
 (font-lock-add-keywords 'emacs-lisp-mode 
'("\\<with-tramp-dbus-call-method\\>"))
 
 (defmacro with-tramp-dbus-get-all-properties
@@ -704,6 +921,7 @@ or `dbus-call-method-asynchronously'."
   "Return all properties of INTERFACE.
 The call will be traced by Tramp with trace level 6."
      ;; Check, that interface exists at object path.  Retrieve properties.
+  (declare (indent 1) (debug t))
   `(when (member
          ,interface
          (tramp-dbus-function
@@ -712,8 +930,6 @@ The call will be traced by Tramp with trace level 6."
      (tramp-dbus-function
       ,vec #'dbus-get-all-properties (list ,bus ,service ,path ,interface))))
 
-(put 'with-tramp-dbus-get-all-properties 'lisp-indent-function 1)
-(put 'with-tramp-dbus-get-all-properties 'edebug-form-spec '(form symbolp 
body))
 (font-lock-add-keywords 'emacs-lisp-mode 
'("\\<with-tramp-dbus-get-all-properties\\>"))
 
 (defvar tramp-gvfs-dbus-event-vector nil
@@ -758,11 +974,15 @@ file names."
        (copy-directory filename newname keep-date t)
        (when (eq op 'rename) (delete-directory filename 'recursive)))
 
-    (let ((t1 (tramp-tramp-file-p filename))
-         (t2 (tramp-tramp-file-p newname))
-         (equal-remote (tramp-equal-remote filename newname))
-         (gvfs-operation (if (eq op 'copy) "gvfs-copy" "gvfs-move"))
-         (msg-operation (if (eq op 'copy) "Copying" "Renaming")))
+    (let* ((t1 (tramp-tramp-file-p filename))
+          (t2 (tramp-tramp-file-p newname))
+          (equal-remote (tramp-equal-remote filename newname))
+          (gvfs-operation
+           (cond
+            ((eq op 'copy) "gvfs-copy")
+            (equal-remote "gvfs-rename")
+            (t "gvfs-move")))
+          (msg-operation (if (eq op 'copy) "Copying" "Renaming")))
 
       (with-parsed-tramp-file-name (if t1 filename newname) nil
        (unless (file-exists-p filename)
@@ -772,7 +992,7 @@ file names."
        (when (and (not ok-if-already-exists) (file-exists-p newname))
          (tramp-error v 'file-already-exists newname))
        (when (and (file-directory-p newname)
-                  (not (tramp-compat-directory-name-p newname)))
+                  (not (directory-name-p newname)))
          (tramp-error v 'file-error "File is a directory %s" newname))
 
        (if (or (and equal-remote
@@ -833,8 +1053,8 @@ file names."
   (filename newname &optional ok-if-already-exists keep-date
    preserve-uid-gid preserve-extended-attributes)
   "Like `copy-file' for Tramp files."
-  (setq filename (expand-file-name filename))
-  (setq newname (expand-file-name newname))
+  (setq filename (expand-file-name filename)
+       newname (expand-file-name newname))
   ;; At least one file a Tramp file?
   (if (or (tramp-tramp-file-p filename)
          (tramp-tramp-file-p newname))
@@ -1330,8 +1550,8 @@ If FILE-SYSTEM is non-nil, return file system attributes."
   "Like `rename-file' for Tramp files."
   ;; Check if both files are local -- invoke normal rename-file.
   ;; Otherwise, use Tramp from local system.
-  (setq filename (expand-file-name filename))
-  (setq newname (expand-file-name newname))
+  (setq filename (expand-file-name filename)
+       newname (expand-file-name newname))
   ;; At least one file a Tramp file?
   (if (or (tramp-tramp-file-p filename)
           (tramp-tramp-file-p newname))
@@ -1383,36 +1603,51 @@ If FILE-SYSTEM is non-nil, return file system 
attributes."
 
 ;; File name conversions.
 
+(defun tramp-gvfs-activation-uri (filename)
+  "Return activation URI to be used in gio commands."
+  (if (tramp-tramp-file-p filename)
+      (with-parsed-tramp-file-name filename nil
+       ;; Ensure that media devices are cached.
+       (when (string-equal method "media")
+         (tramp-get-media-device v))
+       (with-tramp-connection-property v "activation-uri"
+         (setq localname "/")
+         (when (string-equal "gdrive" method)
+           (setq method "google-drive"))
+         (when (string-equal "nextcloud" method)
+           (setq method "davs"
+                 localname
+                 (concat (tramp-gvfs-get-remote-prefix v) localname)))
+         (when (string-equal "media" method)
+           (when-let
+               ((media (tramp-get-connection-property v "media-device" nil)))
+             (setq method (tramp-media-device-method media)
+                   host (tramp-media-device-host media)
+                   port (tramp-media-device-port media))))
+         (when (and user domain)
+           (setq user (concat domain ";" user)))
+         (url-recreate-url
+          (url-parse-make-urlobj
+           method (and user (url-hexify-string user))
+           nil (and host (url-hexify-string host))
+           (if (stringp port) (string-to-number port) port)
+           localname nil nil t))))
+    ;; Local URI.
+    (url-recreate-url
+     (url-parse-make-urlobj "file" nil nil nil nil nil nil nil t))))
+
 (defun tramp-gvfs-url-file-name (filename)
   "Return FILENAME in URL syntax."
-  ;; "/" must NOT be hexified.
   (setq filename (tramp-compat-file-name-unquote filename))
-  (let ((url-unreserved-chars (cons ?/ url-unreserved-chars))
-       result)
-    (setq
-     result
-     (url-recreate-url
-      (if (tramp-tramp-file-p filename)
-         (with-parsed-tramp-file-name filename nil
-           (when (string-equal "gdrive" method)
-             (setq method "google-drive"))
-           (when (string-equal "nextcloud" method)
-             (setq method "davs"
-                   localname
-                   (concat (tramp-gvfs-get-remote-prefix v) localname)))
-           (when (and user domain)
-             (setq user (concat domain ";" user)))
-           (url-parse-make-urlobj
-            method (and user (url-hexify-string user))
-            nil (and host (url-hexify-string host))
-            (if (stringp port) (string-to-number port) port)
-            (and localname (url-hexify-string localname)) nil nil t))
-       (url-parse-make-urlobj
-        "file" nil nil nil nil
-        (url-hexify-string (file-truename filename)) nil nil t))))
+  (let* (;; "/" must NOT be hexified.
+        (url-unreserved-chars (cons ?/ url-unreserved-chars))
+        (result
+         (concat (substring (tramp-gvfs-activation-uri filename) 0 -1)
+                 (url-hexify-string (tramp-file-local-name filename)))))
     (when (tramp-tramp-file-p filename)
-      (with-parsed-tramp-file-name filename nil
-       (tramp-message v 10 "remote file `%s' is URL `%s'" filename result)))
+      (tramp-message
+       (tramp-dissect-file-name filename) 10
+       "remote file `%s' is URL `%s'" filename result))
     result))
 
 (defun tramp-gvfs-object-path (filename)
@@ -1424,6 +1659,14 @@ If FILE-SYSTEM is non-nil, return file system 
attributes."
   (dbus-unescape-from-identifier
    (replace-regexp-in-string "^.*/\\([^/]+\\)$" "\\1" object-path)))
 
+(defun tramp-gvfs-url-host (url)
+  "Return the host name part of URL, a string.
+We cannot use `url-host', because `url-generic-parse-url' returns
+a downcased host name only."
+  (and (stringp url)
+       (string-match "^[[:alnum:]]+://\\([^/:]+\\)" url)
+       (match-string 1 url)))
+
 
 ;; D-Bus GVFS functions.
 
@@ -1564,11 +1807,22 @@ If FILE-SYSTEM is non-nil, return file system 
attributes."
        (when (string-equal "google-drive" method)
          (setq method "gdrive"))
        (when (and (string-equal "http" method) (stringp uri))
-         (setq uri (url-generic-parse-url uri)
+         (setq host (tramp-gvfs-url-host uri)
+               uri (url-generic-parse-url uri)
                method (url-type uri)
                user (url-user uri)
-               host (url-host uri)
                port (url-portspec uri)))
+       (when (member method tramp-media-methods)
+         ;; Ensure that media devices are cached.
+         (tramp-get-media-devices nil)
+         (let ((v (tramp-get-connection-property
+                   (make-tramp-media-device
+                    :method method :host host :port port)
+                   "vector" nil)))
+           (when v
+             (setq method (tramp-file-name-method v)
+                   host (tramp-file-name-host v)
+                   port (tramp-file-name-port v)))))
        (when (member method tramp-gvfs-methods)
          (with-parsed-tramp-file-name
              (tramp-make-tramp-file-name method user domain host port "") nil
@@ -1654,11 +1908,22 @@ If FILE-SYSTEM is non-nil, return file system 
attributes."
         (when (string-equal "google-drive" method)
           (setq method "gdrive"))
         (when (and (string-equal "http" method) (stringp uri))
-          (setq uri (url-generic-parse-url uri)
+          (setq host (tramp-gvfs-url-host uri)
+                uri (url-generic-parse-url uri)
                 method (url-type uri)
                 user (url-user uri)
-                host (url-host uri)
                 port (url-portspec uri)))
+        (when (member method tramp-media-methods)
+          ;; Ensure that media devices are cached.
+          (tramp-get-media-devices vec)
+          (let ((v (tramp-get-connection-property
+                    (make-tramp-media-device
+                     :method method :host host :port port)
+                    "vector" nil)))
+            (when v
+              (setq method (tramp-file-name-method v)
+                    host (tramp-file-name-host v)
+                    port (tramp-file-name-port v)))))
         (when (and
                (string-equal method (tramp-file-name-method vec))
                (string-equal user (tramp-file-name-user vec))
@@ -1696,11 +1961,16 @@ It was \"a(say)\", but has changed to \"a{sv})\"."
 
 (defun tramp-gvfs-mount-spec (vec)
   "Return a mount-spec for \"org.gtk.vfs.MountTracker.mountLocation\"."
-  (let* ((method (tramp-file-name-method vec))
+  (let* ((media (tramp-get-media-device vec))
+        (method (if media
+                    (tramp-media-device-method media)
+                  (tramp-file-name-method vec)))
         (user (tramp-file-name-user vec))
         (domain (tramp-file-name-domain vec))
-        (host (tramp-file-name-host vec))
-        (port (tramp-file-name-port vec))
+        (host (if media
+                  (tramp-media-device-host media) (tramp-file-name-host vec)))
+        (port (if media
+                  (tramp-media-device-port media) (tramp-file-name-port vec)))
         (localname (tramp-file-name-unquote-localname vec))
         (share (when (string-match "^/?\\([^/]+\\)" localname)
                  (match-string 1 localname)))
@@ -1751,6 +2021,38 @@ It was \"a(say)\", but has changed to \"a{sv})\"."
     ;; Return.
     `(:struct ,(tramp-gvfs-dbus-string-to-byte-array mount-pref) ,mount-spec)))
 
+(defun tramp-gvfs-handler-volumeadded-volumeremoved (_dbus-name _id volume)
+  "Signal handler for the \"org.gtk.Private.RemoteVolumeMonitor.VolumeAdded\" \
+and \"org.gtk.Private.RemoteVolumeMonitor.VolumeRemoved\" signals."
+  (ignore-errors
+    (let* ((signal-name (dbus-event-member-name last-input-event))
+          (uri (url-generic-parse-url (nth 5 volume)))
+          (method (url-type uri))
+          (vec (make-tramp-file-name
+                :method "media"
+                ;; A host name cannot contain spaces.
+                :host (replace-regexp-in-string " " "_" (nth 1 volume))))
+          (media (make-tramp-media-device
+                  :method method
+                  :host (tramp-gvfs-url-host (nth 5 volume))
+                  :port (and (url-portspec uri)))))
+      (when (member method tramp-media-methods)
+       (tramp-message
+        vec 6 "%s %s" signal-name (tramp-gvfs-stringify-dbus-message volume))
+       (tramp-flush-connection-properties vec)
+       (tramp-flush-connection-properties media)
+       (tramp-get-media-devices nil)))))
+
+(when tramp-gvfs-enabled
+  (dbus-register-signal
+   :session nil tramp-gvfs-path-remotevolumemonitor
+   tramp-gvfs-interface-remotevolumemonitor "VolumeAdded"
+   #'tramp-gvfs-handler-volumeadded-volumeremoved)
+  (dbus-register-signal
+   :session nil tramp-gvfs-path-remotevolumemonitor
+   tramp-gvfs-interface-remotevolumemonitor "VolumeRemoved"
+   #'tramp-gvfs-handler-volumeadded-volumeremoved))
+
 
 ;; Connection functions.
 
@@ -1794,7 +2096,7 @@ This is relevant for GNOME Online Accounts."
     ;; Ensure that GNOME Online Accounts are cached.
     (when (member (tramp-file-name-method vec) tramp-goa-methods)
       (tramp-get-goa-accounts vec))
-    (tramp-get-connection-property (tramp-make-goa-name vec) "prefix" "/")))
+    (tramp-get-connection-property (tramp-get-goa-account vec) "prefix" "/")))
 
 (defun tramp-gvfs-maybe-open-connection (vec)
   "Maybe open a connection VEC.
@@ -1843,7 +2145,7 @@ connection if a previous connection has died for some 
reason."
        ;; Ensure that GNOME Online Accounts are cached.
        (tramp-get-goa-accounts vec)
        (when (tramp-get-connection-property
-              (tramp-make-goa-name vec) "FilesDisabled" t)
+              (tramp-get-goa-account vec) "FilesDisabled" t)
          (tramp-user-error
           vec "There is no Online Account `%s'"
           (tramp-make-tramp-file-name vec 'noloc))))
@@ -1968,12 +2270,12 @@ is applied, and it returns t if the return code is 
zero."
          (and (tramp-flush-file-properties vec "/") nil)))))
 
 
-;; D-Bus GNOME Online Accounts functions.
+;; GNOME Online Accounts functions.
 
-(defun tramp-make-goa-name (vec)
-  "Transform VEC into a `tramp-goa-name' structure."
+(defun tramp-get-goa-account (vec)
+  "Transform VEC into a `tramp-goa-account' structure."
   (when (tramp-file-name-p vec)
-    (make-tramp-goa-name
+    (make-tramp-goa-account
      :method (tramp-file-name-method vec)
      :user (tramp-file-name-user vec)
      :host (tramp-file-name-host vec)
@@ -1981,12 +2283,12 @@ is applied, and it returns t if the return code is 
zero."
 
 (defun tramp-get-goa-accounts (vec)
   "Retrieve GNOME Online Accounts, and cache them.
-The hash key is a `tramp-goa-name' structure.  The value is an
+The hash key is a `tramp-goa-account' structure.  The value is an
 alist of the properties of `tramp-goa-interface-account' and
-`tramp-goa-interface-files' of the corresponding GNOME online
-account.  Additionally, a property \"prefix\" is added.
+`tramp-goa-interface-files' of the corresponding GNOME Online
+Account.  Additionally, a property \"prefix\" is added.
 VEC is used only for traces."
-  (with-tramp-connection-property (tramp-make-goa-name vec) "goa-accounts"
+  (with-tramp-connection-property nil "goa-accounts"
     (dolist
        (object-path
         (mapcar
@@ -2012,15 +2314,15 @@ VEC is used only for traces."
                (cdr (assoc "ProviderType" account-properties))
                '("google" "owncloud"))
               (string-match tramp-goa-identity-regexp identity))
-         (setq key (make-tramp-goa-name
+         (setq key (make-tramp-goa-account
                     :method (cdr (assoc "ProviderType" account-properties))
                     :user (match-string 1 identity)
                     :host (match-string 2 identity)
                     :port (match-string 3 identity)))
-         (when (string-equal (tramp-goa-name-method key) "google")
-           (setf (tramp-goa-name-method key) "gdrive"))
-         (when (string-equal (tramp-goa-name-method key) "owncloud")
-           (setf (tramp-goa-name-method key) "nextcloud"))
+         (when (string-equal (tramp-goa-account-method key) "google")
+           (setf (tramp-goa-account-method key) "gdrive"))
+         (when (string-equal (tramp-goa-account-method key) "owncloud")
+           (setf (tramp-goa-account-method key) "nextcloud"))
          ;; Cache all properties.
          (dolist (prop (nconc account-properties files-properties))
            (tramp-set-connection-property key (car prop) (cdr prop)))
@@ -2036,6 +2338,87 @@ VEC is used only for traces."
     ;; Mark, that goa accounts have been cached.
     "cached"))
 
+(defun tramp-parse-goa-accounts (service)
+  "Return a list of (user host) tuples allowed to access.
+It checks for registered GNOME Online Accounts."
+  ;; SERVICE might be encoded as a DNS-SD service.
+  (and (string-match tramp-dns-sd-service-regexp service)
+       (setq service (match-string 1 service)))
+  (let (result)
+    (maphash
+     (lambda (key _value)
+       (if (and (tramp-goa-account-p key)
+               (string-equal service (tramp-goa-account-method key)))
+          (push (list (tramp-goa-account-user key)
+                      (tramp-goa-account-host key))
+                result)))
+     tramp-cache-data)
+    result))
+
+
+;; Media devices functions.
+
+(defun tramp-get-media-device (vec)
+  "Transform VEC into a `tramp-media-device' structure.
+Check, that respective cache values do exist."
+  (if-let ((media (tramp-get-connection-property vec "media-device" nil))
+          (prop (tramp-get-connection-property media "vector" nil)))
+      media
+    (tramp-get-media-devices vec)
+    (tramp-get-connection-property vec "media-device" nil)))
+
+(defun tramp-get-media-devices (vec)
+  "Retrieve media devices, and cache them.
+The hash key is a `tramp-media-device' structure.
+VEC is used only for traces."
+  (let (devices)
+    (dolist (method tramp-media-methods)
+      (dolist (volume (cadr (with-tramp-dbus-call-method vec t
+                             :session (tramp-gvfs-service-volumemonitor method)
+                             tramp-gvfs-path-remotevolumemonitor
+                             tramp-gvfs-interface-remotevolumemonitor "List")))
+       (let* ((uri (url-generic-parse-url (nth 5 volume)))
+              (vec (make-tramp-file-name
+                    :method "media"
+                    ;; A host name cannot contain spaces.
+                    :host (replace-regexp-in-string " " "_" (nth 1 volume))))
+              (media (make-tramp-media-device
+                      :method method
+                      :host (tramp-gvfs-url-host (nth 5 volume))
+                      :port (and (url-portspec uri)
+                                 (number-to-string (url-portspec uri))))))
+         (push (tramp-file-name-host vec) devices)
+         (tramp-set-connection-property vec "activation-uri" (nth 5 volume))
+         (tramp-set-connection-property vec "media-device" media)
+         (tramp-set-connection-property media "vector" vec))))
+
+    ;; Adapt default host name, supporting /media:: when possible.
+    (setq tramp-default-host-alist
+         (append
+          `(("media" nil ,(if (= (length devices) 1) (car devices) "")))
+          (delete
+           (assoc "media" tramp-default-host-alist)
+           tramp-default-host-alist)))))
+
+(defun tramp-parse-media-names (service)
+  "Return a list of (user host) tuples allowed to access.
+It checks for mounted media devices."
+  ;; SERVICE might be encoded as a DNS-SD service.
+  (and (string-match tramp-dns-sd-service-regexp service)
+       (setq service (match-string 1 service)))
+  (let (result)
+    (maphash
+     (lambda (key _value)
+       (if (and (tramp-media-device-p key)
+               (string-equal service (tramp-media-device-method key))
+               (tramp-get-connection-property key "vector" nil))
+          (push
+           (list nil (tramp-file-name-host
+                      (tramp-get-connection-property key "vector" nil)))
+           result)))
+     tramp-cache-data)
+    result))
+
 
 ;; D-Bus zeroconf functions.
 
@@ -2080,39 +2463,61 @@ This uses \"avahi-browse\" in case D-Bus is not enabled 
in Avahi."
          (list user host)))
       result))))
 
-;; Add completion functions for AFP, DAV, DAVS, SFTP and SMB methods.
 (when tramp-gvfs-enabled
-  ;; Suppress D-Bus error messages.
-  (let (tramp-gvfs-dbus-event-vector)
+  ;; Suppress D-Bus error messages and Tramp traces.
+  (let (tramp-gvfs-dbus-event-vector tramp-verbose fun)
+    ;; Add completion functions for services announced by DNS-SD.
+    ;; See <http://www.dns-sd.org/ServiceTypes.html> for valid service types.
     (zeroconf-init tramp-gvfs-zeroconf-domain)
-    (if (zeroconf-list-service-types)
-       (progn
-         (tramp-set-completion-function
-          "afp" '((tramp-zeroconf-parse-device-names "_afpovertcp._tcp")))
-         (tramp-set-completion-function
-          "dav" '((tramp-zeroconf-parse-device-names "_webdav._tcp")))
-         (tramp-set-completion-function
-          "davs" '((tramp-zeroconf-parse-device-names "_webdav._tcp")))
-         (tramp-set-completion-function
-          "sftp" '((tramp-zeroconf-parse-device-names "_ssh._tcp")
-                   (tramp-zeroconf-parse-device-names "_workstation._tcp")))
-         (when (member "smb" tramp-gvfs-methods)
-           (tramp-set-completion-function
-            "smb" '((tramp-zeroconf-parse-device-names "_smb._tcp")))))
-
-      (when (executable-find "avahi-browse")
+    (when (setq fun (or (and (zeroconf-list-service-types)
+                            #'tramp-zeroconf-parse-device-names)
+                       (and (executable-find "avahi-browse")
+                            #'tramp-gvfs-parse-device-names)))
+      (when (member "afp" tramp-gvfs-methods)
+       (tramp-set-completion-function
+        "afp" `((,fun "_afpovertcp._tcp"))))
+      (when (member "dav" tramp-gvfs-methods)
+       (tramp-set-completion-function
+        "dav" `((,fun "_webdav._tcp")
+                (,fun "_webdavs._tcp"))))
+      (when (member "davs" tramp-gvfs-methods)
+       (tramp-set-completion-function
+        "davs" `((,fun "_webdav._tcp")
+                 (,fun "_webdavs._tcp"))))
+      (when (member "ftp" tramp-gvfs-methods)
+       (tramp-set-completion-function
+        "ftp" `((,fun "_ftp._tcp"))))
+      (when (member "http" tramp-gvfs-methods)
        (tramp-set-completion-function
-        "afp" '((tramp-gvfs-parse-device-names "_afpovertcp._tcp")))
+        "http" `((,fun "_http._tcp")
+                 (,fun "_https._tcp"))))
+      (when (member "https" tramp-gvfs-methods)
        (tramp-set-completion-function
-        "dav" '((tramp-gvfs-parse-device-names "_webdav._tcp")))
+        "https" `((,fun "_http._tcp")
+                  (,fun "_https._tcp"))))
+      (when (member "sftp" tramp-gvfs-methods)
        (tramp-set-completion-function
-        "davs" '((tramp-gvfs-parse-device-names "_webdav._tcp")))
+        "sftp" `((,fun "_sftp-ssh._tcp")
+                 (,fun "_ssh._tcp")
+                 (,fun "_workstation._tcp"))))
+      (when (member "smb" tramp-gvfs-methods)
        (tramp-set-completion-function
-        "sftp" '((tramp-gvfs-parse-device-names "_ssh._tcp")
-                 (tramp-gvfs-parse-device-names "_workstation._tcp")))
-       (when (member "smb" tramp-gvfs-methods)
-         (tramp-set-completion-function
-          "smb" '((tramp-gvfs-parse-device-names "_smb._tcp"))))))))
+        "smb" `((,fun "_smb._tcp")))))
+
+    ;; Add completion functions for GNOME Online Accounts.
+    (tramp-get-goa-accounts nil)
+    (dolist (method tramp-goa-methods)
+      (when (member method tramp-gvfs-methods)
+       (tramp-set-completion-function
+        method `((tramp-parse-goa-accounts ,(format "_%s._tcp" method))))))
+
+    ;; Add completion functions for media devices.
+    (tramp-get-media-devices nil)
+    (tramp-set-completion-function
+     "media"
+     (mapcar
+      (lambda (method) `(tramp-parse-media-names ,(format "_%s._tcp" method)))
+      tramp-media-methods))))
 
 (add-hook 'tramp-unload-hook
          (lambda ()
@@ -2125,7 +2530,7 @@ This uses \"avahi-browse\" in case D-Bus is not enabled 
in Avahi."
 ;; * (Customizable) unmount when exiting Emacs.  See tramp-archive.el.
 ;;
 ;; * Host name completion for existing mount points (afp-server,
-;;   smb-server, google-drive, nextcloud) or via smb-network or network.
+;;   smb-server) or via smb-network or network.
 ;;
 ;; * Check, how two shares of the same SMB server can be mounted in
 ;;   parallel.
diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el
index 9f53985..445098a 100644
--- a/lisp/net/tramp-rclone.el
+++ b/lisp/net/tramp-rclone.el
@@ -157,10 +157,9 @@ Operations not mentioned here will be handled by the 
default Emacs primitives.")
   "Invoke the rclone handler for OPERATION and ARGS.
 First arg specifies the OPERATION, second arg is a list of arguments to
 pass to the OPERATION."
-  (let ((fn (assoc operation tramp-rclone-file-name-handler-alist)))
-    (if fn
-       (save-match-data (apply (cdr fn) args))
-      (tramp-run-real-handler operation args))))
+  (if-let ((fn (assoc operation tramp-rclone-file-name-handler-alist)))
+      (save-match-data (apply (cdr fn) args))
+    (tramp-run-real-handler operation args)))
 
 ;;;###tramp-autoload
 (tramp--with-startup
@@ -220,7 +219,7 @@ file names."
        (when (and (not ok-if-already-exists) (file-exists-p newname))
          (tramp-error v 'file-already-exists newname))
        (when (and (file-directory-p newname)
-                  (not (tramp-compat-directory-name-p newname)))
+                  (not (directory-name-p newname)))
          (tramp-error v 'file-error "File is a directory %s" newname))
 
        (if (or (and t1 (not (tramp-rclone-file-name-p filename)))
@@ -271,8 +270,8 @@ file names."
   (filename newname &optional ok-if-already-exists keep-date
    preserve-uid-gid preserve-extended-attributes)
   "Like `copy-file' for Tramp files."
-  (setq filename (expand-file-name filename))
-  (setq newname (expand-file-name newname))
+  (setq filename (expand-file-name filename)
+       newname (expand-file-name newname))
   ;; At least one file a Tramp file?
   (if (or (tramp-tramp-file-p filename)
          (tramp-tramp-file-p newname))
@@ -429,8 +428,8 @@ file names."
 (defun tramp-rclone-handle-rename-file
   (filename newname &optional ok-if-already-exists)
   "Like `rename-file' for Tramp files."
-  (setq filename (expand-file-name filename))
-  (setq newname (expand-file-name newname))
+  (setq filename (expand-file-name filename)
+       newname (expand-file-name newname))
   ;; At least one file a Tramp file?
   (if (or (tramp-tramp-file-p filename)
           (tramp-tramp-file-p newname))
@@ -564,7 +563,7 @@ connection if a previous connection has died for some 
reason."
                 ,(tramp-rclone-mount-point vec)
                 ;; This could be nil.
                 ,(tramp-get-method-parameter vec 'tramp-mount-args))))
-       (while (not (file-exists-p (tramp-make-tramp-file-name vec 'localname)))
+       (while (not (file-exists-p (tramp-make-tramp-file-name vec 'noloc)))
          (tramp-cleanup-connection vec 'keep-debug 'keep-password))
 
        ;; Mark it as connected.
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index af97328..b8f3c0d 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -866,8 +866,12 @@ Escape sequence %s is replaced with name of Perl binary.")
   "Perl program to use for decoding a file.
 Escape sequence %s is replaced with name of Perl binary.")
 
+(defconst tramp-hexdump-encode "%h -v -e '16/1 \" %%02x\" \"\\n\"'"
+  "`hexdump' program to use for encoding a file.
+This string is passed to `format', so percent characters need to be doubled.")
+
 (defconst tramp-awk-encode
-  "od -v -t x1 -A n | busybox awk '\\
+  "%a '\\
 BEGIN {
   b64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"
   b16 = \"0123456789abcdef\"
@@ -897,11 +901,25 @@ END {
   }
   printf tail
 }'"
-  "Awk program to use for encoding a file.
+  "`awk' program to use for encoding a file.
+This string is passed to `format', so percent characters need to be doubled.")
+
+(defconst tramp-hexdump-awk-encode
+  (format "%s | %s" tramp-hexdump-encode tramp-awk-encode)
+  "`hexdump' / `awk' pipe to use for encoding a file.
+This string is passed to `format', so percent characters need to be doubled.")
+
+(defconst tramp-od-encode "%o -v -t x1 -A n"
+  "`od' program to use for encoding a file.
+This string is passed to `format', so percent characters need to be doubled.")
+
+(defconst tramp-od-awk-encode
+  (format "%s | %s" tramp-od-encode tramp-awk-encode)
+  "`od' / `awk' pipe to use for encoding a file.
 This string is passed to `format', so percent characters need to be doubled.")
 
 (defconst tramp-awk-decode
-  "busybox awk '\\
+  "%a '\\
 BEGIN {
   b64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"
 }
@@ -926,12 +944,6 @@ BEGIN {
   "Awk program to use for decoding a file.
 This string is passed to `format', so percent characters need to be doubled.")
 
-(defconst tramp-awk-coding-test
-  "test -c /dev/zero && \
-od -v -t x1 -A n </dev/null && \
-busybox awk '{}' </dev/null"
-  "Test command for checking `tramp-awk-encode' and `tramp-awk-decode'.")
-
 (defconst tramp-vc-registered-read-file-names
   "echo \"(\"
 while read file; do
@@ -1051,9 +1063,7 @@ component is used as the target of the symlink."
       (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-name-localname
-                (tramp-dissect-file-name (expand-file-name target))))))
+         (setq target (tramp-file-local-name (expand-file-name target)))))
 
       ;; If TARGET is still remote, quote it.
       (if (tramp-tramp-file-p target)
@@ -1104,8 +1114,7 @@ component is used as the target of the symlink."
   "Like `file-truename' for Tramp files."
   ;; Preserve trailing "/".
   (funcall
-   (if (tramp-compat-directory-name-p filename)
-       #'file-name-as-directory #'identity)
+   (if (directory-name-p filename) #'file-name-as-directory #'identity)
    ;; Quote properly.
    (funcall
     (if (tramp-compat-file-name-quoted-p filename)
@@ -1190,9 +1199,9 @@ component is used as the target of the symlink."
                   (tramp-error
                    v 'file-error
                    "Maximum number (%d) of symlinks exceeded" numchase-limit))
-                (setq result (reverse result))
-                ;; Combine list to form string.
-                (setq result
+                (setq result (reverse result)
+                      ;; Combine list to form string.
+                      result
                       (if result (string-join (cons "" result) "/") "/"))
                 (when (string-empty-p result) (setq result "/")))))
 
@@ -1263,8 +1272,8 @@ component is used as the target of the symlink."
 (defun tramp-do-file-attributes-with-ls (vec localname &optional id-format)
   "Implement `file-attributes' for Tramp files using the ls(1) command."
   (let (symlinkp dirp
-                res-inode res-filemodes res-numlinks
-                res-uid res-gid res-size res-symlink-target)
+       res-inode res-filemodes res-numlinks
+       res-uid res-gid res-size res-symlink-target)
     (tramp-message vec 5 "file attributes with ls: %s" localname)
     ;; We cannot send all three commands combined, it could exceed
     ;; NAME_MAX or PATH_MAX.  Happened on macOS, for example.
@@ -1948,7 +1957,7 @@ tramp-sh-handle-file-name-all-completions: internal error 
accessing `%s': `%s'"
          ;; scp or rsync DTRT.
          (progn
            (when (and (file-directory-p newname)
-                      (not (tramp-compat-directory-name-p newname)))
+                      (not (directory-name-p newname)))
              (tramp-error v 'file-already-exists newname))
            (setq dirname (directory-file-name (expand-file-name dirname))
                  newname (directory-file-name (expand-file-name newname)))
@@ -1978,8 +1987,8 @@ tramp-sh-handle-file-name-all-completions: internal error 
accessing `%s': `%s'"
   "Like `rename-file' for Tramp files."
   ;; Check if both files are local -- invoke normal rename-file.
   ;; Otherwise, use Tramp from local system.
-  (setq filename (expand-file-name filename))
-  (setq newname (expand-file-name newname))
+  (setq filename (expand-file-name filename)
+       newname (expand-file-name newname))
   ;; At least one file a Tramp file?
   (if (or (tramp-tramp-file-p filename)
           (tramp-tramp-file-p newname))
@@ -2030,7 +2039,7 @@ file names."
        (when (and (not ok-if-already-exists) (file-exists-p newname))
          (tramp-error v 'file-already-exists newname))
        (when (and (file-directory-p newname)
-                  (not (tramp-compat-directory-name-p newname)))
+                  (not (directory-name-p newname)))
          (tramp-error v 'file-error "File is a directory %s" newname))
 
        (with-tramp-progress-reporter
@@ -2171,8 +2180,8 @@ the uid and gid from FILENAME."
                            v 'file-error
                            "Unknown operation `%s', must be `copy' or `rename'"
                            op))))
-            (localname1 (tramp-compat-file-local-name filename))
-            (localname2 (tramp-compat-file-local-name newname))
+            (localname1 (tramp-file-local-name filename))
+            (localname2 (tramp-file-local-name newname))
             (prefix (file-remote-p (if t1 filename newname)))
              cmd-result)
        (when (and (eq op 'copy) (file-directory-p filename))
@@ -2714,7 +2723,7 @@ The method used must be an out-of-band method."
            (when (file-symlink-p filename)
              (goto-char (search-backward "->" beg 'noerror)))
            (search-backward
-            (if (tramp-compat-directory-name-p filename)
+            (if (directory-name-p filename)
                 "."
               (file-name-nondirectory filename))
             beg 'noerror)
@@ -2724,12 +2733,11 @@ The method used must be an out-of-band method."
          (goto-char (point-min))
          ;; First find the line to put it on.
          (when (re-search-forward "^\\([[:space:]]*total\\)" nil t)
-           (let ((available (get-free-disk-space ".")))
-             (when available
-               ;; Replace "total" with "total used", to avoid confusion.
-               (replace-match "\\1 used in directory")
-               (end-of-line)
-               (insert " available " available))))
+           (when-let ((available (get-free-disk-space ".")))
+             ;; Replace "total" with "total used", to avoid confusion.
+             (replace-match "\\1 used in directory")
+             (end-of-line)
+             (insert " available " available)))
 
          (goto-char (point-max)))))))
 
@@ -2796,8 +2804,11 @@ the result will be a local, non-Tramp, file name."
 ;; We use BUFFER also as connection buffer during setup. Because of
 ;; this, its original contents must be saved, and restored once
 ;; connection has been setup.
+;; The complete STDERR buffer is available only when the process has
+;; terminated.
 (defun tramp-sh-handle-make-process (&rest args)
-  "Like `make-process' for Tramp files."
+  "Like `make-process' for Tramp files.
+STDERR can also be a file name."
   (when args
     (with-parsed-tramp-file-name (expand-file-name default-directory) nil
       (let ((name (plist-get args :name))
@@ -2829,14 +2840,23 @@ the result will be a local, non-Tramp, file name."
          (signal 'wrong-type-argument (list #'functionp sentinel)))
        (unless (or (null stderr) (bufferp stderr) (stringp stderr))
          (signal 'wrong-type-argument (list #'stringp stderr)))
+       (when (and (stringp stderr) (tramp-tramp-file-p stderr)
+                  (not (tramp-equal-remote default-directory stderr)))
+         (signal 'file-error (list "Wrong stderr" stderr)))
 
        (let* ((buffer
                (if buffer
                    (get-buffer-create buffer)
                  ;; BUFFER can be nil.  We use a temporary buffer.
                  (generate-new-buffer tramp-temp-buffer-name)))
-              (stderr (and stderr (get-buffer-create stderr)))
-              (tmpstderr (and stderr (tramp-make-tramp-temp-file v)))
+              ;; STDERR can also be a file name.
+              (tmpstderr
+               (and stderr
+                    (if (and (stringp stderr) (tramp-tramp-file-p stderr))
+                        (tramp-unquote-file-local-name stderr)
+                      (tramp-make-tramp-temp-file v))))
+              (remote-tmpstderr
+               (and tmpstderr (tramp-make-tramp-file-name v tmpstderr)))
               (program (car command))
               (args (cdr command))
               ;; When PROGRAM matches "*sh", and the first arg is
@@ -2965,21 +2985,35 @@ the result will be a local, non-Tramp, file name."
                      (ignore-errors
                        (set-process-query-on-exit-flag p (null noquery))
                        (set-marker (process-mark p) (point)))
+                     ;; We must flush them here already; otherwise
+                     ;; `rename-file', `delete-file' or
+                     ;; `insert-file-contents' will fail.
+                     (tramp-flush-connection-property v "process-name")
+                     (tramp-flush-connection-property v "process-buffer")
+                     ;; Copy tmpstderr file.
+                     (when (and (stringp stderr)
+                                (not (tramp-tramp-file-p stderr)))
+                       (add-function
+                        :after (process-sentinel p)
+                        (lambda (_proc _msg)
+                          (rename-file remote-tmpstderr stderr))))
                      ;; Provide error buffer.  This shows only
                      ;; initial error messages; messages arriving
-                     ;; later on shall be inserted by `auto-revert'.
-                     ;; The temporary file will still be existing.
-                     ;; TODO: Write a sentinel, which deletes the
-                     ;; temporary file.
-                     (when tmpstderr
-                       ;; We must flush them here already; otherwise
-                       ;; `insert-file-contents' will fail.
-                       (tramp-flush-connection-property v "process-name")
-                       (tramp-flush-connection-property v "process-buffer")
+                     ;; later on will be inserted when the process is
+                     ;; deleted.  The temporary file will exist until
+                     ;; the process is deleted.
+                     (when (bufferp stderr)
                        (with-current-buffer stderr
-                         (insert-file-contents
-                          (tramp-make-tramp-file-name v tmpstderr) 'visit)
-                         (auto-revert-mode)))
+                         (insert-file-contents-literally
+                          remote-tmpstderr 'visit))
+                       ;; Delete tmpstderr file.
+                       (add-function
+                        :after (process-sentinel p)
+                        (lambda (_proc _msg)
+                          (with-current-buffer stderr
+                            (insert-file-contents-literally
+                             remote-tmpstderr 'visit nil nil 'replace))
+                          (delete-file remote-tmpstderr))))
                      ;; Return process.
                      p)))
 
@@ -3028,7 +3062,7 @@ the result will be a local, non-Tramp, file name."
        (setq infile (expand-file-name infile))
        (if (tramp-equal-remote default-directory infile)
            ;; INFILE is on the same remote host.
-           (setq input (with-parsed-tramp-file-name infile nil localname))
+           (setq input (tramp-file-local-name infile))
          ;; INFILE must be copied to remote host.
          (setq input (tramp-make-tramp-temp-file v)
                tmpinput (tramp-make-tramp-file-name v input 'nohop))
@@ -3059,8 +3093,7 @@ the result will be a local, non-Tramp, file name."
          (setcar (cdr destination) (expand-file-name (cadr destination)))
          (if (tramp-equal-remote default-directory (cadr destination))
              ;; stderr is on the same remote host.
-             (setq stderr (with-parsed-tramp-file-name
-                              (cadr destination) nil localname))
+             (setq stderr (tramp-file-local-name (cadr destination)))
            ;; stderr must be copied to remote host.  The temporary
            ;; file must be deleted after execution.
            (setq stderr (tramp-make-tramp-temp-file v)
@@ -3122,7 +3155,7 @@ the result will be a local, non-Tramp, file name."
   (append
    (tramp-get-remote-path (tramp-dissect-file-name default-directory))
    ;; The equivalent to `exec-directory'.
-   `(,(tramp-compat-file-local-name default-directory))))
+   `(,(tramp-file-local-name (expand-file-name default-directory)))))
 
 (defun tramp-sh-handle-file-local-copy (filename)
   "Like `file-local-copy' for Tramp files."
@@ -3468,8 +3501,7 @@ the result will be a local, non-Tramp, file name."
 (defun tramp-sh-handle-vc-registered (file)
   "Like `vc-registered' for Tramp files."
   (when vc-handled-backends
-    (let ((tramp-message-show-message
-          (and (not revert-buffer-in-progress-p) tramp-message-show-message))
+    (let ((inhibit-message (or revert-buffer-in-progress-p inhibit-message))
          (temp-message (unless revert-buffer-in-progress-p "")))
       (with-temp-message temp-message
        (with-parsed-tramp-file-name file nil
@@ -3559,10 +3591,9 @@ the result will be a local, non-Tramp, file name."
 (defun tramp-sh-file-name-handler (operation &rest args)
   "Invoke remote-shell Tramp file name handler.
 Fall back to normal file name handler if no Tramp handler exists."
-  (let ((fn (assoc operation tramp-sh-file-name-handler-alist)))
-    (if fn
-       (save-match-data (apply (cdr fn) args))
-      (tramp-run-real-handler operation args))))
+  (if-let ((fn (assoc operation tramp-sh-file-name-handler-alist)))
+      (save-match-data (apply (cdr fn) args))
+    (tramp-run-real-handler operation args)))
 
 ;; This must be the last entry, because `identity' always matches.
 ;;;###tramp-autoload
@@ -3947,8 +3978,8 @@ This function expects to be in the right *tramp* buffer."
          ;; Remove all ~/foo directories from dirlist.
          (let (newdl d)
            (while dirlist
-             (setq d (car dirlist))
-             (setq dirlist (cdr dirlist))
+             (setq d (car dirlist)
+                   dirlist (cdr dirlist))
              (unless (char-equal ?~ (aref d 0))
                (setq newdl (cons d newdl))))
            (setq dirlist (nreverse newdl))))
@@ -3995,8 +4026,7 @@ variable PATH."
       (setq tmpfile
            (tramp-make-tramp-file-name vec (tramp-make-tramp-temp-file vec)))
       (write-region command nil tmpfile)
-      (tramp-send-command
-       vec (format ". %s" (tramp-compat-file-local-name tmpfile)))
+      (tramp-send-command vec (format ". %s" (tramp-file-local-name tmpfile)))
       (delete-file tmpfile))))
 
 ;; ------------------------------------------------------------
@@ -4383,7 +4413,7 @@ and end of region, and are expected to replace the region 
contents
 with the encoded or decoded results, respectively.")
 
 (defconst tramp-remote-coding-commands
-  `((b64 "base64" "base64 -d -i")
+  '((b64 "base64" "base64 -d -i")
     ;; "-i" is more robust with older base64 from GNU coreutils.
     ;; However, I don't know whether all base64 versions do supports
     ;; this option.
@@ -4394,8 +4424,9 @@ with the encoded or decoded results, respectively.")
     (b64 "recode data..base64" "recode base64..data")
     (b64 tramp-perl-encode-with-module tramp-perl-decode-with-module)
     (b64 tramp-perl-encode tramp-perl-decode)
-    ;; This is painful slow, so we put it on the end.
-    (b64 tramp-awk-encode tramp-awk-decode ,tramp-awk-coding-test)
+    ;; These are painfully slow, so we put them on the end.
+    (b64 tramp-hexdump-awk-encode tramp-awk-decode)
+    (b64 tramp-od-awk-encode tramp-awk-decode)
     (uu  "uuencode xxx" "uudecode -o /dev/stdout" "test -c /dev/stdout")
     (uu  "uuencode xxx" "uudecode -o -")
     (uu  "uuencode xxx" "uudecode -p")
@@ -4421,6 +4452,8 @@ Perl or Shell implementation for this functionality.  This
 program will be transferred to the remote host, and it is
 available as shell function with the same name.  A \"%t\" format
 specifier in the variable value denotes a temporary file.
+\"%a\", \"%h\" and \"%o\" format specifiers are replaced by the
+respective `awk', `hexdump' and `od' commands.
 
 The optional TEST command can be used for further tests, whether
 ENCODING and DECODING are applicable.")
@@ -4439,8 +4472,8 @@ Goes through the list `tramp-local-coding-commands' and
        (catch 'wont-work-local
          (let ((format (nth 0 litem))
                (remote-commands tramp-remote-coding-commands))
-           (setq loc-enc (nth 1 litem))
-           (setq loc-dec (nth 2 litem))
+           (setq loc-enc (nth 1 litem)
+                 loc-dec (nth 2 litem))
            ;; If the local encoder or decoder is a string, the
            ;; corresponding command has to work locally.
            (if (not (stringp loc-enc))
@@ -4462,20 +4495,15 @@ Goes through the list `tramp-local-coding-commands' and
              (setq ritem (pop remote-commands))
              (catch 'wont-work-remote
                (when (equal format (nth 0 ritem))
-                 (setq rem-enc (nth 1 ritem))
-                 (setq rem-dec (nth 2 ritem))
-                 (setq rem-test (nth 3 ritem))
+                 (setq rem-enc (nth 1 ritem)
+                       rem-dec (nth 2 ritem)
+                       rem-test (nth 3 ritem))
                  ;; Check the remote test command if exists.
                  (when (stringp rem-test)
                    (tramp-message
                     vec 5 "Checking remote test command `%s'" rem-test)
                    (unless (tramp-send-command-and-check vec rem-test t)
                      (throw 'wont-work-remote nil)))
-                 ;; Check if remote perl exists when necessary.
-                 (when (and (symbolp rem-enc)
-                            (string-match-p "perl" (symbol-name rem-enc))
-                            (not (tramp-get-remote-perl vec)))
-                   (throw 'wont-work-remote nil))
                  ;; Check if remote encoding and decoding commands can be
                  ;; called remotely with null input and output.  This makes
                  ;; sure there are no syntax errors and the command is really
@@ -4485,10 +4513,36 @@ Goes through the list `tramp-local-coding-commands' and
                  ;; redirecting "mimencode" output to /dev/null, then as root
                  ;; it might change the permissions of /dev/null!
                  (unless (stringp rem-enc)
-                   (let ((name (symbol-name rem-enc)))
+                   (let ((name (symbol-name rem-enc))
+                         (value (symbol-value rem-enc)))
+                     ;; Check if remote perl exists when necessary.
+                     (and (string-match-p "perl" name)
+                          (not (tramp-get-remote-perl vec))
+                          (throw 'wont-work-remote nil))
+                     ;; Check if remote awk exists when necessary.
+                     (and (string-match-p "\\(^\\|[^%]\\)%a" value)
+                          (not (tramp-get-remote-awk vec))
+                          (throw 'wont-work-remote nil))
+                     ;; Check if remote hexdump exists when necessary.
+                     (and (string-match-p "\\(^\\|[^%]\\)%h" value)
+                          (not (tramp-get-remote-hexdump vec))
+                          (throw 'wont-work-remote nil))
+                     ;; Check if remote od exists when necessary.
+                     (and (string-match-p "\\(^\\|[^%]\\)%o" value)
+                          (not (tramp-get-remote-od vec))
+                          (throw 'wont-work-remote nil))
                      (while (string-match "-" name)
                        (setq name (replace-match "_" nil t name)))
-                     (tramp-maybe-send-script vec (symbol-value rem-enc) name)
+                     (when (string-match-p "\\(^\\|[^%]\\)%[aho]" value)
+                       (setq value
+                             (format-spec
+                              value
+                              (format-spec-make
+                               ?a (tramp-get-remote-awk vec)
+                               ?h (tramp-get-remote-hexdump vec)
+                               ?o (tramp-get-remote-od vec)))
+                             value (replace-regexp-in-string "%" "%%" value)))
+                     (tramp-maybe-send-script vec value name)
                      (setq rem-enc name)))
                  (tramp-message
                   vec 5
@@ -4503,6 +4557,15 @@ Goes through the list `tramp-local-coding-commands' and
                          tmpfile)
                      (while (string-match "-" name)
                        (setq name (replace-match "_" nil t name)))
+                     (when (string-match-p "\\(^\\|[^%]\\)%[aho]" value)
+                       (setq value
+                             (format-spec
+                              value
+                              (format-spec-make
+                               ?a (tramp-get-remote-awk vec)
+                               ?h (tramp-get-remote-hexdump vec)
+                               ?o (tramp-get-remote-od vec)))
+                             value (replace-regexp-in-string "%" "%%" value)))
                      (when (string-match-p "\\(^\\|[^%]\\)%t" value)
                        (setq tmpfile
                              (make-temp-name
@@ -4513,7 +4576,7 @@ Goes through the list `tramp-local-coding-commands' and
                              (format-spec
                               value
                               (format-spec-make
-                               ?t (tramp-compat-file-local-name tmpfile)))))
+                               ?t (tramp-file-local-name tmpfile)))))
                      (tramp-maybe-send-script vec value name)
                      (setq rem-dec name)))
                  (tramp-message
@@ -4531,9 +4594,9 @@ Goes through the list `tramp-local-coding-commands' and
                      (throw 'wont-work-remote nil)))
 
                  ;; `rem-enc' and `rem-dec' could be a string meanwhile.
-                 (setq rem-enc (nth 1 ritem))
-                 (setq rem-dec (nth 2 ritem))
-                 (setq found t)))))))
+                 (setq rem-enc (nth 1 ritem)
+                       rem-dec (nth 2 ritem)
+                       found t)))))))
 
       (when found
        ;; Set connection properties.  Since the commands are risky
@@ -4796,7 +4859,7 @@ If there is just some editing, retry it after 5 seconds."
         vec 5 "Cannot timeout session, trying it again in %s seconds." 5)
        (run-at-time 5 nil 'tramp-timeout-session vec))
     (tramp-message
-     vec 3 "Timeout session %s" (tramp-make-tramp-file-name vec 'localname))
+     vec 3 "Timeout session %s" (tramp-make-tramp-file-name vec 'noloc))
     (tramp-cleanup-connection vec 'keep-debug)))
 
 (defun tramp-maybe-open-connection (vec)
@@ -4818,11 +4881,8 @@ connection if a previous connection has died for some 
reason."
                (not (tramp-file-name-equal-p
                      vec (car tramp-current-connection)))
                (time-less-p
-                ;; `current-time' can be removed once we get rid of Emacs 24.
-                (time-since (or (cdr tramp-current-connection) (current-time)))
-                ;; `seconds-to-time' can be removed once we get rid
-                ;; of Emacs 24.
-                (seconds-to-time (or tramp-connection-min-time-diff 0))))
+                (time-since (cdr tramp-current-connection))
+                (or tramp-connection-min-time-diff 0)))
       (throw 'suppress 'suppress))
 
     ;; If too much time has passed since last command was sent, look
@@ -4833,11 +4893,9 @@ connection if a previous connection has died for some 
reason."
     ;; try to send a command from time to time, then look again
     ;; whether the process is really alive.
     (condition-case nil
-       ;; `seconds-to-time' can be removed once we get rid of Emacs 24.
-       (when (and (time-less-p (seconds-to-time 60)
-                               (time-since
-                                (tramp-get-connection-property
-                                 p "last-cmd-time" (seconds-to-time 0))))
+       (when (and (time-less-p
+                   60 (time-since
+                       (tramp-get-connection-property p "last-cmd-time" 0)))
                   (process-live-p p))
          (tramp-send-command vec "echo are you awake" t t)
          (unless (and (process-live-p p)
@@ -5594,7 +5652,7 @@ This command is returned only if 
`delete-by-moving-to-trash' is non-nil."
           "%s -t %s %s"
           result
           (format-time-string "%Y%m%d%H%M.%S")
-          (tramp-compat-file-local-name tmpfile))))
+          (tramp-file-local-name tmpfile))))
        (delete-file tmpfile))
       result)))
 
@@ -5769,6 +5827,47 @@ ID-FORMAT valid values are `string' and `integer'."
        tramp-unknown-id-string)
        (t res)))))
 
+(defun tramp-get-remote-busybox (vec)
+  "Determine remote `busybox' command."
+  (with-tramp-connection-property vec "busybox"
+    (tramp-message vec 5 "Finding a suitable `busybox' command")
+    (tramp-find-executable vec "busybox" (tramp-get-remote-path vec))))
+
+(defun tramp-get-remote-awk (vec)
+  "Determine remote `awk' command."
+  (with-tramp-connection-property vec "awk"
+    (tramp-message vec 5 "Finding a suitable `awk' command")
+    (or (tramp-find-executable vec "awk" (tramp-get-remote-path vec))
+       (let* ((busybox (tramp-get-remote-busybox vec))
+              (command (format "%s %s" busybox "awk")))
+         (and busybox
+              (tramp-send-command-and-check
+               vec (concat command " {} </dev/null"))
+              command)))))
+
+(defun tramp-get-remote-hexdump (vec)
+  "Determine remote `hexdump' command."
+  (with-tramp-connection-property vec "hexdump"
+    (tramp-message vec 5 "Finding a suitable `hexdump' command")
+    (or (tramp-find-executable vec "hexdump" (tramp-get-remote-path vec))
+       (let* ((busybox (tramp-get-remote-busybox vec))
+              (command (format "%s %s" busybox "hexdump")))
+         (and busybox
+              (tramp-send-command-and-check vec (concat command " </dev/null"))
+              command)))))
+
+(defun tramp-get-remote-od (vec)
+  "Determine remote `od' command."
+  (with-tramp-connection-property vec "od"
+    (tramp-message vec 5 "Finding a suitable `od' command")
+    (or (tramp-find-executable vec "od" (tramp-get-remote-path vec))
+       (let* ((busybox (tramp-get-remote-busybox vec))
+              (command (format "%s %s" busybox "od")))
+         (and busybox
+              (tramp-send-command-and-check
+               vec (concat command " -A n </dev/null"))
+              command)))))
+
 (defun tramp-get-env-with-u-option (vec)
   "Check, whether the remote `env' command supports the -u option."
   (with-tramp-connection-property vec "env-u-option"
@@ -5889,9 +5988,6 @@ function cell is returned to be applied on a buffer."
 ;;   likely to produce long command lines, and some shells choke on
 ;;   long command lines.
 ;;
-;; * Don't search for perl5 and perl.  Instead, only search for perl and
-;;   then look if it's the right version (with `perl -v').
-;;
 ;; * When editing a remote CVS controlled file as a different user, VC
 ;;   gets confused about the file locking status.  Try to find out why
 ;;   the workaround doesn't work.
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index bf77ab9..f02be39 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -329,10 +329,9 @@ This can be used to disable echo etc."
   "Invoke the SMB related OPERATION and ARGS.
 First arg specifies the OPERATION, second arg is a list of arguments to
 pass to the OPERATION."
-  (let ((fn (assoc operation tramp-smb-file-name-handler-alist)))
-    (if fn
-       (save-match-data (apply (cdr fn) args))
-      (tramp-run-real-handler operation args))))
+  (if-let ((fn (assoc operation tramp-smb-file-name-handler-alist)))
+      (save-match-data (apply (cdr fn) args))
+    (tramp-run-real-handler operation args)))
 
 ;;;###tramp-autoload
 (unless (memq system-type '(cygwin windows-nt))
@@ -420,7 +419,7 @@ pass to the OPERATION."
             v tramp-file-missing
             "Copying directory" "No such file or directory" dirname))
          (when (and (file-directory-p newname)
-                    (not (tramp-compat-directory-name-p newname)))
+                    (not (directory-name-p newname)))
            (tramp-error v 'file-already-exists newname))
          (cond
           ;; We must use a local temporary directory.
@@ -581,40 +580,39 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
         tramp-file-missing
         "Copying file" "No such file or directory" filename))
 
-      (let ((tmpfile (file-local-copy filename)))
-       (if tmpfile
-           ;; Remote filename.
-           (condition-case err
-               (rename-file tmpfile newname ok-if-already-exists)
-             ((error quit)
-              (delete-file tmpfile)
-              (signal (car err) (cdr err))))
-
-         ;; Remote newname.
+      (if-let ((tmpfile (file-local-copy filename)))
+         ;; Remote filename.
+         (condition-case err
+             (rename-file tmpfile newname ok-if-already-exists)
+           ((error quit)
+            (delete-file tmpfile)
+            (signal (car err) (cdr err))))
+
+       ;; Remote newname.
+       (when (and (file-directory-p newname)
+                  (directory-name-p newname))
+         (setq newname
+               (expand-file-name (file-name-nondirectory filename) newname)))
+
+       (with-parsed-tramp-file-name newname nil
+         (when (and (not ok-if-already-exists) (file-exists-p newname))
+           (tramp-error v 'file-already-exists newname))
          (when (and (file-directory-p newname)
-                    (tramp-compat-directory-name-p newname))
-           (setq newname
-                 (expand-file-name (file-name-nondirectory filename) newname)))
+                    (not (directory-name-p newname)))
+           (tramp-error v 'file-error "File is a directory %s" newname))
 
-         (with-parsed-tramp-file-name newname nil
-           (when (and (not ok-if-already-exists) (file-exists-p newname))
-             (tramp-error v 'file-already-exists newname))
-           (when (and (file-directory-p newname)
-                      (not (tramp-compat-directory-name-p newname)))
-             (tramp-error v 'file-error "File is a directory %s" newname))
-
-           ;; We must also flush the cache of the directory, because
-           ;; `file-attributes' reads the values from there.
-           (tramp-flush-file-properties v localname)
-           (unless (tramp-smb-get-share v)
-             (tramp-error
-              v 'file-error "Target `%s' must contain a share name" newname))
-           (unless (tramp-smb-send-command
-                    v (format "put \"%s\" \"%s\""
-                              (tramp-compat-file-name-unquote filename)
-                              (tramp-smb-get-localname v)))
-             (tramp-error
-              v 'file-error "Cannot copy `%s' to `%s'" filename newname))))))
+         ;; We must also flush the cache of the directory, because
+         ;; `file-attributes' reads the values from there.
+         (tramp-flush-file-properties v localname)
+         (unless (tramp-smb-get-share v)
+           (tramp-error
+            v 'file-error "Target `%s' must contain a share name" newname))
+         (unless (tramp-smb-send-command
+                  v (format "put \"%s\" \"%s\""
+                            (tramp-compat-file-name-unquote filename)
+                            (tramp-smb-get-localname v)))
+           (tramp-error
+            v 'file-error "Cannot copy `%s' to `%s'" filename newname)))))
 
     ;; KEEP-DATE handling.
     (when keep-date
@@ -1003,7 +1001,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
   (setq filename (expand-file-name filename))
   (unless switches (setq switches ""))
   ;; Mark trailing "/".
-  (when (and (tramp-compat-directory-name-p filename)
+  (when (and (directory-name-p filename)
             (not full-directory-p))
     (setq switches (concat switches "F")))
   (if full-directory-p
@@ -1188,9 +1186,7 @@ component is used as the target of the symlink."
       (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-name-localname
-                (tramp-dissect-file-name (expand-file-name target))))))
+         (setq target (tramp-file-local-name (expand-file-name target)))))
 
       ;; If TARGET is still remote, quote it.
       (if (tramp-tramp-file-p target)
@@ -1244,7 +1240,7 @@ component is used as the target of the symlink."
        (setq infile (expand-file-name infile))
        (if (tramp-equal-remote default-directory infile)
            ;; INFILE is on the same remote host.
-           (setq input (with-parsed-tramp-file-name infile nil localname))
+           (setq input (tramp-file-local-name infile))
          ;; INFILE must be copied to remote host.
          (setq input (tramp-make-tramp-temp-file v)
                tmpinput (tramp-make-tramp-file-name v input))
@@ -1357,7 +1353,7 @@ component is used as the target of the symlink."
     (when (and (not ok-if-already-exists) (file-exists-p newname))
       (tramp-error v 'file-already-exists newname))
     (when (and (file-directory-p newname)
-              (not (tramp-compat-directory-name-p newname)))
+              (not (directory-name-p newname)))
       (tramp-error v 'file-error "File is a directory %s" newname))
 
     (with-tramp-progress-reporter
@@ -1924,11 +1920,9 @@ If ARGUMENT is non-nil, use it as argument for
     ;; connection timeout.
     (with-current-buffer buf
       (goto-char (point-min))
-      ;; `seconds-to-time' can be removed once we get rid of Emacs 24.
-      (when (and (time-less-p (seconds-to-time 60)
-                             (time-since
-                              (tramp-get-connection-property
-                               p "last-cmd-time" (seconds-to-time 0))))
+      (when (and (time-less-p
+                 60 (time-since
+                     (tramp-get-connection-property p "last-cmd-time" 0)))
                 (process-live-p p)
                 (re-search-forward tramp-smb-errors nil t))
        (delete-process p)
@@ -1994,7 +1988,7 @@ If ARGUMENT is non-nil, use it as argument for
              (set-process-query-on-exit-flag p nil)
 
              (condition-case err
-                 (let (tramp-message-show-message)
+                 (let ((inhibit-message t))
                    ;; Play login scenario.
                    (tramp-process-actions
                     p vec nil
@@ -2132,7 +2126,5 @@ Removes smb prompt.  Returns nil if an error message has 
appeared."
 ;;
 ;; * Try to remove the inclusion of dummy "" directory.  Seems to be at
 ;;   several places, especially in `tramp-smb-handle-insert-directory'.
-;;
-;; * Ignore case in file names.
 
 ;;; tramp-smb.el ends here
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index 18b30ad..f258ad6 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -153,10 +153,9 @@ See `tramp-actions-before-shell' for more info.")
   "Invoke the SUDOEDIT handler for OPERATION and ARGS.
 First arg specifies the OPERATION, second arg is a list of arguments to
 pass to the OPERATION."
-  (let ((fn (assoc operation tramp-sudoedit-file-name-handler-alist)))
-    (if fn
-       (save-match-data (apply (cdr fn) args))
-      (tramp-run-real-handler operation args))))
+  (if-let ((fn (assoc operation tramp-sudoedit-file-name-handler-alist)))
+      (save-match-data (apply (cdr fn) args))
+    (tramp-run-real-handler operation args)))
 
 ;;;###tramp-autoload
 (tramp--with-startup
@@ -248,7 +247,7 @@ absolute file names."
        (when (and (not ok-if-already-exists) (file-exists-p newname))
          (tramp-error v 'file-already-exists newname))
        (when (and (file-directory-p newname)
-                  (not (tramp-compat-directory-name-p newname)))
+                  (not (directory-name-p newname)))
          (tramp-error v 'file-error "File is a directory %s" newname))
 
        (if (or (and (file-remote-p filename) (not t1))
@@ -265,10 +264,8 @@ absolute file names."
              v 0 (format "%s %s to %s" msg-operation filename newname)
            (unless (tramp-sudoedit-send-command
                     v sudoedit-operation
-                    (tramp-compat-file-name-unquote
-                     (tramp-compat-file-local-name filename))
-                    (tramp-compat-file-name-unquote
-                     (tramp-compat-file-local-name newname)))
+                    (tramp-unquote-file-local-name filename)
+                    (tramp-unquote-file-local-name newname))
              (tramp-error
               v 'file-error
               "Error %s `%s' `%s'" msg-operation filename newname))))
@@ -305,8 +302,8 @@ absolute file names."
   (filename newname &optional ok-if-already-exists keep-date
    preserve-uid-gid preserve-extended-attributes)
   "Like `copy-file' for Tramp files."
-  (setq filename (expand-file-name filename))
-  (setq newname (expand-file-name newname))
+  (setq filename (expand-file-name filename)
+       newname (expand-file-name newname))
   ;; At least one file a Tramp file?
   (if (or (tramp-tramp-file-p filename)
          (tramp-tramp-file-p newname))
@@ -508,21 +505,21 @@ the result will be a local, non-Tramp, file name."
       (tramp-message v 5 "file system info: %s" localname)
       (when (tramp-sudoedit-send-command
             v "df" "--block-size=1" "--output=size,used,avail"
-            (tramp-compat-file-name-unquote localname)))
-      (with-current-buffer (tramp-get-connection-buffer v)
-       (goto-char (point-min))
-       (forward-line)
-       (when (looking-at
-              (eval-when-compile
-                (concat "[[:space:]]*\\([[:digit:]]+\\)"
-                        "[[:space:]]+\\([[:digit:]]+\\)"
-                        "[[:space:]]+\\([[:digit:]]+\\)")))
-         (list (string-to-number (match-string 1))
-               ;; The second value is the used size.  We need the
-               ;; free size.
-               (- (string-to-number (match-string 1))
-                  (string-to-number (match-string 2)))
-               (string-to-number (match-string 3))))))))
+            (tramp-compat-file-name-unquote localname))
+       (with-current-buffer (tramp-get-connection-buffer v)
+         (goto-char (point-min))
+         (forward-line)
+         (when (looking-at
+                (eval-when-compile
+                  (concat "[[:space:]]*\\([[:digit:]]+\\)"
+                          "[[:space:]]+\\([[:digit:]]+\\)"
+                          "[[:space:]]+\\([[:digit:]]+\\)")))
+           (list (string-to-number (match-string 1))
+                 ;; The second value is the used size.  We need the
+                 ;; free size.
+                 (- (string-to-number (match-string 1))
+                    (string-to-number (match-string 2)))
+                 (string-to-number (match-string 3)))))))))
 
 (defun tramp-sudoedit-handle-set-file-times (filename &optional time)
   "Like `set-file-times' for Tramp files."
@@ -543,8 +540,7 @@ the result will be a local, non-Tramp, file name."
   "Like `file-truename' for Tramp files."
   ;; Preserve trailing "/".
   (funcall
-   (if (tramp-compat-directory-name-p filename)
-       #'file-name-as-directory #'identity)
+   (if (directory-name-p filename) #'file-name-as-directory #'identity)
    ;; Quote properly.
    (funcall
     (if (tramp-compat-file-name-quoted-p filename)
@@ -615,9 +611,7 @@ component is used as the target of the symlink."
       (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-name-localname
-                (tramp-dissect-file-name (expand-file-name target))))))
+         (setq target (tramp-file-local-name (expand-file-name target)))))
 
       ;; If TARGET is still remote, quote it.
       (if (tramp-tramp-file-p target)
@@ -646,8 +640,8 @@ component is used as the target of the symlink."
 (defun tramp-sudoedit-handle-rename-file
   (filename newname &optional ok-if-already-exists)
   "Like `rename-file' for Tramp files."
-  (setq filename (expand-file-name filename))
-  (setq newname (expand-file-name newname))
+  (setq filename (expand-file-name filename)
+       newname (expand-file-name newname))
   ;; At least one file a Tramp file?
   (if (or (tramp-tramp-file-p filename)
           (tramp-tramp-file-p newname))
@@ -715,8 +709,7 @@ ID-FORMAT valid values are `string' and `integer'."
        (format "%d:%d"
               (or uid (tramp-sudoedit-get-remote-uid v 'integer))
               (or gid (tramp-sudoedit-get-remote-gid v 'integer)))
-       (tramp-compat-file-name-unquote
-       (tramp-compat-file-local-name filename)))))
+       (tramp-unquote-file-local-name filename))))
 
 (defun tramp-sudoedit-handle-write-region
   (start end filename &optional append visit lockname mustbenew)
diff --git a/lisp/net/tramp-uu.el b/lisp/net/tramp-uu.el
index 6a044e5..f368f72 100644
--- a/lisp/net/tramp-uu.el
+++ b/lisp/net/tramp-uu.el
@@ -94,8 +94,3 @@
 (provide 'tramp-uu)
 
 ;;; tramp-uu.el ends here
-
-;; Local Variables:
-;; mode: Emacs-Lisp
-;; coding: utf-8
-;; End:
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 1e52fae..a38b3c6 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -7,8 +7,8 @@
 ;; Maintainer: Michael Albinus <address@hidden>
 ;; Keywords: comm, processes
 ;; Package: tramp
-;; Version: 2.4.3
-;; Package-Requires: ((emacs "24.4"))
+;; Version: 2.5.0-pre
+;; Package-Requires: ((emacs "25.1"))
 ;; Package-Type: multi
 ;; URL: https://savannah.gnu.org/projects/tramp
 
@@ -1033,7 +1033,7 @@ initial value is overwritten by the car of 
`tramp-file-name-structure'.")
 
 ;;;###autoload
 (defcustom tramp-ignored-file-name-regexp nil
-  "Regular expression matching file names that are not under Tramp’s control."
+  "Regular expression matching file names that are not under Tramp's control."
   :version "27.1"
   :type '(choice (const nil) regexp))
 
@@ -1258,7 +1258,7 @@ calling HANDLER.")
 ;; data structure.
 
 ;; The basic structure for remote file names.  We use a list :type,
-;; in order to be compatible with Emacs 24 and 25.
+;; in order to be compatible with Emacs 25.
 (cl-defstruct (tramp-file-name (:type list) :named)
   method user domain host port localname hop)
 
@@ -1306,9 +1306,10 @@ entry does not exist, return nil."
        ;; We use the cached property.
        (tramp-get-connection-property vec hash-entry nil)
       ;; Use the static value from `tramp-methods'.
-      (let ((methods-entry
-            (assoc param (assoc (tramp-file-name-method vec) tramp-methods))))
-       (when methods-entry (cadr methods-entry))))))
+      (when-let ((methods-entry
+                 (assoc
+                  param (assoc (tramp-file-name-method vec) tramp-methods))))
+       (cadr methods-entry)))))
 
 ;; The localname can be quoted with "/:".  Extract this.
 (defun tramp-file-name-unquote-localname (vec)
@@ -1329,6 +1330,29 @@ entry does not exist, return nil."
        (string-match-p tramp-file-name-regexp name)
        t))
 
+;; This function bypasses the file name handler approach.  It is NOT
+;; recommended to use it in any package if not absolutely necessary.
+;; However, it is more performant than `file-local-name', and might be
+;; useful where performance matters, like in operations over a bulk
+;; list of file names.
+(defun tramp-file-local-name (name)
+  "Return the local name component of NAME.
+This function removes from NAME the specification of the remote
+host and the method of accessing the host, leaving only the part
+that identifies NAME locally on the remote system.  If NAME does
+not match `tramp-file-name-regexp', just `file-local-name' is
+called.  The returned file name can be used directly as argument
+of `process-file', `start-file-process', or `shell-command'."
+  (or (and (tramp-tramp-file-p name)
+           (string-match (nth 0 tramp-file-name-structure) name)
+           (match-string (nth 4 tramp-file-name-structure) name))
+      (tramp-compat-file-local-name name)))
+
+;; The localname can be quoted with "/:".  Extract this.
+(defun tramp-unquote-file-local-name (name)
+  "Return unquoted localname of NAME."
+  (tramp-compat-file-name-unquote (tramp-file-local-name name)))
+
 (defun tramp-find-method (method user host)
   "Return the right method string to use depending on USER and HOST.
 This is METHOD, if non-nil.  Otherwise, do a lookup in
@@ -1345,8 +1369,8 @@ This is METHOD, if non-nil.  Otherwise, do a lookup in
                 (setq item (pop choices))
                 (when (and (string-match-p (or (nth 0 item) "") (or host ""))
                            (string-match-p (or (nth 1 item) "") (or user "")))
-                  (setq lmethod (nth 2 item))
-                  (setq choices nil)))
+                  (setq lmethod (nth 2 item)
+                        choices nil)))
               lmethod)
             tramp-default-method)))
     ;; We must mark, whether a default value has been used.
@@ -1366,8 +1390,8 @@ This is USER, if non-nil.  Otherwise, do a lookup in
                 (setq item (pop choices))
                 (when (and (string-match-p (or (nth 0 item) "") (or method ""))
                            (string-match-p (or (nth 1 item) "") (or host "")))
-                  (setq luser (nth 2 item))
-                  (setq choices nil)))
+                  (setq luser (nth 2 item)
+                        choices nil)))
               luser)
             tramp-default-user)))
     ;; We must mark, whether a default value has been used.
@@ -1387,8 +1411,8 @@ This is HOST, if non-nil.  Otherwise, do a lookup in
                 (setq item (pop choices))
                 (when (and (string-match-p (or (nth 0 item) "") (or method ""))
                            (string-match-p (or (nth 1 item) "") (or user "")))
-                  (setq lhost (nth 2 item))
-                  (setq choices nil)))
+                  (setq lhost (nth 2 item)
+                        choices nil)))
               lhost)
             tramp-default-host)))
     ;; We must mark, whether a default value has been used.
@@ -1450,7 +1474,7 @@ default values are used."
                     :method method :user user :domain domain :host host
                     :port port :localname localname :hop hop))
          ;; The method must be known.
-         (unless (or nodefault (tramp-completion-mode-p)
+         (unless (or nodefault non-essential
                      (string-equal method tramp-default-method-marker)
                      (assoc method tramp-methods))
            (tramp-user-error
@@ -1574,7 +1598,7 @@ necessary only.  This function will be used in file name 
completion."
                  tramp-prefix-ipv6-format host tramp-postfix-ipv6-format)
               host)
             tramp-postfix-host-format))
-         (when localname localname)))
+         localname))
 
 (defun tramp-get-buffer (vec &optional dont-create)
   "Get the connection buffer to be used for VEC.
@@ -1630,7 +1654,7 @@ version, the function does nothing."
   "Set connection-local variables in the current buffer.
 If connection-local variables are not supported by this Emacs
 version, the function does nothing."
-  (when (file-remote-p default-directory)
+  (when (tramp-tramp-file-p default-directory)
     ;; `hack-connection-local-variables-apply' exists since Emacs 26.1.
     (tramp-compat-funcall
      'hack-connection-local-variables-apply
@@ -1726,29 +1750,10 @@ ARGUMENTS to actually emit the message (if applicable)."
        (setq btf (nth 1 (backtrace-frame btn)))
        (if (not btf)
            (setq fn "")
-         (when (symbolp btf)
-           (setq fn (symbol-name btf))
-           (unless
-               (and
-                (string-match-p "^tramp" fn)
-                (not
-                 (string-match-p
-                  (eval-when-compile
-                    (concat
-                     "^"
-                     (regexp-opt
-                      '("tramp-backtrace"
-                        "tramp-compat-funcall"
-                        "tramp-debug-message"
-                        "tramp-error"
-                        "tramp-error-with-buffer"
-                        "tramp-message"
-                        "tramp-signal-hook-function"
-                        "tramp-user-error")
-                      t)
-                     "$"))
-                  fn)))
-             (setq fn nil)))
+         (and (symbolp btf) (setq fn (symbol-name btf))
+              (or (not (string-match-p "^tramp" fn))
+                  (get btf 'tramp-suppress-trace))
+              (setq fn nil))
          (setq btn (1+ btn))))
       ;; The following code inserts filename and line number.  Should
       ;; be inactive by default, because it is time consuming.
@@ -1763,11 +1768,7 @@ ARGUMENTS to actually emit the message (if applicable)."
     ;; The message.
     (insert (apply #'format-message fmt-string arguments))))
 
-(defvar tramp-message-show-message (null noninteractive)
-  "Show Tramp message in the minibuffer.
-This variable is used to suppress progress reporter output, and
-to disable messages from `tramp-error'.  Those messages are
-visible anyway, because an error is raised.")
+(put #'tramp-debug-message 'tramp-suppress-trace t)
 
 (defsubst tramp-message (vec-or-proc level fmt-string &rest arguments)
   "Emit a message depending on verbosity level.
@@ -1785,7 +1786,7 @@ applicable)."
   (ignore-errors
     (when (<= level tramp-verbose)
       ;; Display only when there is a minimum level.
-      (when (and tramp-message-show-message (<= level 3))
+      (when (<= level 3)
        (apply #'message
               (concat
                (cond
@@ -1817,6 +1818,8 @@ applicable)."
                 (concat (format "(%d) # " level) fmt-string)
                 arguments))))))
 
+(put #'tramp-message 'tramp-suppress-trace t)
+
 (defsubst tramp-backtrace (&optional vec-or-proc)
   "Dump a backtrace into the debug buffer.
 If VEC-OR-PROC is nil, the buffer *debug tramp* is used.  This
@@ -1827,13 +1830,16 @@ function is meant for debugging purposes."
         vec-or-proc 10 "\n%s" (with-output-to-string (backtrace)))
       (with-output-to-temp-buffer "*debug tramp*" (backtrace)))))
 
+(put #'tramp-backtrace 'tramp-suppress-trace t)
+
 (defsubst tramp-error (vec-or-proc signal fmt-string &rest arguments)
   "Emit an error.
 VEC-OR-PROC identifies the connection to use, SIGNAL is the
 signal identifier to be raised, remaining arguments passed to
 `tramp-message'.  Finally, signal SIGNAL is raised with
 FMT-STRING and ARGUMENTS."
-  (let (tramp-message-show-message signal-hook-function)
+  (let ((inhibit-message t)
+       signal-hook-function)
     (tramp-backtrace vec-or-proc)
     (unless arguments
       ;; FMT-STRING could be just a file name, as in
@@ -1851,6 +1857,8 @@ FMT-STRING and ARGUMENTS."
     (signal signal (list (substring-no-properties
                          (apply #'format-message fmt-string arguments))))))
 
+(put #'tramp-error 'tramp-suppress-trace t)
+
 (defsubst tramp-error-with-buffer
   (buf vec-or-proc signal fmt-string &rest arguments)
   "Emit an error, and show BUF.
@@ -1868,13 +1876,13 @@ an input event arrives.  The other arguments are passed 
to `tramp-error'."
          (apply #'tramp-error vec-or-proc signal fmt-string arguments)
        ;; Save exit.
        (when (and buf
-                  tramp-message-show-message
                   (not (zerop tramp-verbose))
                   ;; Do not show when flagged from outside.
-                  (not (tramp-completion-mode-p))
+                  (not non-essential)
                   ;; Show only when Emacs has started already.
                   (current-message))
-         (let ((enable-recursive-minibuffers t))
+         (let ((enable-recursive-minibuffers t)
+               inhibit-message)
            ;; `tramp-error' does not show messages.  So we must do it
            ;; ourselves.
            (apply #'message fmt-string arguments)
@@ -1886,19 +1894,21 @@ an input event arrives.  The other arguments are passed 
to `tramp-error'."
        (when (tramp-file-name-equal-p vec (car tramp-current-connection))
          (setcdr tramp-current-connection (current-time)))))))
 
+(put #'tramp-error-with-buffer 'tramp-suppress-trace t)
+
 ;; We must make it a defun, because it is used earlier already.
 (defun tramp-user-error (vec-or-proc fmt-string &rest arguments)
   "Signal a user error (or \"pilot error\")."
   (unwind-protect
       (apply #'tramp-error vec-or-proc 'user-error fmt-string arguments)
     ;; Save exit.
-    (when (and tramp-message-show-message
-              (not (zerop tramp-verbose))
+    (when (and (not (zerop tramp-verbose))
               ;; Do not show when flagged from outside.
-              (not (tramp-completion-mode-p))
+              (not non-essential)
               ;; Show only when Emacs has started already.
               (current-message))
-      (let ((enable-recursive-minibuffers t))
+      (let ((enable-recursive-minibuffers t)
+           inhibit-message)
        ;; `tramp-error' does not show messages.  So we must do it ourselves.
        (apply #'message fmt-string arguments)
        (discard-input)
@@ -1908,18 +1918,21 @@ an input event arrives.  The other arguments are passed 
to `tramp-error'."
            (tramp-file-name-equal-p vec-or-proc (car tramp-current-connection))
          (setcdr tramp-current-connection (current-time)))))))
 
+(put #'tramp-user-error 'tramp-suppress-trace t)
+
 (defmacro tramp-with-demoted-errors (vec-or-proc format &rest body)
   "Execute BODY while redirecting the error message to `tramp-message'.
 BODY is executed like wrapped by `with-demoted-errors'.  FORMAT
 is a format-string containing a %-sequence meaning to substitute
 the resulting error message."
-  (declare (debug (symbolp body))
-           (indent 2))
+  (declare (indent 2) (debug (symbolp form body)))
   (let ((err (make-symbol "err")))
     `(condition-case-unless-debug ,err
          (progn ,@body)
        (error (tramp-message ,vec-or-proc 3 ,format ,err) nil))))
 
+(put #'tramp-with-demoted-errors 'tramp-suppress-trace t)
+
 ;; This function provides traces in case of errors not triggered by
 ;; Tramp functions.
 (defun tramp-signal-hook-function (error-symbol data)
@@ -1931,6 +1944,8 @@ the resulting error message."
      (car tramp-current-connection) error-symbol
      "%s" (mapconcat (lambda (x) (format "%s" x)) data " "))))
 
+(put #'tramp-signal-hook-function 'tramp-suppress-trace t)
+
 (defmacro with-parsed-tramp-file-name (filename var &rest body)
   "Parse a Tramp filename and make components available in the body.
 
@@ -1947,12 +1962,14 @@ Remaining args are Lisp expressions to be evaluated 
(inside an implicit
 
 If VAR is nil, then we bind `v' to the structure and `method', `user',
 `domain', `host', `port', `localname', `hop' to the components."
+  (declare (indent 2) (debug (form symbolp body)))
   (let ((bindings
-         (mapcar (lambda (elem)
-                   `(,(if var (intern (format "%s-%s" var elem)) elem)
-                     (,(intern (format "tramp-file-name-%s" elem))
-                      ,(or var 'v))))
-                `,(tramp-compat-tramp-file-name-slots))))
+         (mapcar
+         (lambda (elem)
+            `(,(if var (intern (format "%s-%s" var elem)) elem)
+              (,(intern (format "tramp-file-name-%s" elem))
+               ,(or var 'v))))
+         (cdr (mapcar #'car (cl-struct-slot-info 'tramp-file-name))))))
     `(let* ((,(or var 'v) (tramp-dissect-file-name ,filename))
             ,@bindings)
        ;; We don't know which of those vars will be used, so we bind them all,
@@ -1961,8 +1978,6 @@ If VAR is nil, then we bind `v' to the structure and 
`method', `user',
        (ignore ,@(mapcar #'car bindings))
        ,@body)))
 
-(put 'with-parsed-tramp-file-name 'lisp-indent-function 2)
-(put 'with-parsed-tramp-file-name 'edebug-form-spec '(form symbolp body))
 (font-lock-add-keywords 'emacs-lisp-mode 
'("\\<with-parsed-tramp-file-name\\>"))
 
 (defun tramp-progress-reporter-update (reporter &optional value suffix)
@@ -1973,22 +1988,20 @@ If VAR is nil, then we bind `v' to the structure and 
`method', `user',
       (tramp-compat-progress-reporter-update reporter value suffix))))
 
 (defmacro with-tramp-progress-reporter (vec level message &rest body)
-  "Execute BODY, spinning a progress reporter with MESSAGE.
+  "Execute BODY, spinning a progress reporter with MESSAGE in interactive mode.
 If LEVEL does not fit for visible messages, there are only traces
 without a visible progress reporter."
   (declare (indent 3) (debug t))
-  `(progn
+  `(if (or noninteractive inhibit-message)
+       (progn ,@body)
      (tramp-message ,vec ,level "%s..." ,message)
      (let ((cookie "failed")
            (tm
-            ;; We start a pulsing progress reporter after 3 seconds.
-            (when (and tramp-message-show-message
-                       ;; Display only when there is a minimum level.
-                       (<= ,level (min tramp-verbose 3)))
-             (let ((pr (make-progress-reporter ,message nil nil)))
-               (when pr
-                 (run-at-time
-                  3 0.1 #'tramp-progress-reporter-update pr))))))
+            ;; We start a pulsing progress reporter after 3
+            ;; seconds. Display only when there is a minimum level.
+           (when-let ((pr (and (<= ,level (min tramp-verbose 3))
+                               (make-progress-reporter ,message nil nil))))
+             (run-at-time 3 0.1 #'tramp-progress-reporter-update pr))))
        (unwind-protect
            ;; Execute the body.
            (prog1 (progn ,@body) (setq cookie "done"))
@@ -2002,6 +2015,7 @@ without a visible progress reporter."
 (defmacro with-tramp-file-property (vec file property &rest body)
   "Check in Tramp cache for PROPERTY, otherwise execute BODY and set cache.
 FILE must be a local file name on a connection identified via VEC."
+  (declare (indent 3) (debug t))
   `(if (file-name-absolute-p ,file)
       (let ((value (tramp-get-file-property ,vec ,file ,property 'undef)))
        (when (eq value 'undef)
@@ -2013,12 +2027,11 @@ FILE must be a local file name on a connection 
identified via VEC."
        value)
      ,@body))
 
-(put 'with-tramp-file-property 'lisp-indent-function 3)
-(put 'with-tramp-file-property 'edebug-form-spec t)
 (font-lock-add-keywords 'emacs-lisp-mode '("\\<with-tramp-file-property\\>"))
 
 (defmacro with-tramp-connection-property (key property &rest body)
   "Check in Tramp for property PROPERTY, otherwise execute BODY and set."
+  (declare (indent 2) (debug t))
   `(let ((value (tramp-get-connection-property ,key ,property 'undef)))
     (when (eq value 'undef)
       ;; We cannot pass ,@body as parameter to
@@ -2028,8 +2041,6 @@ FILE must be a local file name on a connection identified 
via VEC."
       (tramp-set-connection-property ,key ,property value))
     value))
 
-(put 'with-tramp-connection-property 'lisp-indent-function 2)
-(put 'with-tramp-connection-property 'edebug-form-spec t)
 (font-lock-add-keywords
  'emacs-lisp-mode '("\\<with-tramp-connection-property\\>"))
 
@@ -2048,6 +2059,9 @@ letter into the file name.  This function removes it."
 
 ;;; Config Manipulation Functions:
 
+(defconst tramp-dns-sd-service-regexp "^_[-[:alnum:]]+\\._tcp$"
+  "DNS-SD service regexp.")
+
 (defun tramp-set-completion-function (method function-list)
   "Set the list of completion functions for METHOD.
 FUNCTION-LIST is a list of entries of the form (FUNCTION FILE).
@@ -2080,10 +2094,10 @@ Example:
                          (zerop
                           (tramp-call-process
                            v "reg" nil nil nil "query" (nth 1 (car v))))))
-                   ;; Zeroconf service type.
+                   ;; DNS-SD service type.
                    ((string-match-p
-                     "^_[[:alpha:]]+\\._[[:alpha:]]+$" (nth 1 (car v))))
-                   ;; Configuration file.
+                     tramp-dns-sd-service-regexp (nth 1 (car v))))
+                   ;; Configuration file or empty string.
                    (t (file-exists-p (nth 1 (car v))))))
        (setq r (delete (car v) r)))
       (setq v (cdr v)))
@@ -2249,10 +2263,7 @@ Must be handled by the callers."
              exec-path make-process))
     default-directory)
    ;; PROC.
-   ((member operation
-           '(file-notify-rm-watch
-             ;; Emacs 25+ only.
-             file-notify-valid-p))
+   ((member operation '(file-notify-rm-watch file-notify-valid-p))
     (when (processp (nth 0 args))
       (with-current-buffer (process-buffer (nth 0 args))
        default-directory)))
@@ -2372,7 +2383,7 @@ Fall back to normal file name handler if no Tramp file 
name handler exists."
                           (cons operation args))
                          (tramp-run-real-handler operation args))
                         ((eq result 'suppress)
-                         (let (tramp-message-show-message)
+                         (let ((inhibit-message t))
                            (tramp-message
                             v 1 "Suppress received in operation %s"
                             (cons operation args))
@@ -2401,18 +2412,19 @@ Fall back to normal file name handler if no Tramp file 
name handler exists."
 (defun tramp-completion-file-name-handler (operation &rest args)
   "Invoke Tramp file name completion handler for OPERATION and ARGS.
 Falls back to normal file name handler if no Tramp file name handler exists."
-  (let ((fn (assoc operation tramp-completion-file-name-handler-alist)))
-    (if (and fn tramp-mode)
-       (save-match-data (apply (cdr fn) args))
-      (tramp-run-real-handler operation args))))
+  (if-let
+      ((fn (and tramp-mode
+               (assoc operation tramp-completion-file-name-handler-alist))))
+      (save-match-data (apply (cdr fn) args))
+    (tramp-run-real-handler operation args)))
 
 ;;;###autoload
 (progn (defun tramp-autoload-file-name-handler (operation &rest args)
   "Load Tramp file name handler, and perform OPERATION."
   (tramp-unload-file-name-handlers)
-  (if tramp-mode
-      (let ((default-directory temporary-file-directory))
-       (load "tramp" 'noerror 'nomessage)))
+  (when tramp-mode
+    (let ((default-directory temporary-file-directory))
+      (load "tramp" 'noerror 'nomessage)))
   (apply operation args)))
 
 ;; `tramp-autoload-file-name-handler' must be registered before
@@ -2424,7 +2436,7 @@ Falls back to normal file name handler if no Tramp file 
name handler exists."
   (add-to-list 'file-name-handler-alist
               (cons tramp-autoload-file-name-regexp
                     'tramp-autoload-file-name-handler))
-  (put 'tramp-autoload-file-name-handler 'safe-magic t)))
+  (put #'tramp-autoload-file-name-handler 'safe-magic t)))
 
 ;;;###autoload (tramp-register-autoload-file-name-handlers)
 
@@ -2465,29 +2477,28 @@ remote file names."
   ;; respective foreign handlers.
   (add-to-list 'file-name-handler-alist
               (cons tramp-file-name-regexp #'tramp-file-name-handler))
-  (put 'tramp-file-name-handler 'safe-magic t)
+  (put #'tramp-file-name-handler 'safe-magic t)
 
   (add-to-list 'file-name-handler-alist
               (cons tramp-completion-file-name-regexp
                     #'tramp-completion-file-name-handler))
-  (put 'tramp-completion-file-name-handler 'safe-magic t)
+  (put #'tramp-completion-file-name-handler 'safe-magic t)
   ;; Mark `operations' the handler is responsible for.
-  (put 'tramp-completion-file-name-handler 'operations
+  (put #'tramp-completion-file-name-handler 'operations
        (mapcar #'car tramp-completion-file-name-handler-alist))
 
   (when (bound-and-true-p tramp-archive-enabled)
     (add-to-list 'file-name-handler-alist
                 (cons tramp-archive-file-name-regexp
                       #'tramp-archive-file-name-handler))
-    (put 'tramp-archive-file-name-handler 'safe-magic t))
+    (put #'tramp-archive-file-name-handler 'safe-magic t))
 
   ;; If jka-compr or epa-file are already loaded, move them to the
   ;; front of `file-name-handler-alist'.
   (dolist (fnh '(epa-file-handler jka-compr-handler))
-    (let ((entry (rassoc fnh file-name-handler-alist)))
-      (when entry
-       (setq file-name-handler-alist
-             (cons entry (delete entry file-name-handler-alist)))))))
+    (when-let ((entry (rassoc fnh file-name-handler-alist)))
+      (setq file-name-handler-alist
+           (cons entry (delete entry file-name-handler-alist))))))
 
 (tramp--with-startup (tramp-register-file-name-handlers))
 
@@ -2499,7 +2510,7 @@ Add operations defined in `HANDLER-alist' to 
`tramp-file-name-handler'."
   (add-to-list
    'tramp-foreign-file-name-handler-alist `(,func . ,handler) append)
   ;; Mark `operations' the handler is responsible for.
-  (put 'tramp-file-name-handler
+  (put #'tramp-file-name-handler
        'operations
        (delete-dups
         (append
@@ -2540,19 +2551,6 @@ Add operations defined in `HANDLER-alist' to 
`tramp-file-name-handler'."
 
 ;;; File name handler functions for completion mode:
 
-;;;###autoload
-(defvar tramp-completion-mode nil
-  "If non-nil, external packages signal that they are in file name 
completion.")
-(make-obsolete-variable 'tramp-completion-mode 'non-essential "26.1")
-
-(defun tramp-completion-mode-p ()
-  "Check, whether method / user name / host name completion is active."
-  (or
-   ;; Signal from outside.
-   non-essential
-   ;; This variable has been obsoleted in Emacs 26.
-   tramp-completion-mode))
-
 (defun tramp-connectable-p (vec-or-filename)
   "Check, whether it is possible to connect the remote host w/o side-effects.
 This is true, if either the remote host is already connected, or if we are
@@ -2567,7 +2565,7 @@ not in completion mode."
        ;; `tramp-buffer-name'; otherwise `start-file-process'
        ;; wouldn't run ever when `non-essential' is non-nil.
         (and vec (process-live-p (get-process (tramp-buffer-name vec))))
-       (not (tramp-completion-mode-p)))))
+       (not non-essential))))
 
 ;; Method, host name and user name completion.
 ;; `tramp-completion-dissect-file-name' returns a list of
@@ -2846,7 +2844,7 @@ User is always nil."
   (let ((default-directory (tramp-compat-temporary-file-directory)))
     (when (file-readable-p filename)
       (with-temp-buffer
-       (insert-file-contents filename)
+       (insert-file-contents-literally filename)
        (goto-char (point-min))
         (cl-loop while (not (eobp)) collect (funcall function))))))
 
@@ -2858,7 +2856,7 @@ Either user or host may be nil."
 (defun tramp-parse-rhosts-group ()
    "Return a (user host) tuple allowed to access.
 Either user or host may be nil."
-   (let ((result)
+   (let (result
         (regexp
          (concat
           "^\\(" tramp-host-regexp "\\)"
@@ -2943,7 +2941,7 @@ Host is always \"localhost\"."
 (defun tramp-parse-passwd-group ()
    "Return a (user host) tuple allowed to access.
 Host is always \"localhost\"."
-   (let ((result)
+   (let (result
         (regexp (concat "^\\(" tramp-user-regexp "\\):")))
      (when (re-search-forward regexp (point-at-eol) t)
        (setq result (list (match-string 1) "localhost")))
@@ -2965,7 +2963,7 @@ Host is always \"localhost\"."
 (defun tramp-parse-etc-group-group ()
    "Return a (group host) tuple allowed to access.
 Host is always \"localhost\"."
-   (let ((result)
+   (let (result
         (split (split-string (buffer-substring (point) (point-at-eol)) ":")))
      (when (member (user-login-name) (split-string (nth 3 split) "," 'omit))
        (setq result (list (nth 0 split) "localhost")))
@@ -3002,7 +3000,7 @@ User is always nil."
 (defun tramp-parse-putty-group (registry)
    "Return a (user host) tuple allowed to access.
 User is always nil."
-   (let ((result)
+   (let (result
         (regexp (concat (regexp-quote registry) "\\\\\\(.+\\)")))
      (when (re-search-forward regexp (point-at-eol) t)
        (setq result (list nil (match-string 1))))
@@ -3183,10 +3181,8 @@ User is always nil."
 
 (defun tramp-handle-file-modes (filename)
   "Like `file-modes' for Tramp files."
-  ;; Starting with Emacs 25.1, `when-let' can be used.
-  (let ((attrs (file-attributes (or (file-truename filename) filename))))
-    (when attrs
-      (tramp-mode-string-to-int (tramp-compat-file-attribute-modes attrs)))))
+  (when-let ((attrs (file-attributes (or (file-truename filename) filename))))
+    (tramp-mode-string-to-int (tramp-compat-file-attribute-modes attrs))))
 
 ;; Localname manipulation functions that grok Tramp localnames...
 (defun tramp-handle-file-name-as-directory (file)
@@ -3229,7 +3225,7 @@ User is always nil."
                  ;; lower case letters.  This avoids us to create a
                  ;; temporary file.
                  (while (and (string-match-p
-                              "[a-z]" (tramp-compat-file-local-name candidate))
+                              "[a-z]" (tramp-file-local-name candidate))
                              (not (file-exists-p candidate)))
                    (setq candidate
                          (directory-file-name
@@ -3239,8 +3235,7 @@ User is always nil."
                  ;; to Emacs 26+ like `file-name-case-insensitive-p',
                  ;; so there is no compatibility problem calling it.
                  (unless
-                     (string-match-p
-                      "[a-z]" (tramp-compat-file-local-name candidate))
+                     (string-match-p "[a-z]" (tramp-file-local-name candidate))
                    (setq tmpfile
                          (let ((default-directory
                                  (file-name-directory filename)))
@@ -3253,7 +3248,7 @@ User is always nil."
                      (file-exists-p
                       (concat
                        (file-remote-p candidate)
-                       (upcase (tramp-compat-file-local-name candidate))))
+                       (upcase (tramp-file-local-name candidate))))
                    ;; Cleanup.
                    (when tmpfile (delete-file tmpfile)))))))))))
 
@@ -3305,21 +3300,18 @@ User is always nil."
   (cond
    ((not (file-exists-p file1)) nil)
    ((not (file-exists-p file2)) t)
-   (t (time-less-p (tramp-compat-file-attribute-modification-time
-                   (file-attributes file2))
-                  (tramp-compat-file-attribute-modification-time
-                   (file-attributes file1))))))
+   (t (time-less-p
+       (tramp-compat-file-attribute-modification-time (file-attributes file2))
+       (tramp-compat-file-attribute-modification-time
+       (file-attributes file1))))))
 
 (defun tramp-handle-file-regular-p (filename)
   "Like `file-regular-p' for Tramp files."
   (and (file-exists-p filename)
        ;; Sometimes, `file-attributes' does not return a proper value
        ;; even if `file-exists-p' does.
-       (ignore-errors
-        (eq ?-
-            (aref
-             (tramp-compat-file-attribute-modes (file-attributes filename))
-             0)))))
+       (when-let ((attr (file-attributes filename)))
+        (eq ?- (aref (tramp-compat-file-attribute-modes attr) 0)))))
 
 (defun tramp-handle-file-remote-p (filename &optional identification connected)
   "Like `file-remote-p' for Tramp files."
@@ -3358,8 +3350,7 @@ User is always nil."
   "Like `file-truename' for Tramp files."
   ;; Preserve trailing "/".
   (funcall
-   (if (tramp-compat-directory-name-p filename)
-       #'file-name-as-directory #'identity)
+   (if (directory-name-p filename) #'file-name-as-directory #'identity)
    ;; Quote properly.
    (funcall
     (if (tramp-compat-file-name-quoted-p filename)
@@ -3395,7 +3386,7 @@ User is always nil."
               (tramp-error
                v1 'file-error
                "Maximum number (%d) of symlinks exceeded" numchase-limit)))
-          (tramp-compat-file-local-name (directory-file-name result)))))))))
+          (tramp-file-local-name (directory-file-name result)))))))))
 
 (defun tramp-handle-file-writable-p (filename)
   "Like `file-writable-p' for Tramp files."
@@ -3430,7 +3421,7 @@ User is always nil."
   "Like `insert-directory' for Tramp files."
   (unless switches (setq switches ""))
   ;; Mark trailing "/".
-  (when (and (tramp-compat-directory-name-p filename)
+  (when (and (directory-name-p filename)
             (not full-directory-p))
     (setq switches (concat switches "F")))
   ;; Check, whether directory is accessible.
@@ -3564,8 +3555,8 @@ User is always nil."
        ;; Save exit.
        (progn
          (when visit
-           (setq buffer-file-name filename)
-           (setq buffer-read-only (not (file-writable-p filename)))
+           (setq buffer-file-name filename
+                 buffer-read-only (not (file-writable-p filename)))
            (set-visited-file-modtime)
            (set-buffer-modified-p nil))
          (when (and (stringp local-copy)
@@ -3599,7 +3590,7 @@ User is always nil."
        v tramp-file-missing "Cannot load nonexistent file `%s'" file))
     (if (not (file-exists-p file))
        nil
-      (let ((tramp-message-show-message (not nomessage)))
+      (let ((inhibit-message nomessage))
        (with-tramp-progress-reporter v 0 (format "Loading %s" file)
          (let ((local-copy (file-local-copy file)))
            (unwind-protect
@@ -3627,10 +3618,16 @@ support symbolic links."
   (let* ((asynchronous (string-match-p "[ \t]*&[ \t]*\\'" command))
         (command (substring command 0 asynchronous))
         current-buffer-p
+        (output-buffer-p output-buffer)
         (output-buffer
          (cond
-          ((bufferp output-buffer) output-buffer)
-          ((stringp output-buffer) (get-buffer-create output-buffer))
+          ((bufferp output-buffer)
+           (setq current-buffer-p (eq (current-buffer) output-buffer))
+           output-buffer)
+          ((stringp output-buffer)
+           (setq current-buffer-p
+                 (eq (buffer-name (current-buffer)) output-buffer))
+           (get-buffer-create output-buffer))
           (output-buffer
            (setq current-buffer-p t)
            (current-buffer))
@@ -3642,13 +3639,19 @@ support symbolic links."
          (cond
           ((bufferp error-buffer) error-buffer)
           ((stringp error-buffer) (get-buffer-create error-buffer))))
+        (error-file
+         (and error-buffer
+              (with-parsed-tramp-file-name default-directory nil
+                (tramp-make-tramp-file-name
+                 v (tramp-make-tramp-temp-file v)))))
         (bname (buffer-name output-buffer))
         (p (get-buffer-process output-buffer))
+        (dir default-directory)
         buffer)
 
     ;; The following code is taken from `shell-command', slightly
     ;; adapted.  Shouldn't it be factored out?
-    (when p
+    (when (and (integerp asynchronous) p)
       (cond
        ((eq async-shell-command-buffer 'confirm-kill-process)
        ;; If will kill a process, query first.
@@ -3680,22 +3683,25 @@ support symbolic links."
          (rename-uniquely))
         (setq output-buffer (get-buffer-create bname)))))
 
-    (setq buffer (if (and (not asynchronous) error-buffer)
-                    (with-parsed-tramp-file-name default-directory nil
-                      (list output-buffer
-                            (tramp-make-tramp-file-name
-                             v (tramp-make-tramp-temp-file v))))
-                  output-buffer))
-
-    (if current-buffer-p
-       (progn
-         (barf-if-buffer-read-only)
-         (push-mark nil t))
+    (unless output-buffer-p
       (with-current-buffer output-buffer
+       (setq default-directory dir)))
+
+    (setq buffer (if error-file (list output-buffer error-file) output-buffer))
+
+    (with-current-buffer output-buffer
+      (when current-buffer-p
+       (barf-if-buffer-read-only)
+       (push-mark nil t))
+      ;; `shell-command-save-pos-or-erase' has been introduced with
+      ;; Emacs 27.1.
+      (if (fboundp 'shell-command-save-pos-or-erase)
+         (tramp-compat-funcall
+          'shell-command-save-pos-or-erase current-buffer-p)
        (setq buffer-read-only nil)
        (erase-buffer)))
 
-    (if (and (not current-buffer-p) (integerp asynchronous))
+    (if (integerp asynchronous)
        (let ((tramp-remote-process-environment
               ;; `async-shell-command-width' has been introduced with
               ;; Emacs 27.1.
@@ -3708,42 +3714,67 @@ support symbolic links."
              ;; Run the process.
              (setq p (start-file-process-shell-command
                       (buffer-name output-buffer) buffer command))
-           ;; Display output.
-           (with-current-buffer output-buffer
-             (display-buffer output-buffer '(nil (allow-no-window . t)))
-             (setq mode-line-process '(":%s"))
-             (shell-mode)
-             (set-process-sentinel p #'shell-command-sentinel)
-             (set-process-filter p #'comint-output-filter))))
+           ;; Insert error messages if they were separated.
+           (when error-file
+             (with-current-buffer error-buffer
+               (insert-file-contents-literally error-file)))
+           (if (process-live-p p)
+             ;; Display output.
+             (with-current-buffer output-buffer
+               (display-buffer output-buffer '(nil (allow-no-window . t)))
+               (setq mode-line-process '(":%s"))
+               (shell-mode)
+               (set-process-filter p #'comint-output-filter)
+               (set-process-sentinel p #'shell-command-sentinel)
+               (when error-file
+                 (add-function
+                  :after (process-sentinel p)
+                  (lambda (_proc _string)
+                    (with-current-buffer error-buffer
+                      (insert-file-contents-literally
+                       error-file nil nil nil 'replace))
+                    (delete-file error-file)))))
+
+             (when error-file
+               (delete-file error-file)))))
 
       (prog1
          ;; Run the process.
          (process-file-shell-command command nil buffer nil)
        ;; Insert error messages if they were separated.
-       (when (listp buffer)
+       (when error-file
          (with-current-buffer error-buffer
-           (insert-file-contents (cadr buffer)))
-         (delete-file (cadr buffer)))
+           (insert-file-contents-literally error-file))
+         (delete-file error-file))
        (if current-buffer-p
            ;; This is like exchange-point-and-mark, but doesn't
            ;; activate the mark.  It is cleaner to avoid activation,
            ;; even though the command loop would deactivate the mark
            ;; because we inserted text.
-           (goto-char (prog1 (mark t)
-                        (set-marker (mark-marker) (point)
-                                    (current-buffer))))
+           (progn
+             (goto-char (prog1 (mark t)
+                          (set-marker (mark-marker) (point)
+                                      (current-buffer))))
+              ;; `shell-command-set-point-after-cmd' has been
+             ;; introduced with Emacs 27.1.
+             (if (fboundp 'shell-command-set-point-after-cmd)
+                 (tramp-compat-funcall
+                  'shell-command-set-point-after-cmd)))
          ;; There's some output, display it.
          (when (with-current-buffer output-buffer (> (point-max) (point-min)))
            (display-message-or-buffer output-buffer)))))))
 
 (defun tramp-handle-start-file-process (name buffer program &rest args)
-  "Like `start-file-process' for Tramp files."
+  "Like `start-file-process' for Tramp files.
+BUFFER might be a list, in this case STDERR is separated."
   ;; `make-process' knows the `:file-handler' argument since Emacs 27.1 only.
   (tramp-file-name-handler
    'make-process
    :name name
-   :buffer buffer
+   :buffer (if (consp buffer) (car buffer) buffer)
    :command (and program (cons program args))
+   ;; `shell-command' adds an errfile to `buffer'.
+   :stderr (when (consp buffer) (cadr buffer))
    :noquery nil
    :file-handler t))
 
@@ -3780,10 +3811,10 @@ support symbolic links."
        filename))))
 
 (defconst tramp-time-dont-know '(0 0 0 1000)
-  "An invalid time value, used as \"Don’t know\" value.")
+  "An invalid time value, used as \"Don't know\" value.")
 
 (defconst tramp-time-doesnt-exist '(-1 65535)
-  "An invalid time value, used as \"Doesn’t exist\" value.")
+  "An invalid time value, used as \"Doesn't exist\" value.")
 
 (defun tramp-handle-set-visited-file-modtime (&optional time-list)
   "Like `set-visited-file-modtime' for Tramp files."
@@ -4065,9 +4096,9 @@ See `tramp-process-actions' for the format of ACTIONS."
       (while (tramp-accept-process-output proc 0))
       (setq todo actions)
       (while todo
-       (setq item (pop todo))
-       (setq pattern (format "\\(%s\\)\\'" (symbol-value (nth 0 item))))
-       (setq action (nth 1 item))
+       (setq item (pop todo)
+             pattern (format "\\(%s\\)\\'" (symbol-value (nth 0 item)))
+             action (nth 1 item))
        (tramp-message
         vec 5 "Looking for regexp \"%s\" from remote shell" pattern)
        (when (tramp-check-for-regexp proc pattern)
@@ -4117,9 +4148,8 @@ performed successfully.  Any other value means an error."
                      (catch 'tramp-action
                        (tramp-process-one-action proc vec actions)))))
          (while (not exit)
-           (setq exit
-                 (catch 'tramp-action
-                   (tramp-process-one-action proc vec actions)))))
+           (setq exit (catch 'tramp-action
+                        (tramp-process-one-action proc vec actions)))))
        (with-current-buffer (tramp-get-connection-buffer vec)
          (widen)
          (tramp-message vec 6 "\n%s" (buffer-string)))
@@ -4344,7 +4374,7 @@ would yield t.  On the other hand, the following check 
results in nil:
   (tramp-equal-remote \"/sudo::/etc\" \"/su::/etc\")
 
 If both files are local, the function returns t."
-  (or (and (null (file-remote-p file1)) (null (file-remote-p file2)))
+  (or (and (null (tramp-tramp-file-p file1)) (null (tramp-tramp-file-p file2)))
       (and (tramp-tramp-file-p file1) (tramp-tramp-file-p file2)
           (string-equal (file-remote-p file1) (file-remote-p file2)))))
 
@@ -4437,9 +4467,9 @@ This is used to map a mode number to a permission 
string.")
        (suid   (> (logand (ash mode -9) 4) 0))
        (sgid   (> (logand (ash mode -9) 2) 0))
        (sticky (> (logand (ash mode -9) 1) 0)))
-    (setq user  (tramp-file-mode-permissions user  suid "s"))
-    (setq group (tramp-file-mode-permissions group sgid "s"))
-    (setq other (tramp-file-mode-permissions other sticky "t"))
+    (setq user  (tramp-file-mode-permissions user  suid "s")
+         group (tramp-file-mode-permissions group sgid "s")
+         other (tramp-file-mode-permissions other sticky "t"))
     (concat type user group other)))
 
 (defun tramp-file-mode-permissions (perm suid suid-text)
@@ -4469,16 +4499,15 @@ If FILENAME is remote, a file name handler is called."
     (when (and modes (not (zerop (logand modes #o2000))))
       (setq gid (tramp-compat-file-attribute-group-id (file-attributes dir)))))
 
-  (let ((handler (find-file-name-handler filename 'tramp-set-file-uid-gid)))
-    (if handler
-       (funcall handler #'tramp-set-file-uid-gid filename uid gid)
-      ;; On W32 systems, "chown" does not work.
-      (unless (memq system-type '(ms-dos windows-nt))
-       (let ((uid (or (and (natnump uid) uid) (tramp-get-local-uid 'integer)))
-             (gid (or (and (natnump gid) gid) (tramp-get-local-gid 'integer))))
-         (tramp-call-process
-          nil "chown" nil nil nil (format "%d:%d" uid gid)
-          (tramp-unquote-shell-quote-argument filename)))))))
+  (if-let ((handler (find-file-name-handler filename 'tramp-set-file-uid-gid)))
+      (funcall handler #'tramp-set-file-uid-gid filename uid gid)
+    ;; On W32 systems, "chown" does not work.
+    (unless (memq system-type '(ms-dos windows-nt))
+      (let ((uid (or (and (natnump uid) uid) (tramp-get-local-uid 'integer)))
+           (gid (or (and (natnump gid) gid) (tramp-get-local-gid 'integer))))
+       (tramp-call-process
+        nil "chown" nil nil nil (format "%d:%d" uid gid)
+        (tramp-unquote-shell-quote-argument filename))))))
 
 (defun tramp-get-local-uid (id-format)
   "The uid of the local user, in ID-FORMAT.
@@ -4614,7 +4643,7 @@ This handles also chrooted environments, which are not 
regarded as local."
           (tramp-make-tramp-file-name
            vec (or (tramp-get-method-parameter vec 'tramp-tmpdir) "/tmp"))))
       (or (and (file-directory-p dir) (file-writable-p dir)
-              (tramp-compat-file-local-name dir))
+              (tramp-file-local-name dir))
          (tramp-error vec 'file-error "Directory %s not accessible" dir))
       dir)))
 
@@ -4637,7 +4666,7 @@ Return the local name of the temporary file."
        (set-file-modes result #o0700)))
 
     ;; Return the local part.
-    (with-parsed-tramp-file-name result nil localname)))
+    (tramp-file-local-name result)))
 
 (defun tramp-delete-temp-file-function ()
   "Remove temporary files related to current buffer."
@@ -4664,7 +4693,7 @@ this file, if that variable is non-nil."
 
   (let ((system-type
         (if (and (stringp tramp-auto-save-directory)
-                 (file-remote-p tramp-auto-save-directory))
+                 (tramp-tramp-file-p tramp-auto-save-directory))
             'not-windows
           system-type))
        (auto-save-file-name-transforms
@@ -4802,6 +4831,19 @@ verbosity of 6."
     (tramp-message vec 6 "%s" result)
     result))
 
+(defun tramp-process-running-p (process-name)
+  "Return t if system process PROCESS-NAME is running for `user-login-name'."
+  (when (stringp process-name)
+    (catch 'result
+      (dolist (pid (tramp-compat-funcall 'list-system-processes))
+       (let ((attributes (process-attributes pid)))
+         (and (string-equal (cdr (assoc 'user attributes)) (user-login-name))
+               (when-let ((comm (cdr (assoc 'comm attributes))))
+                 ;; The returned command name could be truncated to 15
+                 ;; characters.  Therefore, we cannot check for `string-equal'.
+                (string-prefix-p comm process-name))
+              (throw 'result t)))))))
+
 (defun tramp-read-passwd (proc &optional prompt)
   "Read a password from user (compat function).
 Consults the auth-source package.
@@ -5022,10 +5064,4 @@ name of a process or buffer, or nil to default to the 
current buffer."
 ;;   `start-file-process-shell-command', which is sufficient due to
 ;;   connection-local `shell-file-name'.
 
-
 ;;; tramp.el ends here
-
-;; Local Variables:
-;; mode: Emacs-Lisp
-;; coding: utf-8
-;; End:
diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el
index e5f628d..0a92e0d 100644
--- a/lisp/net/trampver.el
+++ b/lisp/net/trampver.el
@@ -35,11 +35,8 @@
 ;; Emacs version check is defined in macro AC_EMACS_INFO of
 ;; aclocal.m4; should be changed only there.
 
-;; Needed for Emacs 24.
-(defvar inhibit-message)
-
 ;;;###tramp-autoload
-(defconst tramp-version "2.4.3"
+(defconst tramp-version "2.5.0-pre"
   "This version of Tramp.")
 
 ;;;###tramp-autoload
@@ -71,9 +68,9 @@
   "The repository revision of the Tramp sources.")
 
 ;; Check for Emacs version.
-(let ((x   (if (not (string-lessp emacs-version "24.4"))
+(let ((x   (if (not (string-lessp emacs-version "25.1"))
       "ok"
-    (format "Tramp 2.4.3 is not fit for %s"
+    (format "Tramp 2.5.0-pre is not fit for %s"
             (replace-regexp-in-string "\n" "" (emacs-version))))))
   (unless (string-equal "ok" x) (error "%s" x)))
 
@@ -92,7 +89,8 @@
         ("2.2.13.25.1" . "25.1") ("2.2.13.25.2" . "25.2")
         ("2.2.13.25.2" . "25.3")
          ("2.3.3" . "26.1") ("2.3.3.26.1" . "26.1") ("2.3.5.26.2" . "26.2")
-         ("2.3.5.26.3" . "26.3")))
+         ("2.3.5.26.3" . "26.3")
+         ("2.4.3.27.1" . "27.1")))
 
 (add-hook 'tramp-unload-hook
          (lambda ()
@@ -101,8 +99,3 @@
 (provide 'trampver)
 
 ;;; trampver.el ends here
-
-;; Local Variables:
-;; mode: Emacs-Lisp
-;; coding: utf-8
-;; End:
diff --git a/lisp/obsolete/cust-print.el b/lisp/obsolete/cust-print.el
index fbf8069..40532ea 100644
--- a/lisp/obsolete/cust-print.el
+++ b/lisp/obsolete/cust-print.el
@@ -156,10 +156,7 @@ If nil, printing proceeds recursively and may lead to
 If non-nil, shared substructures anywhere in the structure are printed
 with `#N=' before the first occurrence (in the order of the print
 representation) and `#N#' in place of each subsequent occurrence,
-where N is a positive decimal integer.
-
-There is no way to read this representation in standard Emacs,
-but if you need to do so, try the cl-read.el package."
+where N is a positive decimal integer."
   :type 'boolean
   :group 'cust-print)
 
diff --git a/lisp/obsolete/iswitchb.el b/lisp/obsolete/iswitchb.el
index 350eabd..96b063b 100644
--- a/lisp/obsolete/iswitchb.el
+++ b/lisp/obsolete/iswitchb.el
@@ -1393,7 +1393,7 @@ Copied from `icomplete-tidy'."
   "Move the summaries to the end of the list.
 This is an example function which can be hooked on to
 `iswitchb-make-buflist-hook'.  Any buffer matching the regexps
-`Summary' or `output\*$'are put to the end of the list."
+`Summary' or `output\\*$'are put to the end of the list."
   (let ((summaries (delq nil
                         (mapcar
                          (lambda (x)
diff --git a/lisp/obsolete/old-whitespace.el b/lisp/obsolete/old-whitespace.el
index 95010c0..2f46d7d 100644
--- a/lisp/obsolete/old-whitespace.el
+++ b/lisp/obsolete/old-whitespace.el
@@ -383,10 +383,10 @@ To disable timer scans, set this to zero."
 (defun whitespace-buffer (&optional quiet)
   "Find five different types of white spaces in buffer.
 These are:
-1. Leading space \(empty lines at the top of a file\).
-2. Trailing space \(empty lines at the end of a file\).
-3. Indentation space \(8 or more spaces, that should be replaced with TABS\).
-4. Spaces followed by a TAB. \(Almost always, we never want that\).
+1. Leading space \(empty lines at the top of a file).
+2. Trailing space \(empty lines at the end of a file).
+3. Indentation space \(8 or more spaces, that should be replaced with TABS).
+4. Spaces followed by a TAB. \(Almost always, we never want that).
 5. Spaces or TABS at the end of a line.
 
 Check for whitespace only if this buffer really contains a non-empty file
diff --git a/lisp/obsolete/rcompile.el b/lisp/obsolete/rcompile.el
index 5ef8be2..6d95b71 100644
--- a/lisp/obsolete/rcompile.el
+++ b/lisp/obsolete/rcompile.el
@@ -89,7 +89,7 @@ nil means use the value returned by \\[user-login-name]."
   "Command to run before compilation.
 This can be used for setting up environment variables,
 since rsh does not invoke the shell as a login shell and files like .login
-\(tcsh\) and .bash_profile \(bash\) are not run.
+\(tcsh) and .bash_profile \(bash) are not run.
 nil means run no commands."
   :type '(choice string (const nil))
   :group 'remote-compile)
diff --git a/lisp/obsolete/sb-image.el b/lisp/obsolete/sb-image.el
new file mode 100644
index 0000000..fd88847
--- /dev/null
+++ b/lisp/obsolete/sb-image.el
@@ -0,0 +1,46 @@
+;;; sb-image --- Image management for speedbar
+
+;; Copyright (C) 1999-2003, 2005-2019 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <address@hidden>
+;; Keywords: file, tags, tools
+;; Obsolete-since: 28.1
+
+;; 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 is obsolete.
+;;
+;; Supporting Image display for Emacs 20 and less, Emacs 21, and XEmacs,
+;; is a challenging task, which doesn't take kindly to being byte compiled.
+;; When sharing speedbar.elc between these three applications, the Image
+;; support can get lost.
+;;
+;; By splitting out that hard part into this file, and avoiding byte
+;; compilation, one copy speedbar can support all these platforms together.
+;;
+;; This file requires the `image' package if it is available.
+
+(require 'ezimage)
+
+;;; Code:
+
+(defalias 'defimage-speedbar 'defezimage)
+
+(provide 'sb-image)
+
+;;; sb-image.el ends here
diff --git a/lisp/obsolete/vc-arch.el b/lisp/obsolete/vc-arch.el
index 0b70927..b186a5c 100644
--- a/lisp/obsolete/vc-arch.el
+++ b/lisp/obsolete/vc-arch.el
@@ -5,6 +5,7 @@
 ;; Author:      FSF (see vc.el for full credits)
 ;; Maintainer:  Stefan Monnier <address@hidden>
 ;; Package: vc
+;; Obsolete-since: 25.1
 
 ;; This file is part of GNU Emacs.
 
diff --git a/lisp/obsolete/vi.el b/lisp/obsolete/vi.el
index df5ddfd..eee00b4 100644
--- a/lisp/obsolete/vi.el
+++ b/lisp/obsolete/vi.el
@@ -1225,7 +1225,7 @@ SPECIAL FEATURE: char argument can be used to specify 
shift amount(1-9)."
 (defun vi-end-of-blank-delimited-word (count)
   "Forward to the end of the COUNT'th blank-delimited word."
   (interactive "p")
-  (if (re-search-forward "[^ \t\n\']+[ \t\n\']" nil t count)
+  (if (re-search-forward "[^ \t\n']+[ \t\n']" nil t count)
       (if (not (eobp)) (backward-char 2))))
 
 (defun vi-home-window-line (arg)
diff --git a/lisp/obsolete/vip.el b/lisp/obsolete/vip.el
index 4a9b8ff..37defd1 100644
--- a/lisp/obsolete/vip.el
+++ b/lisp/obsolete/vip.el
@@ -80,7 +80,7 @@
 
 (defvar vip-current-major-mode nil
   "vip-current-major-mode is the major-mode vi considers it is now.
-\(buffer specific\)")
+\(buffer specific)")
 
 (make-variable-buffer-local 'vip-current-major-mode)
 
@@ -1510,7 +1510,7 @@ used.  This behavior is controlled by the sign of prefix 
numeric value."
               (* (/ (point-max) 100) arg)
             (/ (* (point-max) arg) 100)))
          (back-to-indentation))
-    (cond ((looking-at "[\(\[{]")
+    (cond ((looking-at "[([{]")
           (if com (move-marker vip-com-point (point)))
           (forward-sexp 1)
           (if com
@@ -1719,7 +1719,7 @@ STRING.  Search will be forward if FORWARD, otherwise 
backward."
   (let (buffer)
     (setq buffer
          (read-buffer
-          (format "switch to buffer \(%s\): "
+          (format "switch to buffer (%s): "
                   (buffer-name (other-buffer (current-buffer))))))
     (switch-to-buffer buffer)
     (vip-change-mode-to-vi)))
@@ -1730,7 +1730,7 @@ STRING.  Search will be forward if FORWARD, otherwise 
backward."
   (let (buffer)
     (setq buffer
          (read-buffer
-          (format "Switch to buffer \(%s\): "
+          (format "Switch to buffer (%s): "
                   (buffer-name (other-buffer (current-buffer))))))
     (switch-to-buffer-other-window buffer)
     (vip-change-mode-to-vi)))
@@ -1741,7 +1741,7 @@ STRING.  Search will be forward if FORWARD, otherwise 
backward."
   (let (buffer buffer-name)
     (setq buffer-name
          (read-buffer
-          (format "Kill buffer \(%s\): "
+          (format "Kill buffer (%s): "
                   (buffer-name (current-buffer)))))
     (setq buffer
          (if (null buffer-name)
@@ -2162,7 +2162,7 @@ is a command.")
 
 (defun vip-get-ex-token ()
   "get an ex-token which is either an address or a command.
-a token has type \(command, address, end-mark\) and value."
+a token has type \(command, address, end-mark) and value."
   (with-current-buffer " *ex-working-space*"
     (skip-chars-forward " \t")
     (cond ((looking-at "[k#]")
@@ -2668,7 +2668,7 @@ a token has type \(command, address, end-mark\) and 
value."
   "ex-edit"
   (vip-get-ex-file)
   (if (and (not ex-variant) (buffer-modified-p) buffer-file-name)
-      (error "No write since last change \(:e! overrides\)"))
+      (error "No write since last change (:e! overrides)"))
   (vip-change-mode-to-emacs)
   (set-buffer
    (find-file-noselect (concat default-directory ex-file)))
diff --git a/lisp/org/ol.el b/lisp/org/ol.el
index baed23b..c9e4da5 100644
--- a/lisp/org/ol.el
+++ b/lisp/org/ol.el
@@ -845,8 +845,8 @@ E.g. \"%C3%B6\" becomes the german o-Umlaut."
     (insert link)
     (insert (make-string (- (skip-chars-backward "\\\\"))
                         ?\\))
-    (while (search-backward "\]" nil t)
-      (when (looking-at-p "\\]\\(?:[][]\\|\\'\\)")
+    (while (search-backward "]" nil t)
+      (when (looking-at-p "]\\(?:[][]\\|\\'\\)")
        (insert (make-string (1+ (- (skip-chars-backward "\\\\")))
                             ?\\))))
     (buffer-string)))
diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el
index ceaa816..5fe140d 100644
--- a/lisp/org/org-agenda.el
+++ b/lisp/org/org-agenda.el
@@ -8981,7 +8981,6 @@ fold drawers."
         (narrow-to-region (org-entry-beginning-position)
                           (org-entry-end-position))
         (org-show-all '(drawers))))
-      (when arg )
       (setq org-agenda-show-window (selected-window)))
     (select-window win)))
 
diff --git a/lisp/org/org-element.el b/lisp/org/org-element.el
index 4b5f9a1..be74dfd 100644
--- a/lisp/org/org-element.el
+++ b/lisp/org/org-element.el
@@ -4892,7 +4892,7 @@ with `org-element--cache-compare'.  This cache is used in
 
 A request is a vector with the following pattern:
 
- \[NEXT BEG END OFFSET PARENT PHASE]
+ [NEXT BEG END OFFSET PARENT PHASE]
 
 Processing a synchronization request consists of three phases:
 
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 5c8b02b..1581625 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -11410,8 +11410,8 @@ D      Show deadlines and scheduled items between a 
date range."
   (setq type (or type org-sparse-tree-default-date-type))
   (setq org-ts-type type)
   (message "Sparse tree: [r]egexp [t]odo [T]odo-kwd [m]atch [p]roperty
-             \[d]eadlines [b]efore-date [a]fter-date [D]ates range
-             \[c]ycle through date types: %s"
+             [d]eadlines [b]efore-date [a]fter-date [D]ates range
+             [c]ycle through date types: %s"
           (cl-case type
             (all "all timestamps")
             (scheduled "only scheduled")
diff --git a/lisp/org/ox-odt.el b/lisp/org/ox-odt.el
index 51cb42a..a148631 100644
--- a/lisp/org/ox-odt.el
+++ b/lisp/org/ox-odt.el
@@ -940,7 +940,7 @@ See `org-odt--build-date-styles' for implementation 
details."
         (has-time-p (or (not timestamp)
                         (org-timestamp-has-time-p timestamp)))
         (iso-date (let ((format (if has-time-p "%Y-%m-%dT%H:%M:%S"
-                                  "%Y-%m-%dT%H:%M:%S")))
+                                  "%Y-%m-%d")))
                     (funcall format-timestamp timestamp format end))))
     (if iso-date-p iso-date
       (let* ((style (if has-time-p "OrgDate2" "OrgDate1"))
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index 1071191..a608122 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -512,11 +512,11 @@ function to control that."
        (let ((src (default-value 'post-self-insert-hook)))
          (while src
            (unless (memq (car src) c--unsafe-post-self-insert-hook-functions)
-             (add-hook 'dest (car src) t)) ; Preserve the order of the 
functions.
+             (push (car src) dest))
            (setq src (cdr src)))))
-       (t (add-hook 'dest (car src) t))) ; Preserve the order of the functions.
+       (t (push (car src) dest)))
       (setq src (cdr src)))
-    (run-hooks 'dest)))
+    (mapc #'funcall (nreverse dest)))) ; Preserve the order of the functions.
 
 (defmacro c--call-post-self-insert-hook-more-safely ()
   ;; Call post-self-insert-hook, if such exists.  See comment for
@@ -2024,6 +2024,23 @@ other top level construct with a brace block."
             (c-backward-syntactic-ws)
             (point))))
 
+        ((and (c-major-mode-is 'objc-mode) (looking-at "[-+]\\s-*("))     ; 
Objective-C method
+         ;; Move to the beginning of the method name.
+         (c-forward-token-2 2 t)
+         (let* ((class
+                 (save-excursion
+                   (when (re-search-backward
+                          
"^\\s-*@\\(implementation\\|class\\|interface\\)\\s-+\\(\\sw+\\)" nil t)
+                     (match-string-no-properties 2))))
+                (limit (save-excursion (re-search-forward "[;{]" nil t)))
+                (method (when (re-search-forward "\\(\\sw+:?\\)" limit t)
+                          (match-string-no-properties 1))))
+           (when (and class method)
+             ;; Add the parameter labels onto name.  They always end in ':'.
+             (while (re-search-forward "\\(\\sw+:\\)" limit 1)
+               (setq method (concat method (match-string-no-properties 1))))
+             (concat "[" class " " method "]"))))
+
         (t                             ; Normal function or initializer.
          (when (looking-at c-defun-type-name-decl-key) ; struct, etc.
            (goto-char (match-end 0))
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index b50e7e7..715af32 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -2055,11 +2055,10 @@ the appropriate place for that."
   "Keywords that might act as prefixes for primitive types.  Assumed to
 be a subset of `c-primitive-type-kwds'."
   t       nil
-  (c c++) '("long" "short" "signed" "unsigned")
-  idl     '("long" "unsigned"
+  (c c++ objc) '("long" "short" "signed" "unsigned")
+  idl    '("long" "unsigned"
            ;; In CORBA PSDL:
            "strong"))
-
 (c-lang-defconst c-typedef-kwds
   "Prefix keyword(s) like \"typedef\" which make a type declaration out
 of a variable declaration."
diff --git a/lisp/progmodes/cc-menus.el b/lisp/progmodes/cc-menus.el
index 9c8c7ab..97037de 100644
--- a/lisp/progmodes/cc-menus.el
+++ b/lisp/progmodes/cc-menus.el
@@ -45,6 +45,7 @@
 (cc-bytecomp-defvar imenu-case-fold-search)
 (cc-bytecomp-defvar imenu-generic-expression)
 (cc-bytecomp-defvar imenu-create-index-function)
+(cc-bytecomp-defun c-literal-limits)
 
 
 ;; imenu integration
@@ -437,55 +438,56 @@ Example:
     (goto-char (point-max))
     ;;
     (while (re-search-backward cc-imenu-objc-generic-expression nil t)
-      (setq langnum (if (match-beginning OBJC)
-                       OBJC
-                     (cond
-                      ((match-beginning Cproto) Cproto)
-                      ((match-beginning Cgeneralfunc) Cgeneralfunc)
-                      ((match-beginning Cnoreturn) Cnoreturn))))
-      (setq str (funcall func (match-beginning langnum) (match-end langnum)))
-      ;;
-      (cond
-       ;;
-       ;; C
-       ;;
-       ((not (eq langnum OBJC))
-       (setq clist (cons (cons str (match-beginning langnum)) clist)))
-       ;;
-       ;; ObjC
-       ;;
-       ;; An instance Method
-       ((eq (aref str 0) ?-)
-       (setq str (concat "-" (cc-imenu-objc-method-to-selector str)))
-       (setq methodlist (cons (cons str
-                             (match-beginning langnum))
-                       methodlist)))
-       ;; A factory Method
-       ((eq (aref str 0) ?+)
-       (setq str (concat "+" (cc-imenu-objc-method-to-selector str)))
-       (setq methodlist (cons (cons str
-                             (match-beginning langnum))
-                       methodlist)))
-       ;; Interface or implementation or protocol
-       ((eq (aref str 0) ?@)
-       (setq classcount (1+ classcount))
+      (when (not (c-literal-limits))
+       (setq langnum (if (match-beginning OBJC)
+                         OBJC
+                       (cond
+                        ((match-beginning Cproto) Cproto)
+                        ((match-beginning Cgeneralfunc) Cgeneralfunc)
+                        ((match-beginning Cnoreturn) Cnoreturn))))
+       (setq str (funcall func (match-beginning langnum) (match-end langnum)))
+       ;;
        (cond
-        ((and (> (length str) implen)
-              (string= (substring  str 0 implen) "@implementation"))
-         (setq str (substring str implen)
-               str2 "@implementation"))
-        ((string= (substring  str 0 intflen) "@interface")
-         (setq str (substring str intflen)
-               str2 "@interface"))
-        ((string= (substring  str 0 prtlen) "@protocol")
-         (setq str (substring str prtlen)
-               str2 "@protocol")))
-       (setq str (cc-imenu-objc-remove-white-space str))
-       (setq methodlist (cons (cons str2
-                                    (match-beginning langnum))
-                              methodlist))
-       (setq toplist (cons (cons str methodlist) toplist)
-             methodlist nil))))
+        ;;
+        ;; C
+        ;;
+        ((not (eq langnum OBJC))
+         (setq clist (cons (cons str (match-beginning langnum)) clist)))
+        ;;
+        ;; ObjC
+        ;;
+        ;; An instance Method
+        ((eq (aref str 0) ?-)
+         (setq str (concat "-" (cc-imenu-objc-method-to-selector str)))
+         (setq methodlist (cons (cons str
+                                      (match-beginning langnum))
+                                methodlist)))
+        ;; A factory Method
+        ((eq (aref str 0) ?+)
+         (setq str (concat "+" (cc-imenu-objc-method-to-selector str)))
+         (setq methodlist (cons (cons str
+                                      (match-beginning langnum))
+                                methodlist)))
+        ;; Interface or implementation or protocol
+        ((eq (aref str 0) ?@)
+         (setq classcount (1+ classcount))
+         (cond
+          ((and (> (length str) implen)
+                (string= (substring  str 0 implen) "@implementation"))
+           (setq str (substring str implen)
+                 str2 "@implementation"))
+          ((string= (substring  str 0 intflen) "@interface")
+           (setq str (substring str intflen)
+                 str2 "@interface"))
+          ((string= (substring  str 0 prtlen) "@protocol")
+           (setq str (substring str prtlen)
+                 str2 "@protocol")))
+         (setq str (cc-imenu-objc-remove-white-space str))
+         (setq methodlist (cons (cons str2
+                                      (match-beginning langnum))
+                                methodlist))
+         (setq toplist (cons (cons str methodlist) toplist)
+               methodlist nil)))))
 
     ;; In this buffer, there is only one or zero 
@{interface|implementation|protocol}.
     (if (< classcount 2)
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index 8618724..556ff60 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -1657,9 +1657,10 @@ white space either before or after the operator, but not 
both."
 
 (defcustom c-noise-macro-names nil
   "A list of names of macros which expand to nothing, or compiler extensions
-like \"????\" which are syntactic noise.  Such a macro/extension is complete in
-itself, never having parentheses.  All these names must be syntactically valid
-identifiers.
+like \"INLINE\" which are syntactic noise.  Such a macro/extension is complete
+in itself, never having parentheses.  All these names must be syntactically
+valid identifiers.  Alternatively, this variable may be a regular expression
+which matches the names of such macros.
 
 If you change this variable's value, call the function
 `c-make-noise-macro-regexps' to set the necessary internal variables (or do
@@ -1673,7 +1674,13 @@ this implicitly by reinitializing C/C++/Objc Mode on any 
buffer)."
 (defcustom c-noise-macro-with-parens-names nil
   "A list of names of macros (or compiler extensions like \"__attribute__\")
 which optionally have arguments in parentheses, and which expand to nothing.
-These are recognized by CC Mode only in declarations."
+All these names must be syntactically valid identifiers.  These are recognized
+by CC Mode only in declarations.  Alternatively, this variable may be a
+regular expression which matches the names of such macros.
+
+If you change this variable's value, call the function
+`c-make-noise-macro-regexps' to set the necessary internal variables (or do
+this implicitly by reinitializing C/C++/Objc Mode on any buffer)."
   :version "26.1"
   :type '(repeat :tag "List of names (possibly empty)" string)
   :group 'c)
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index 53a4c68..5fee2df 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -446,7 +446,7 @@ May require patched `imenu' and `imenu-go'.  Obsolete."
   :group 'cperl-help-system)
 
 (defcustom cperl-info-page "perl"
-  "Name of the info page containing perl docs.
+  "Name of the Info manual containing perl docs.
 Older version of this page was called `perl5', newer `perl'."
   :type 'string
   :group 'cperl-help-system)
diff --git a/lisp/progmodes/cwarn.el b/lisp/progmodes/cwarn.el
index dfb987b..6cd2fa3 100644
--- a/lisp/progmodes/cwarn.el
+++ b/lisp/progmodes/cwarn.el
@@ -168,6 +168,8 @@ deactivated."
   :tag "Load Hook"
   :group 'cwarn
   :type 'hook)
+(make-obsolete-variable 'cwarn-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 ;;}}}
 ;;{{{ The modes
diff --git a/lisp/progmodes/ebnf2ps.el b/lisp/progmodes/ebnf2ps.el
index d5820bb..d5dddfc 100644
--- a/lisp/progmodes/ebnf2ps.el
+++ b/lisp/progmodes/ebnf2ps.el
@@ -1157,21 +1157,6 @@ Please send all bug fixes and enhancements to
 (and (string< ps-print-version "5.2.3")
      (error "`ebnf2ps' requires `ps-print' package version 5.2.3 or later"))
 
-
-;; to avoid gripes with Emacs 20
-(or (fboundp 'assq-delete-all)
-    (defun assq-delete-all (key alist)
-      "Delete from ALIST all elements whose car is KEY.
-Return the modified alist.
-Elements of ALIST that are not conses are ignored."
-      (let ((tail alist))
-       (while tail
-         (if (and (consp (car tail))
-                  (eq (car (car tail)) key))
-             (setq alist (delq (car tail) alist)))
-         (setq tail (cdr tail)))
-       alist)))
-
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; User Variables:
@@ -2053,8 +2038,7 @@ It must be a float between 0.0 (top) and 1.0 (bottom)."
 
 
 ;; Printing color requires x-color-values.
-(defcustom ebnf-color-p (or (fboundp 'x-color-values) ; Emacs
-                           (fboundp 'color-instance-rgb-components)) ; XEmacs
+(defcustom ebnf-color-p t
   "Non-nil means use color."
   :type 'boolean
   :version "20"
@@ -2738,8 +2722,7 @@ Used in functions `ebnf-reset-style', `ebnf-push-style' 
and
       (ebnf-eps-footer-font             . '(7 Helvetica "Black" "White" bold))
       (ebnf-eps-footer                  . nil)
       (ebnf-entry-percentage            . 0.5)
-      (ebnf-color-p   . (or (fboundp 'x-color-values) ; Emacs
-                           (fboundp 'color-instance-rgb-components))) ; XEmacs
+      (ebnf-color-p                     . t)
       (ebnf-line-width                  . 1.0)
       (ebnf-line-color                  . "Black")
       (ebnf-debug-ps                    . nil)
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 774e332..2617a6e 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -933,7 +933,8 @@ Paragraphs are separated only by blank lines.
 Semicolons start comments.
 
 \\{lisp-interaction-mode-map}"
-  :abbrev-table nil)
+  :abbrev-table nil
+  (setq-local lexical-binding t))
 
 ;;; Emacs Lisp Byte-Code mode
 
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index fe64895..897f105 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -60,7 +60,8 @@ Any other value means use the setting of `case-fold-search'."
   :type '(choice (const :tag "Case-sensitive" nil)
                 (const :tag "Case-insensitive" t)
                 (other :tag "Use default" default))
-  :version "21.1")
+  :version "21.1"
+  :safe 'symbolp)
 
 ;;;###autoload
 ;; Use `visit-tags-table-buffer' to cycle through tags tables in this list.
@@ -819,9 +820,7 @@ tags table for BUF and its (recursively) included tags 
tables."
   "Using tags, return a completion table for the text around point.
 If no tags table is loaded, do nothing and return nil."
   (when (or tags-table-list tags-file-name)
-    (let ((completion-ignore-case (if (memq tags-case-fold-search '(t nil))
-                                     tags-case-fold-search
-                                   case-fold-search))
+    (let ((completion-ignore-case (find-tag--completion-ignore-case))
          (pattern (find-tag--default))
          beg)
       (when pattern
@@ -836,9 +835,7 @@ If no tags table is loaded, do nothing and return nil."
 
 (defun find-tag-tag (string)
   "Read a tag name, with defaulting and completion."
-  (let* ((completion-ignore-case (if (memq tags-case-fold-search '(t nil))
-                                    tags-case-fold-search
-                                  case-fold-search))
+  (let* ((completion-ignore-case (find-tag--completion-ignore-case))
         (default (find-tag--default))
         (spec (completing-read (if default
                                    (format "%s (default %s): "
@@ -851,6 +848,11 @@ If no tags table is loaded, do nothing and return nil."
        (or default (user-error "There is no default tag"))
       spec)))
 
+(defun find-tag--completion-ignore-case ()
+  (if (memq tags-case-fold-search '(t nil))
+      tags-case-fold-search
+    case-fold-search))
+
 (defun find-tag--default ()
   (funcall (or find-tag-default-function
                (get major-mode 'find-tag-default-function)
@@ -2072,6 +2074,9 @@ file name, add `tag-partial-file-name-match-p' to the 
list value.")
 (cl-defmethod xref-backend-identifier-completion-table ((_backend (eql etags)))
   (tags-lazy-completion-table))
 
+(cl-defmethod xref-backend-identifier-completion-ignore-case ((_backend (eql 
etags)))
+  (find-tag--completion-ignore-case))
+
 (cl-defmethod xref-backend-definitions ((_backend (eql etags)) symbol)
   (etags--xref-find-definitions symbol))
 
@@ -2086,9 +2091,7 @@ file name, add `tag-partial-file-name-match-p' to the 
list value.")
          (first-time t)
          (search-fun (if regexp? #'re-search-forward #'search-forward))
          (marks (make-hash-table :test 'equal))
-         (case-fold-search (if (memq tags-case-fold-search '(nil t))
-                               tags-case-fold-search
-                             case-fold-search))
+         (case-fold-search (find-tag--completion-ignore-case))
          (cbuf (current-buffer)))
     (save-excursion
       (while (visit-tags-table-buffer (not first-time) cbuf)
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
index 92fba1c..22f1cfd 100644
--- a/lisp/progmodes/f90.el
+++ b/lisp/progmodes/f90.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 1995-1997, 2000-2020 Free Software Foundation, Inc.
 
 ;; Author: Torbjörn Einarsson <address@hidden>
-;; Maintainer: Glenn Morris <address@hidden>
+;; Maintainer: address@hidden
 ;; Keywords: fortran, f90, languages
 
 ;; This file is part of GNU Emacs.
@@ -539,8 +539,10 @@ type-name parts, respectively."
 read\\|write\\)\\)[ \t]*(" (1 font-lock-keyword-face t))
    ;; Other functions and declarations.  Named interfaces = F2003.
    ;; F2008: end submodule submodule_name.
-   '("\\_<\\(\\(?:end[ \t]*\\)?\\(program\\|\\(?:sub\\)?module\\|\
-function\\|associate\\|subroutine\\|interface\\)\\|use\\|call\\)\
+   ;; F2008: module function|subroutine NAME.
+   '("\\_<\\(\\(?:end[ \t]*\\)?\\(program\\|\
+\\(?:module[ \t]*\\)?\\(?:function\\|subroutine\\)\\|\
+\\(?:sub\\)?module\\|associate\\|interface\\)\\|use\\|call\\)\
 \\_>[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)?"
      (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t))
    ;; F2008: submodule (parent_name) submodule_name.
@@ -1381,14 +1383,19 @@ write\\)[ \t]*([^)\n]*)")
   (cond
    ((looking-at "\\(program\\)[ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>")
     (list (match-string 1) (match-string 2)))
-   ((and (not (looking-at "module[ \t]*procedure\\_>"))
+   ((and (not (looking-at "module[ 
\t]*\\(procedure\\|function\\|subroutine\\)\\_>"))
          (looking-at "\\(module\\)[ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>"))
     (list (match-string 1) (match-string 2)))
    ((looking-at "\\(submodule\\)[ \t]*([^)\n]+)[ 
\t]*\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>")
     (list (match-string 1) (match-string 2)))
-   ((and (not (looking-at "end[ \t]*\\(function\\|subroutine\\)"))
-         (looking-at "[^!'\"&\n]*\\(function\\|subroutine\\)[ \t]+\
+   ((and (not (looking-at "end[ \t]*\\(function\\|procedure\\|subroutine\\)"))
+         (looking-at "[^!'\"&\n]*\\(?:module[ \t]*\\)?\
+\\(function\\|subroutine\\)[ \t]+\
 \\(\\(?:\\sw\\|\\s_\\)+\\)"))
+    ;; TODO: In F2008  "module procedure foo" may or may not start a block,
+    ;; It is impossible to tell the difference without parsing state.
+;;;         (looking-at "[^!'\"&\n]*module[ \t]*\\(procedure\\)[ \t]+\
+;;;\\(\\(?:\\sw\\|\\s_\\)+\\)")))
     (list (match-string 1) (match-string 2)))))
 ;; Following will match an un-named main program block; however
 ;; one needs to check if there is an actual PROGRAM statement after
diff --git a/lisp/progmodes/flymake-proc.el b/lisp/progmodes/flymake-proc.el
index e2d9408..62f6d1a 100644
--- a/lisp/progmodes/flymake-proc.el
+++ b/lisp/progmodes/flymake-proc.el
@@ -851,7 +851,7 @@ can also be executed interactively independently of
   (interactive (list "Interrupted by user"))
   (dolist (buf (buffer-list))
     (with-current-buffer buf
-      (let (p flymake-proc--current-process)
+      (let ((p flymake-proc--current-process))
         (when (process-live-p p)
           (kill-process p)
           (process-put p 'flymake-proc--interrupted reason)
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
index b7e9e78..811951e 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -4,7 +4,7 @@
 ;; Inc.
 
 ;; Author: Michael D. Prange <address@hidden>
-;; Maintainer: Glenn Morris <address@hidden>
+;; Maintainer: address@hidden
 ;; Keywords: fortran, languages
 
 ;; This file is part of GNU Emacs.
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index b08d487..e785acd 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -37,7 +37,7 @@
 ;; buffers which control the execution and describe the state of your program.
 ;; It separates the input/output of your program from that of GDB and displays
 ;; expressions and their current values in their own buffers.  It also uses
-;; features of Emacs 21 such as the fringe/display margin for breakpoints, and
+;; features such as the fringe/display margin for breakpoints, and
 ;; the toolbar (see the GDB Graphical Interface section in the Emacs info
 ;; manual).
 
@@ -324,7 +324,10 @@ in `gdb-handler-list' and clears all pending handlers 
invalidated
 by the reception of this reply."
   (let ((handler-function (gdb-get-handler-function token-number)))
     (when handler-function
-      (funcall handler-function)
+      ;; Protect against errors in handler-function.
+      (condition-case err
+          (funcall handler-function)
+        (error (message (error-message-string err))))
       (gdb-delete-handler token-number))))
 
 (defun gdb-remove-all-pending-triggers ()
@@ -1001,8 +1004,10 @@ no input, and GDB is waiting for input."
        ;; Sending an EOF does not work with GDB-MI; submit an
        ;; explicit quit command.
        (progn
-         (insert "quit")
-         (comint-send-input t t))
+          (if (> gdb-control-level 0)
+              (process-send-eof proc)
+            (insert "quit")
+            (comint-send-input t t)))
       (delete-char arg))))
 
 (defvar gdb-define-alist nil "Alist of #define directives for GUD tooltips.")
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index d4aca28..7731be5 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -64,8 +64,7 @@ SYMBOL should be one of `grep-command', `grep-template',
   "Number of lines in a grep window.  If nil, use `compilation-window-height'."
   :type '(choice (const :tag "Default" nil)
                 integer)
-  :version "22.1"
-  :group 'grep)
+  :version "22.1")
 
 (defcustom grep-highlight-matches 'auto-detect
   "Use special markers to highlight grep matches.
@@ -98,9 +97,8 @@ To change the default value, use \\[customize] or call the 
function
                 (const :tag "Use --color=always" always)
                 (const :tag "Use --color" auto)
                 (other :tag "Not Set" auto-detect))
-  :set 'grep-apply-setting
-  :version "22.1"
-  :group 'grep)
+  :set #'grep-apply-setting
+  :version "22.1")
 
 (defcustom grep-scroll-output nil
   "Non-nil to scroll the *grep* buffer window as output appears.
@@ -109,8 +107,7 @@ Setting it causes the grep commands to put point at the end 
of their
 output window so that the end of the output is always visible rather
 than the beginning."
   :type 'boolean
-  :version "22.1"
-  :group 'grep)
+  :version "22.1")
 
 ;;;###autoload
 (defcustom grep-command nil
@@ -124,8 +121,7 @@ by `grep-compute-defaults'; to change the default value, use
 \\[customize] or call the function `grep-apply-setting'."
   :type '(choice string
                 (const :tag "Not Set" nil))
-  :set 'grep-apply-setting
-  :group 'grep)
+  :set #'grep-apply-setting)
 
 (defcustom grep-template nil
   "The default command to run for \\[lgrep].
@@ -141,9 +137,8 @@ by `grep-compute-defaults'; to change the default value, use
 \\[customize] or call the function `grep-apply-setting'."
   :type '(choice string
                 (const :tag "Not Set" nil))
-  :set 'grep-apply-setting
-  :version "22.1"
-  :group 'grep)
+  :set #'grep-apply-setting
+  :version "22.1")
 
 (defcustom grep-use-null-device 'auto-detect
   "If t, append the value of `null-device' to `grep' commands.
@@ -157,8 +152,7 @@ by `grep-compute-defaults'; to change the default value, use
   :type '(choice (const :tag "Do Not Append Null Device" nil)
                 (const :tag "Append Null Device" t)
                 (other :tag "Not Set" auto-detect))
-  :set 'grep-apply-setting
-  :group 'grep)
+  :set #'grep-apply-setting)
 
 (defcustom grep-use-null-filename-separator 'auto-detect
   "If non-nil, use `grep's `--null' option.
@@ -167,8 +161,7 @@ This is done to disambiguate file names in `grep's output."
   :type '(choice (const :tag "Do Not Use `--null'" nil)
                  (const :tag "Use `--null'" t)
                  (other :tag "Not Set" auto-detect))
-  :set 'grep-apply-setting
-  :group 'grep)
+  :set #'grep-apply-setting)
 
 ;;;###autoload
 (defcustom grep-find-command nil
@@ -178,8 +171,7 @@ by `grep-compute-defaults'; to change the default value, use
 \\[customize] or call the function `grep-apply-setting'."
   :type '(choice string
                 (const :tag "Not Set" nil))
-  :set 'grep-apply-setting
-  :group 'grep)
+  :set #'grep-apply-setting)
 
 (defcustom grep-find-template nil
   "The default command to run for \\[rgrep].
@@ -194,9 +186,8 @@ by `grep-compute-defaults'; to change the default value, use
 \\[customize] or call the function `grep-apply-setting'."
   :type '(choice string
                 (const :tag "Not Set" nil))
-  :set 'grep-apply-setting
-  :version "22.1"
-  :group 'grep)
+  :set #'grep-apply-setting
+  :version "22.1")
 
 (defcustom grep-files-aliases
   '(("all" .   "* .[!.]* ..?*") ;; Don't match `..'. See bug#22577
@@ -213,8 +204,7 @@ by `grep-compute-defaults'; to change the default value, use
     ("texi" .  "*.texi")
     ("asm" .   "*.[sS]"))
   "Alist of aliases for the FILES argument to `lgrep' and `rgrep'."
-  :type 'alist
-  :group 'grep)
+  :type 'alist)
 
 (defcustom grep-find-ignored-directories vc-directory-exclusion-list
   "List of names of sub-directories which `rgrep' shall not recurse into.
@@ -223,8 +213,7 @@ to determine whether cdr should not be recursed into.
 
 The default value is inherited from `vc-directory-exclusion-list'."
   :type '(choice (repeat :tag "Ignored directories" string)
-                (const :tag "No ignored directories" nil))
-  :group 'grep)
+                (const :tag "No ignored directories" nil)))
 
 (defcustom grep-find-ignored-files
   (cons ".#*" (delq nil (mapcar (lambda (s)
@@ -235,8 +224,7 @@ The default value is inherited from 
`vc-directory-exclusion-list'."
 If an element is a cons cell, the car is called on the search directory
 to determine whether cdr should not be excluded."
   :type '(choice (repeat :tag "Ignored file" string)
-                (const :tag "No ignored files" nil))
-  :group 'grep)
+                (const :tag "No ignored files" nil)))
 
 (defcustom grep-save-buffers 'ask
   "If non-nil, save buffers before running the grep commands.
@@ -251,22 +239,19 @@ to limit saving to files located under `my-grep-root'."
           (const :tag "Ask before saving" ask)
           (const :tag "Don't save buffers" nil)
           function
-          (other :tag "Save all buffers" t))
-  :group 'grep)
+          (other :tag "Save all buffers" t)))
 
 (defcustom grep-error-screen-columns nil
   "If non-nil, column numbers in grep hits are screen columns.
 See `compilation-error-screen-columns'."
   :type '(choice (const :tag "Default" nil)
                 integer)
-  :version "22.1"
-  :group 'grep)
+  :version "22.1")
 
 ;;;###autoload
 (defcustom grep-setup-hook nil
   "List of hook functions run by `grep-process-setup' (see `run-hooks')."
-  :type 'hook
-  :group 'grep)
+  :type 'hook)
 
 (defvar grep-mode-map
   (let ((map (make-sparse-keymap)))
@@ -333,7 +318,10 @@ See `compilation-error-screen-columns'."
   ;; When bootstrapping, tool-bar-map is not properly initialized yet,
   ;; so don't do anything.
   (when (keymapp (butlast tool-bar-map))
+    ;; We have to `copy-keymap' rather than use keymap inheritance because
+    ;; we want to put the new items at the *end* of the tool-bar.
     (let ((map (butlast (copy-keymap tool-bar-map)))
+         ;; FIXME: Nowadays the last button is not "help" but "search"!
          (help (last tool-bar-map))) ;; Keep Help last in tool bar
       (tool-bar-local-item
        "left-arrow" 'previous-error-no-select 'previous-error-no-select map
@@ -439,15 +427,13 @@ and reveals the entire command line.  The visibility of 
the
 abbreviated part can also be toggled with
 `grep-find-toggle-abbreviation'."
   :type 'boolean
-  :version "27.1"
-  :group 'grep)
+  :version "27.1")
 
 (defcustom grep-search-path '(nil)
   "List of directories to search for files named in grep messages.
 Elements should be directory names, not file names of
 directories.  The value nil as an element means the grep messages
 buffer `default-directory'."
-  :group 'grep
   :version "27.1"
   :type '(repeat (choice (const :tag "Default" nil)
                         (string :tag "Directory"))))
@@ -528,9 +514,8 @@ This variable's value takes effect when 
`grep-compute-defaults' is called."
                  (const :tag "find -print0 | sort -z | xargs -0'" gnu-sort)
                  string
                 (const :tag "Not Set" nil))
-  :set 'grep-apply-setting
-  :version "27.1"
-  :group 'grep)
+  :set #'grep-apply-setting
+  :version "27.1")
 
 ;; History of grep commands.
 ;;;###autoload
@@ -562,7 +547,7 @@ Set up `compilation-exit-message-function' and run 
`grep-setup-hook'."
     (setenv "GREP_COLORS" "mt=01;31:fn=:ln=:bn=:se=:sl=:cx=:ne"))
   (setq-local grep-num-matches-found 0)
   (set (make-local-variable 'compilation-exit-message-function)
-       'grep-exit-message)
+       #'grep-exit-message)
   (run-hooks 'grep-setup-hook))
 
 (defun grep-exit-message (status code msg)
@@ -612,7 +597,7 @@ This function is called from `compilation-filter-hook'."
 (defun grep-probe (command args &optional func result)
   (let (process-file-side-effects)
     (equal (condition-case nil
-              (apply (or func 'process-file) command args)
+              (apply (or func #'process-file) command args)
             (error nil))
           (or result 0))))
 
@@ -808,7 +793,7 @@ The value depends on `grep-command', `grep-template',
           (buffer-substring-no-properties (point) (mark)))
       (funcall (or find-tag-default-function
                   (get major-mode 'find-tag-default-function)
-                  'find-tag-default))
+                  #'find-tag-default))
       ""))
 
 (defun grep-default-command ()
@@ -863,11 +848,11 @@ The value depends on `grep-command', `grep-template',
   (set (make-local-variable 'compilation-directory-matcher)
        (list regexp-unmatchable))
   (set (make-local-variable 'compilation-process-setup-function)
-       'grep-process-setup)
+       #'grep-process-setup)
   (set (make-local-variable 'compilation-disable-input) t)
   (set (make-local-variable 'compilation-error-screen-columns)
        grep-error-screen-columns)
-  (add-hook 'compilation-filter-hook 'grep-filter nil t))
+  (add-hook 'compilation-filter-hook #'grep-filter nil t))
 
 (defun grep--save-buffers ()
   (when grep-save-buffers
@@ -914,7 +899,7 @@ list is empty)."
   (compilation-start (if (and grep-use-null-device null-device)
                         (concat command-args " " null-device)
                       command-args)
-                    'grep-mode))
+                    #'grep-mode))
 
 
 ;;;###autoload
@@ -993,23 +978,31 @@ these include `opts', `dir', `files', `null-device', 
`excl' and
   "Read regexp arg for interactive grep using `read-regexp'."
   (read-regexp "Search for" 'grep-tag-default 'grep-regexp-history))
 
+(defvar grep-read-files-function #'grep-read-files--default)
+
+(defun grep-read-files--default ()
+  ;; Instead of a `grep-read-files-function' variable, we used to lookup
+  ;; mode-specific functions in the major mode's symbol properties, so preserve
+  ;; this behavior for backward compatibility.
+  (let ((old-function (get major-mode 'grep-read-files))) ;Obsolete since 28.1
+    (if old-function
+       (funcall old-function)
+      (let ((file-name-at-point
+            (run-hook-with-args-until-success 'file-name-at-point-functions)))
+       (or (if (and (stringp file-name-at-point)
+                    (not (file-directory-p file-name-at-point)))
+               file-name-at-point)
+           (buffer-file-name)
+           (replace-regexp-in-string "<[0-9]+>\\'" "" (buffer-name)))))))
+
 (defun grep-read-files (regexp)
   "Read a file-name pattern arg for interactive grep.
-The pattern can include shell wildcards.  As whitespace triggers
+The pattern can include shell wildcards.  As SPC can triggers
 completion when entering a pattern, including it requires
 quoting, e.g. `\\[quoted-insert]<space>'.
 
 REGEXP is used as a string in the prompt."
-  (let* ((grep-read-files-function (get major-mode 'grep-read-files))
-        (file-name-at-point
-          (run-hook-with-args-until-success 'file-name-at-point-functions))
-        (bn (if grep-read-files-function
-                (funcall grep-read-files-function)
-              (or (if (and (stringp file-name-at-point)
-                           (not (file-directory-p file-name-at-point)))
-                      file-name-at-point)
-                  (buffer-file-name)
-                  (replace-regexp-in-string "<[0-9]+>\\'" "" (buffer-name)))))
+  (let* ((bn (funcall grep-read-files-function))
         (fn (and bn
                  (stringp bn)
                  (file-name-nondirectory bn)))
@@ -1022,7 +1015,7 @@ REGEXP is used as a string in the prompt."
                    (setq alias (car aliases)
                          aliases (cdr aliases))
                    (if (string-match (mapconcat
-                                      'wildcard-to-regexp
+                                      #'wildcard-to-regexp
                                       (split-string (cdr alias) nil t)
                                       "\\|")
                                      fn)
@@ -1043,11 +1036,11 @@ REGEXP is used as a string in the prompt."
                         "\" in files matching wildcard"
                         (if default (concat " (default " default ")"))
                         ": ")
-                'read-file-name-internal
+                #'read-file-name-internal
                 nil nil nil 'grep-files-history
                 (delete-dups
                  (delq nil (append (list default default-alias 
default-extension)
-                                   (mapcar 'car grep-files-aliases)))))))
+                                   (mapcar #'car grep-files-aliases)))))))
     (and files
         (or (cdr (assoc files grep-files-aliases))
             files))))
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index d5fd1dc..567f452 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -486,9 +486,8 @@ The value t means that there is no stack, and we are in 
display-file mode.")
   "Additional menu items to add to the speedbar frame.")
 
 ;; Make sure our special speedbar mode is loaded
-(if (featurep 'speedbar)
-    (gud-install-speedbar-variables)
-  (add-hook 'speedbar-load-hook 'gud-install-speedbar-variables))
+(with-eval-after-load 'speedbar
+  (gud-install-speedbar-variables))
 
 (defun gud-expansion-speedbar-buttons (_directory _zero)
   "Wrapper for call to `speedbar-add-expansion-list'.
diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el
index 7bc2b60..3092d4c 100644
--- a/lisp/progmodes/idlwave.el
+++ b/lisp/progmodes/idlwave.el
@@ -1096,6 +1096,8 @@ class-arrows         Object Arrows with class property"
   "Normal hook.  Executed when idlwave.el is loaded."
   :group 'idlwave-misc
   :type 'hook)
+(make-obsolete-variable 'idlwave-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defvar idlwave-experimental nil
   "Non-nil means turn on a few experimental features.
@@ -1870,7 +1872,6 @@ The main features of this mode are
 
 8. Hooks
    -----
-   Loading idlwave.el runs `idlwave-load-hook'.
    Turning on `idlwave-mode' runs `idlwave-mode-hook'.
 
 9. Documentation and Customization
diff --git a/lisp/progmodes/inf-lisp.el b/lisp/progmodes/inf-lisp.el
index a24b940..9f34a37 100644
--- a/lisp/progmodes/inf-lisp.el
+++ b/lisp/progmodes/inf-lisp.el
@@ -130,9 +130,8 @@ mode.  Default is whitespace followed by 0 or 1 
single-letter colon-keyword
 
 ;;;  "This function binds many inferior-lisp commands to C-c <letter> bindings,
 ;;;where they are more accessible. C-c <letter> bindings are reserved for the
-;;;user, so these bindings are non-standard. If you want them, you should
-;;;have this function called by the inferior-lisp-load-hook:
-;;;  (add-hook 'inferior-lisp-load-hook 'inferior-lisp-install-letter-bindings)
+;;;user, so these bindings are non-standard. If you want them:
+;;;  (with-eval-after-load 'inf-lisp 'inferior-lisp-install-letter-bindings)
 ;;;You can modify this function to install just the bindings you want."
 (defun inferior-lisp-install-letter-bindings ()
   (define-key lisp-mode-map "\C-ce" 'lisp-eval-defun-and-go)
@@ -632,6 +631,8 @@ See variable `lisp-describe-sym-command'."
 ;;;===============================
 (defvar inferior-lisp-load-hook nil
   "This hook is run when the library `inf-lisp' is loaded.")
+(make-obsolete-variable 'inferior-lisp-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (run-hooks 'inferior-lisp-load-hook)
 
diff --git a/lisp/progmodes/meta-mode.el b/lisp/progmodes/meta-mode.el
index 6f0e535..4a5d872 100644
--- a/lisp/progmodes/meta-mode.el
+++ b/lisp/progmodes/meta-mode.el
@@ -895,6 +895,8 @@ The environment marked is the one that contains point or 
follows point."
   "Hook evaluated when first loading Metafont or MetaPost mode."
   :type 'hook
   :group 'meta-font)
+(make-obsolete-variable 'meta-mode-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defcustom meta-common-mode-hook nil
   "Hook evaluated by both `metafont-mode' and `metapost-mode'."
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index cc6d5b4..a241a1e 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -64,61 +64,10 @@
 ;;     *   Indent right half sh-basic-offset
 ;;     /   Indent left  half sh-basic-offset.
 ;;
-;; There are 4 commands to help set the indentation variables:
-;;
-;; `sh-show-indent'
-;;    This shows what variable controls the indentation of the current
-;;    line and its value.
-;;
-;; `sh-set-indent'
-;;    This allows you to set the value of the variable controlling the
-;;    current line's indentation.  You can enter a number or one of a
-;;    number of special symbols to denote the value of sh-basic-offset,
-;;    or its negative, or half it, or twice it, etc.  If you've used
-;;    cc-mode this should be familiar.  If you forget which symbols are
-;;    valid simply press C-h at the prompt.
-;;
-;; `sh-learn-line-indent'
-;;    Simply make the line look the way you want it, then invoke this
-;;    command.  It will set the variable to the value that makes the line
-;;    indent like that.  If called with a prefix argument then it will set
-;;    the value to one of the symbols if applicable.
-;;
-;; `sh-learn-buffer-indent'
-;;    This is the deluxe function!  It "learns" the whole buffer (use
-;;    narrowing if you want it to process only part).  It outputs to a
-;;    buffer *indent* any conflicts it finds, and all the variables it has
-;;    learned.  This buffer is a sort of Occur mode buffer, allowing you to
-;;    easily find where something was set.  It is popped to automatically
-;;    if there are any conflicts found or if `sh-popup-occur-buffer' is
-;;    non-nil.
-;;    `sh-indent-comment' will be set if all comments follow  the same
-;;    pattern;  if they don't it will be set to nil.
-;;    Whether `sh-basic-offset' is set is determined by variable
-;;    `sh-learn-basic-offset'.
-;;
-;;    Unfortunately, `sh-learn-buffer-indent' can take a long time to run
-;;    (e.g. if there are large case statements).  Perhaps it does not make
-;;    sense to run it on large buffers: if lots of lines have different
-;;    indentation styles it will produce a lot of diagnostics in the
-;;    *indent* buffer; if there is a consistent style then running
-;;    `sh-learn-buffer-indent' on a small region of the buffer should
-;;    suffice.
-;;
 ;;     Saving indentation values
 ;;     -------------------------
-;; After you've learned the values in a buffer, how to you remember
-;; them?   Originally I had hoped that `sh-learn-buffer-indent'
-;; would make this unnecessary;  simply learn the values when you visit
-;; the buffer.
-;; You can do this automatically like this:
-;;   (add-hook 'sh-set-shell-hook #'sh-learn-buffer-indent)
-;;
-;; However...  `sh-learn-buffer-indent' is extremely slow,
-;; especially on large-ish buffer.  Also, if there are conflicts the
-;; "last one wins" which may not produce the desired setting.
-;;
-;; So...There is a minimal way of being able to save indentation values and
+;; After you've learned the values in a buffer, how to you remember them?
+;; There is a minimal way of being able to save indentation values and
 ;; to reload them in another buffer or at another point in time.
 ;;
 ;; Use `sh-name-style' to give a name to the indentation settings of
@@ -132,7 +81,7 @@
 ;;     Indentation variables - buffer local or global?
 ;;     ----------------------------------------------
 ;; I think that often having them buffer-local makes sense,
-;; especially if one is using `sh-learn-buffer-indent'.  However, if
+;; especially if one is using `smie-config-guess'.  However, if
 ;; a user sets values using customization, these changes won't appear
 ;; to work if the variables are already local!
 ;;
@@ -175,18 +124,10 @@
 ;; - Indenting many lines is slow.  It currently does each line
 ;;   independently, rather than saving state information.
 ;;
-;; - `sh-learn-buffer-indent' is extremely slow.
-;;
-;; - "case $x in y) echo ;; esac)" the last ) is mis-identified as being
-;;   part of a case-pattern.  You need to add a semi-colon after "esac" to
-;;   coerce sh-script into doing the right thing.
-;;
 ;; - "echo $z in ps | head)" the last ) is mis-identified as being part of
 ;;   a case-pattern.  You need to put the "in" between quotes to coerce
 ;;   sh-script into doing the right thing.
 ;;
-;; - A line starting with "}>foo" is not indented like "} >foo".
-;;
 ;; Richard Sharman <address@hidden>  June 1999.
 
 ;;; Code:
@@ -474,10 +415,10 @@ This is buffer-local in every such buffer.")
     (define-key map "\C-c\C-i" 'sh-if)
     (define-key map "\C-c\C-f" 'sh-for)
     (define-key map "\C-c\C-c" 'sh-case)
-    (define-key map "\C-c?" 'sh-show-indent)
-    (define-key map "\C-c=" 'sh-set-indent)
-    (define-key map "\C-c<" 'sh-learn-line-indent)
-    (define-key map "\C-c>" 'sh-learn-buffer-indent)
+    (define-key map "\C-c?" #'smie-config-show-indent)
+    (define-key map "\C-c=" #'smie-config-set-indent)
+    (define-key map "\C-c<" #'smie-config-set-indent)
+    (define-key map "\C-c>" #'smie-config-guess)
     (define-key map "\C-c\C-\\" 'sh-backslash-region)
 
     (define-key map "\C-c+" 'sh-add)
@@ -493,17 +434,14 @@ This is buffer-local in every such buffer.")
     (define-key map [remap backward-sentence] 'sh-beginning-of-command)
     (define-key map [remap forward-sentence] 'sh-end-of-command)
     (define-key map [menu-bar sh-script] (cons "Sh-Script" menu-map))
-    (define-key menu-map [sh-learn-buffer-indent]
-      '(menu-item "Learn buffer indentation" sh-learn-buffer-indent
+    (define-key menu-map [smie-config-guess]
+      '(menu-item "Learn buffer indentation" smie-config-guess
         :help "Learn how to indent the buffer the way it currently is."))
-    (define-key menu-map [sh-learn-line-indent]
-      '(menu-item "Learn line indentation" sh-learn-line-indent
-        :help "Learn how to indent a line as it currently is indented"))
-    (define-key menu-map [sh-show-indent]
-      '(menu-item "Show indentation" sh-show-indent
+    (define-key menu-map [smie-config-show-indent]
+      '(menu-item "Show indentation" smie-config-show-indent
                  :help "Show the how the current line would be indented"))
-    (define-key menu-map [sh-set-indent]
-      '(menu-item "Set indentation" sh-set-indent
+    (define-key menu-map [smie-config-set-indent]
+      '(menu-item "Set indentation" smie-config-set-indent
                  :help "Set the indentation for the current line"))
 
     (define-key menu-map [sh-pair]
@@ -1196,20 +1134,8 @@ and command `sh-reset-indent-vars-to-global-values'."
   :options '(sh-electric-here-document-mode)
   :group 'sh-script)
 
-(defcustom sh-learn-basic-offset nil
-  "When `sh-guess-basic-offset' should learn `sh-basic-offset'.
-
-nil mean:              never.
-t means:               only if there seems to be an obvious value.
-Anything else means:   whenever we have a \"good guess\" as to the value."
-  :type '(choice
-         (const :tag "Never" nil)
-         (const :tag "Only if sure"  t)
-         (const :tag "If have a good guess" usually))
-  :group 'sh-indentation)
-
 (defcustom sh-popup-occur-buffer nil
-  "Controls when  `sh-learn-buffer-indent' pops the `*indent*' buffer.
+  "Controls when  `smie-config-guess' pops the `*indent*' buffer.
 If t it is always shown.  If nil, it is shown only when there
 are conflicts."
   :type '(choice
@@ -1217,14 +1143,6 @@ are conflicts."
          (const :tag "Always"  t))
   :group 'sh-indentation)
 
-(defcustom sh-blink t
-  "If non-nil, `sh-show-indent' shows the line indentation is relative to.
-The position on the line is not necessarily meaningful.
-In some cases the line will be the matching keyword, but this is not
-always the case."
-  :type 'boolean
-  :group 'sh-indentation)
-
 (defcustom sh-first-lines-indent 0
   "The indentation of the first non-blank non-comment line.
 Usually 0 meaning first column.
@@ -1567,11 +1485,9 @@ following commands are available, based on the current 
shell's syntax:
 \\[sh-while]    while loop
 
 For sh and rc shells indentation commands are:
-\\[sh-show-indent]     Show the variable controlling this line's indentation.
-\\[sh-set-indent]      Set then variable controlling this line's indentation.
-\\[sh-learn-line-indent]       Change the indentation variable so this line
-would indent to the way it currently is.
-\\[sh-learn-buffer-indent]  Set the indentation variables so the
+\\[smie-config-show-indent]    Show the rules controlling this line's 
indentation.
+\\[smie-config-set-indent]     Change the rules controlling this line's 
indentation.
+\\[smie-config-guess]  Try to tweak the indentation rules so the
 buffer indents as it currently is indented.
 
 
@@ -1738,13 +1654,6 @@ This adds rules for comments and assignments."
 
 (require 'smie)
 
-;; The SMIE code should generally be preferred, but it currently does not obey
-;; the various indentation custom-vars, and it misses some important features
-;; of the old code, mostly: sh-learn-line/buffer-indent, sh-show-indent,
-;; sh-name/save/load-style.
-(defvar sh-use-smie t
-  "Whether to use the SMIE code for navigation and indentation.")
-
 (defun sh-smie--keyword-p ()
   "Non-nil if we're at a keyword position.
 A keyword position is one where if we're looking at something that looks
@@ -2279,60 +2188,6 @@ Point should be before the newline."
 (defvar sh-regexp-for-done nil
   "A buffer-local regexp to match opening keyword for done.")
 
-(defvar sh-kw-alist nil
-  "A buffer-local, since it is shell-type dependent, list of keywords.")
-
-;; ( key-word  first-on-this  on-prev-line )
-;; This is used to set `sh-kw-alist' which is a list of sublists each
-;; having 3 elements:
-;;   a keyword
-;;   a rule to check when the keyword appears on "this" line
-;;   a rule to check when the keyword appears on "the previous" line
-;; The keyword is usually a string and is the first word on a line.
-;; If this keyword appears on the line whose indentation is to be
-;; calculated, the rule in element 2 is called.  If this returns
-;; non-zero, the resulting point (which may be changed by the rule)
-;; is used as the default indentation.
-;; If it returned false or the keyword was not found in the table,
-;; then the keyword from the previous line is looked up and the rule
-;; in element 3 is called.  In this case, however,
-;; `sh-get-indent-info' does not stop but may keep going and test
-;; other keywords against rules in element 3.  This is because the
-;; preceding line could have, for example, an opening "if" and an
-;; opening "while" keyword and we need to add the indentation offsets
-;; for both.
-;;
-(defconst sh-kw
-  '((sh
-     ("if" nil sh-handle-prev-if)
-     ("elif" sh-handle-this-else sh-handle-prev-else)
-     ("else" sh-handle-this-else sh-handle-prev-else)
-     ("fi" sh-handle-this-fi sh-handle-prev-fi)
-     ("then" sh-handle-this-then sh-handle-prev-then)
-     ("(" nil sh-handle-prev-open)
-     ("{" nil sh-handle-prev-open)
-     ("[" nil sh-handle-prev-open)
-     ("}" sh-handle-this-close nil)
-     (")" sh-handle-this-close nil)
-     ("]" sh-handle-this-close nil)
-     ("case" nil sh-handle-prev-case)
-     ("esac" sh-handle-this-esac sh-handle-prev-esac)
-     (case-label nil sh-handle-after-case-label) ;; ???
-     (";;" nil sh-handle-prev-case-alt-end) ;; ???
-     (";;&" nil sh-handle-prev-case-alt-end) ;Like ";;" with diff semantics.
-     (";&" nil sh-handle-prev-case-alt-end) ;Like ";;" with diff semantics.
-     ("done" sh-handle-this-done sh-handle-prev-done)
-     ("do" sh-handle-this-do sh-handle-prev-do))
-
-    ;; Note: we don't need specific stuff for bash and zsh shells;
-    ;; the regexp `sh-regexp-for-done' handles the extra keywords
-    ;; these shells use.
-    (rc
-     ("{" nil sh-handle-prev-open)
-     ("}" sh-handle-this-close nil)
-     ("case" sh-handle-this-rc-case sh-handle-prev-rc-case))))
-
-
 
 (defun sh-set-shell (shell &optional no-query-flag insert-flag)
   "Set this buffer's shell to SHELL (a string).
@@ -2400,16 +2255,6 @@ whose value is the shell name (don't quote it)."
                       (funcall mksym "rules")
                       :forward-token  (funcall mksym "forward-token")
                       :backward-token (funcall mksym "backward-token")))
-        (unless sh-use-smie
-          (setq-local sh-kw-alist (sh-feature sh-kw))
-          (let ((regexp (sh-feature sh-kws-for-done)))
-            (if regexp
-                (setq-local sh-regexp-for-done
-                           (sh-mkword-regexpr (regexp-opt regexp t)))))
-          (message "setting up indent stuff")
-          ;; sh-mode has already made indent-line-function local
-          ;; but do it in case this is called before that.
-          (setq-local indent-line-function #'sh-indent-line))
        (if sh-make-vars-local
            (sh-make-vars-local))
        (message "Indentation setup for shell type %s" sh-shell))
@@ -2564,11 +2409,6 @@ region, clear header."
   (eq -1 (% (save-excursion (skip-chars-backward "\\\\")) 2)))
 
 ;; Indentation stuff.
-(defun sh-must-support-indent ()
-  "Signal an error if the shell type for this buffer is not supported.
-Also, the buffer must be in Shell-script mode."
-  (unless sh-indent-supported-here
-    (error "This buffer's shell does not support indentation through Emacs")))
 
 (defun sh-make-vars-local ()
   "Make the indentation variables local to this buffer.
@@ -2589,654 +2429,12 @@ Then, if variable `sh-make-vars-local' is non-nil, 
make them local."
   (if sh-make-vars-local
       (mapcar 'make-local-variable sh-var-list)))
 
-
-;; Theoretically these are only needed in shell and derived modes.
-;; However, the routines which use them are only called in those modes.
-(defconst sh-special-keywords "then\\|do")
-
-(defun sh-help-string-for-variable (var)
-  "Construct a string for `sh-read-variable' when changing variable VAR ."
-  (let ((msg (documentation-property var 'variable-documentation))
-       (msg2 ""))
-    (unless (memq var '(sh-first-lines-indent sh-indent-comment))
-      (setq msg2
-           (format "\n
-You can enter a number (positive to increase indentation,
-negative to decrease indentation, zero for no change to indentation).
-
-Or, you can enter one of the following symbols which are relative to
-the value of variable `sh-basic-offset'
-which in this buffer is currently %s.
-
-\t%s."
-                   sh-basic-offset
-                   (mapconcat (lambda (x)
-                                (nth (1- (length x)) x))
-                              sh-symbol-list  "\n\t"))))
-    (concat
-     ;; The following shows the global not the local value!
-     ;; (format "Current value of %s is %s\n\n" var (symbol-value var))
-     msg msg2)))
-
-(defun sh-read-variable (var)
-  "Read a new value for indentation variable VAR."
-  (let ((minibuffer-help-form `(sh-help-string-for-variable
-                               (quote ,var)))
-       val)
-    (setq val (read-from-minibuffer
-              (format "New value for %s (press %s for help): "
-                      var  (single-key-description help-char))
-              (format "%s" (symbol-value var))
-              nil t))
-    val))
-
-
-
 (defun sh-in-comment-or-string (start)
   "Return non-nil if START is in a comment or string."
   (save-excursion
     (let ((state (syntax-ppss start)))
       (or (nth 3 state) (nth 4 state)))))
 
-(defun sh-goto-matching-if ()
-  "Go to the matching if for a fi.
-This handles nested if..fi pairs."
-  (let ((found (sh-find-prev-matching "\\bif\\b" "\\bfi\\b" 1)))
-    (if found
-       (goto-char found))))
-
-
-;; Functions named sh-handle-this-XXX are called when the keyword on the
-;; line whose indentation is being handled contain XXX;
-;; those named sh-handle-prev-XXX are when XXX appears on the previous line.
-
-(defun sh-handle-prev-if ()
-  (list '(+ sh-indent-after-if)))
-
-(defun sh-handle-this-else ()
-  (if (sh-goto-matching-if)
-      ;; (list "aligned to if")
-      (list "aligned to if" '(+ sh-indent-for-else))
-    nil
-    ))
-
-(defun sh-handle-prev-else ()
-  (if (sh-goto-matching-if)
-      (list  '(+ sh-indent-after-if))
-    ))
-
-(defun sh-handle-this-fi ()
-  (if (sh-goto-matching-if)
-      (list "aligned to if" '(+ sh-indent-for-fi))
-    nil
-    ))
-
-(defun sh-handle-prev-fi ()
-  ;; Why do we have this rule?  Because we must go back to the if
-  ;; to get its indent.  We may continue back from there.
-  ;; We return nil because we don't have anything to add to result,
-  ;; the side affect of setting align-point is all that matters.
-  ;; we could return a comment (a string) but I can't think of a good one...
-  (sh-goto-matching-if)
-  nil)
-
-(defun sh-handle-this-then ()
-  (let ((p (sh-goto-matching-if)))
-    (if p
-       (list '(+ sh-indent-for-then))
-      )))
-
-(defun sh-handle-prev-then ()
-  (let ((p (sh-goto-matching-if)))
-    (if p
-       (list '(+ sh-indent-after-if))
-      )))
-
-(defun sh-handle-prev-open ()
-  (save-excursion
-    (let ((x (sh-prev-stmt)))
-      (if (and x
-              (progn
-                (goto-char x)
-                (or
-                 (looking-at "function\\b")
-                 (looking-at "\\s-*\\S-+\\s-*()")
-                 )))
-         (list '(+ sh-indent-after-function))
-       (list '(+ sh-indent-after-open)))
-      )))
-
-(defun sh-handle-this-close ()
-  (forward-char 1) ;; move over ")"
-  (if (sh-safe-forward-sexp -1)
-      (list "aligned to opening paren")))
-
-(defun sh-goto-matching-case ()
-  (let ((found (sh-find-prev-matching "\\bcase\\b" "\\besac\\b" 1)))
-    (if found (goto-char found))))
-
-(defun sh-handle-prev-case ()
-  ;; This is typically called when point is on same line as a case
-  ;; we shouldn't -- and can't find prev-case
-  (if (looking-at ".*\\<case\\>")
-      (list '(+ sh-indent-for-case-label))
-    (error "We don't seem to be on a line with a case"))) ;; debug
-
-(defun sh-handle-this-esac ()
-  (if (sh-goto-matching-case)
-      (list "aligned to matching case")))
-
-(defun sh-handle-prev-esac ()
-  (if (sh-goto-matching-case)
-      (list "matching case")))
-
-(defun sh-handle-after-case-label ()
-  (if (sh-goto-matching-case)
-      (list '(+ sh-indent-for-case-alt))))
-
-(defun sh-handle-prev-case-alt-end ()
-  (if (sh-goto-matching-case)
-      (list '(+ sh-indent-for-case-label))))
-
-(defun sh-safe-forward-sexp (&optional arg)
-  "Try and do a `forward-sexp', but do not error.
-Return new point if successful, nil if an error occurred."
-  (condition-case nil
-      (progn
-       (forward-sexp (or arg 1))
-       (point))        ;; return point if successful
-    (error
-     (sh-debug "oops!(1) %d" (point))
-     nil))) ;; return nil if fail
-
-(defun sh-goto-match-for-done ()
-  (let ((found (sh-find-prev-matching sh-regexp-for-done sh-re-done 1)))
-    (if found
-       (goto-char found))))
-
-(defun sh-handle-this-done ()
-  (if (sh-goto-match-for-done)
-      (list  "aligned to do stmt"  '(+ sh-indent-for-done))))
-
-(defun sh-handle-prev-done ()
-  (if (sh-goto-match-for-done)
-      (list "previous done")))
-
-(defun sh-handle-this-do ()
-  (if (sh-goto-match-for-done)
-      (list '(+ sh-indent-for-do))))
-
-(defun sh-handle-prev-do ()
-  (cond
-   ((save-restriction
-      (narrow-to-region (point) (line-beginning-position))
-      (sh-goto-match-for-done))
-    (sh-debug "match for done found on THIS line")
-    (list '(+ sh-indent-after-loop-construct)))
-   ((sh-goto-match-for-done)
-    (sh-debug "match for done found on PREV line")
-    (list '(+ sh-indent-after-do)))
-   (t
-    (message "match for done NOT found")
-    nil)))
-
-;; for rc:
-(defun sh-find-prev-switch ()
-  "Find the line for the switch keyword matching this line's case keyword."
-  (re-search-backward "\\<switch\\>" nil t))
-
-(defun sh-handle-this-rc-case ()
-  (if (sh-find-prev-switch)
-      (list  '(+ sh-indent-after-switch))
-    ;; (list  '(+ sh-indent-for-case-label))
-    nil))
-
-(defun sh-handle-prev-rc-case ()
-  (list '(+ sh-indent-after-case)))
-
-(defun sh-check-rule (n thing)
-  (let ((rule (nth n (assoc thing sh-kw-alist)))
-       (val nil))
-    (if rule
-       (progn
-         (setq val (funcall rule))
-         (sh-debug "rule (%d) for %s at %d is %s\n-> returned %s"
-                   n thing (point) rule val)))
-    val))
-
-
-(defun sh-get-indent-info ()
-  "Return indent-info for this line.
-This is a list.  nil means the line is to be left as is.
-Otherwise it contains one or more of the following sublists:
-\(t NUMBER)   NUMBER is the base location in the buffer that indentation is
-            relative to.  If present, this is always the first of the
-            sublists.  The indentation of the line in question is
-            derived from the indentation of this point, possibly
-            modified by subsequent sublists.
-\(+ VAR)
-\(- VAR)      Get the value of variable VAR and add to or subtract from
-            the indentation calculated so far.
-\(= VAR)      Get the value of variable VAR and *replace* the
-            indentation with its value.  This only occurs for
-            special variables such as `sh-indent-comment'.
-STRING      This is ignored for the purposes of calculating
-            indentation, it is printed in certain cases to help show
-            what the indentation is based on."
-  ;; See comments before `sh-kw'.
-  (save-excursion
-    (let ((have-result nil)
-         this-kw
-         val
-         (result nil)
-         (align-point nil)
-         prev-line-end x)
-      (beginning-of-line)
-      ;; Note: setting result to t means we are done and will return nil.
-      ;;(This function never returns just t.)
-      (cond
-       ((or (nth 3 (syntax-ppss (point)))
-           (eq (get-text-property (point) 'face) 'sh-heredoc))
-       ;; String continuation -- don't indent
-       (setq result t)
-       (setq have-result t))
-       ((looking-at "\\s-*#")          ; was (equal this-kw "#")
-       (if (bobp)
-           (setq result t) ;; return nil if 1st line!
-         (setq result (list '(= sh-indent-comment)))
-         ;; we still need to get previous line in case
-         ;; sh-indent-comment is t (indent as normal)
-         (setq align-point (sh-prev-line nil))
-         (setq have-result nil)
-         ))
-       ) ;; cond
-
-      (unless have-result
-       ;; Continuation lines are handled specially
-       (if (sh-this-is-a-continuation)
-           (progn
-              (setq result
-                    (if (save-excursion
-                          (beginning-of-line)
-                          (not (memq (char-before (- (point) 2)) '(?\s ?\t))))
-                        ;; By convention, if the continuation \ is not
-                        ;; preceded by a SPC or a TAB it means that the line
-                        ;; is cut at a place where spaces cannot be freely
-                        ;; added/removed.  I.e. do not indent the line.
-                        (list '(= nil))
-                      ;; We assume the line being continued is already
-                      ;; properly indented...
-                      ;; (setq prev-line-end (sh-prev-line))
-                      (setq align-point (sh-prev-line nil))
-                      (list '(+ sh-indent-for-continuation))))
-             (setq have-result t))
-         (beginning-of-line)
-         (skip-chars-forward " \t")
-         (setq this-kw (sh-get-kw)))
-
-        ;; Handle "this" keyword:  first word on the line we're
-       ;; calculating indentation info for.
-       (if this-kw
-           (if (setq val (sh-check-rule 1 this-kw))
-               (progn
-                 (setq align-point (point))
-                 (sh-debug
-                  "this - setting align-point to %d" align-point)
-                 (setq result (append result val))
-                 (setq have-result t)
-                 ;; set prev-line to continue processing remainder
-                 ;; of this line as a previous line
-                 (setq prev-line-end (point))
-                 ))))
-
-      (unless have-result
-       (setq prev-line-end (sh-prev-line 'end)))
-
-      (if prev-line-end
-         (save-excursion
-           ;; We start off at beginning of this line.
-           ;; Scan previous statements while this is <=
-           ;; start of previous line.
-           (goto-char prev-line-end)
-           (setq x t)
-           (while (and x (setq x  (sh-prev-thing)))
-             (sh-debug "at %d x is: %s  result is: %s" (point) x result)
-             (cond
-              ((and (equal x ")")
-                    (equal (get-text-property (1- (point)) 'syntax-table)
-                           sh-st-punc))
-               (sh-debug "Case label) here")
-               (setq x 'case-label)
-               (if (setq val (sh-check-rule 2 x))
-                   (progn
-                     (setq result (append result val))
-                     (setq align-point (point))))
-               (or (bobp)
-                   (forward-char -1))
-               (skip-chars-forward "*0-9?[]a-z")
-               )
-              ((string-match "[])}]" x)
-               (setq x (sh-safe-forward-sexp -1))
-               (if x
-                   (progn
-                     (setq align-point (point))
-                     (setq result (append result
-                                          (list "aligned to opening paren")))
-                     )))
-              ((string-match "[[({]" x)
-               (sh-debug "Checking special thing: %s" x)
-               (if (setq val (sh-check-rule 2 x))
-                   (setq result (append result val)))
-               (forward-char -1)
-               (setq align-point (point)))
-              ((string-match "[\"'`]" x)
-               (sh-debug "Skipping back for %s" x)
-               ;; this was oops-2
-               (setq x (sh-safe-forward-sexp -1)))
-              ((stringp x)
-               (sh-debug "Checking string %s at %s" x (point))
-               (if (setq val (sh-check-rule 2 x))
-                   ;; (or (eq t (car val))
-                   ;; (eq t (car (car val))))
-                   (setq result (append result val)))
-               ;; not sure about this test Wed Jan 27 23:48:35 1999
-               (setq align-point (point))
-               (unless (bolp)
-                 (forward-char -1)))
-              (t
-               (error "Don't know what to do with %s" x))
-              )
-             ) ;; while
-           (sh-debug "result is %s" result)
-           )
-       (sh-debug "No prev line!")
-       (sh-debug "result: %s  align-point: %s" result align-point)
-       )
-
-      (if align-point
-         ;; was: (setq result (append result (list (list t align-point))))
-         (setq result (append  (list (list t align-point)) result))
-       )
-      (sh-debug "result is now: %s" result)
-
-      (or result
-         (setq result (list (if prev-line-end
-                                 (list t prev-line-end)
-                               (list '= 'sh-first-lines-indent)))))
-
-      (if (eq result t)
-         (setq result nil))
-      (sh-debug  "result is: %s" result)
-      result
-      )        ;; let
-    ))
-
-
-(defun sh-get-indent-var-for-line (&optional info)
-  "Return the variable controlling indentation for this line.
-If there is not [just] one such variable, return a string
-indicating the problem.
-If INFO is supplied it is used, else it is calculated."
-  (let ((var nil)
-       (result nil)
-       (reason nil)
-       sym elt)
-    (or info
-       (setq info (sh-get-indent-info)))
-    (if (null info)
-       (setq result "this line to be left as is")
-      (while (and info (null result))
-       (setq elt (car info))
-       (cond
-        ((stringp elt)
-         (setq reason elt)
-         )
-        ((not (listp elt))
-         (error "sh-get-indent-var-for-line invalid elt: %s" elt))
-        ;; so it is a list
-        ((eq t (car elt))
-         ) ;; nothing
-        ((symbolp  (setq sym (nth 1 elt)))
-         ;; A bit of a kludge - when we see the sh-indent-comment
-         ;; ignore other variables.  Otherwise it is tricky to
-         ;; "learn" the comment indentation.
-         (if (eq var 'sh-indent-comment)
-             (setq result var)
-           (if var
-               (setq result
-                     "this line is controlled by more than 1 variable.")
-             (setq var sym))))
-        (t
-         (error "sh-get-indent-var-for-line invalid list elt: %s" elt)))
-       (setq info (cdr info))
-       ))
-    (or result
-       (setq result var))
-    (or result
-       (setq result reason))
-    (if (null result)
-       ;; e.g. just had (t POS)
-       (setq result "line has default indentation"))
-    result))
-
-
-
-;; Finding the previous line isn't trivial.
-;; We must *always* go back one more and see if that is a continuation
-;; line -- it is the PREVIOUS line which is continued, not the one
-;; we are going to!
-;; Also, we want to treat a whole "here document" as one big line,
-;; because we may want to align to the beginning of it.
-;;
-;; What we do:
-;; - go back to previous non-empty line
-;; - if this is in a here-document, go to the beginning of it
-;; - while previous line is continued, go back one line
-(defun sh-prev-line (&optional end)
-  "Back to end of previous non-comment non-empty line.
-Go to beginning of logical line unless END is non-nil, in which case
-we go to the end of the previous line and do not check for continuations."
-  (save-excursion
-    (beginning-of-line)
-    (forward-comment (- (point-max)))
-    (unless end (beginning-of-line))
-    (when (and (not (bobp))
-              (eq (get-text-property (1- (point)) 'face) 'sh-heredoc))
-      (let ((p1 (previous-single-property-change (1- (point)) 'face)))
-       (when p1
-         (goto-char p1)
-         (if end
-             (end-of-line)
-           (beginning-of-line)))))
-    (unless end
-      ;; we must check previous lines to see if they are continuation lines
-      ;; if so, we must return position of first of them
-      (while (and (sh-this-is-a-continuation)
-                 (>= 0 (forward-line -1))))
-      (beginning-of-line)
-      (skip-chars-forward " \t"))
-    (point)))
-
-
-(defun sh-prev-stmt ()
-  "Return the address of the previous stmt or nil."
-  ;; This is used when we are trying to find a matching keyword.
-  ;; Searching backward for the keyword would certainly be quicker, but
-  ;; it is hard to remove "false matches" -- such as if the keyword
-  ;; appears in a string or quote.  This way is slower, but (I think) safer.
-  (interactive)
-  (save-excursion
-    (let ((going t)
-         (start (point))
-         (found nil)
-         (prev nil))
-      (skip-chars-backward " \t;|&({[")
-      (while (and (not found)
-                 (not (bobp))
-                 going)
-       ;; Do a backward-sexp if possible, else backup bit by bit...
-       (if (sh-safe-forward-sexp -1)
-           (progn
-             (if (looking-at sh-special-keywords)
-                 (progn
-                   (setq found prev))
-               (setq prev (point))
-               ))
-         ;; backward-sexp failed
-         (if (zerop (skip-chars-backward " \t()[]{};`'"))
-             (forward-char -1))
-         (if (bolp)
-             (let ((back (sh-prev-line nil)))
-               (if back
-                   (goto-char back)
-                 (setq going nil)))))
-       (unless found
-         (skip-chars-backward " \t")
-         (if (or (and (bolp) (not (sh-this-is-a-continuation)))
-                 (eq (char-before) ?\;)
-                 (looking-at "\\s-*[|&]"))
-             (setq found (point)))))
-      (if found
-         (goto-char found))
-      (if found
-         (progn
-           (skip-chars-forward " \t|&({[")
-           (setq found (point))))
-      (if (>= (point) start)
-         (progn
-           (debug "We didn't move!")
-           (setq found nil))
-       (or found
-           (sh-debug "Did not find prev stmt.")))
-      found)))
-
-
-(defun sh-get-word ()
-  "Get a shell word skipping whitespace from point."
-  (interactive)
-  (skip-chars-forward "\t ")
-  (let ((start (point)))
-    (while
-       (if (looking-at "[\"'`]")
-           (sh-safe-forward-sexp)
-         ;; (> (skip-chars-forward "^ \t\n\"'`") 0)
-         (> (skip-chars-forward "-_$[:alnum:]") 0)
-         ))
-    (buffer-substring start (point))
-    ))
-
-(defun sh-prev-thing ()
-  "Return the previous thing this logical line."
-  ;; This is called when `sh-get-indent-info' is working backwards on
-  ;; the previous line(s) finding what keywords may be relevant for
-  ;; indenting.  It moves over sexps if possible, and will stop
-  ;; on a ; and at the beginning of a line if it is not a continuation
-  ;; line.
-  ;;
-  ;; Added a kludge for ";;"
-  ;; Possible return values:
-  ;;  nil  -  nothing
-  ;; a string - possibly a keyword
-  ;;
-  (if (bolp)
-      nil
-    (let ((start (point))
-          (min-point (if (sh-this-is-a-continuation)
-                         (sh-prev-line nil)
-                       (line-beginning-position))))
-      (skip-chars-backward " \t;" min-point)
-      (if (looking-at "\\s-*;[;&]")
-          ;; (message "Found ;; !")
-          ";;"
-        (skip-chars-backward "^)}];\"'`({[" min-point)
-        (let ((c (if (> (point) min-point) (char-before))))
-          (sh-debug "stopping at %d c is %s  start=%d min-point=%d"
-                    (point) c start min-point)
-          (if (not (memq c '(?\n nil ?\;)))
-              ;; c     -- return a string
-              (char-to-string c)
-            ;; Return the leading keyword of the "command" we supposedly
-            ;; skipped over.  Maybe we skipped too far (e.g. past a `do' or
-            ;; `then' that precedes the actual command), so check whether
-            ;; we're looking at such a keyword and if so, move back forward.
-            (let ((boundary (point))
-                  kwd next)
-              (while
-                  (progn
-                    ;; Skip forward over white space newline and \ at eol.
-                    (skip-chars-forward " \t\n\\\\" start)
-                    (if (>= (point) start)
-                        (progn
-                          (sh-debug "point: %d >= start: %d" (point) start)
-                          nil)
-                      (if next (setq boundary next))
-                      (sh-debug "Now at %d   start=%d" (point) start)
-                      (setq kwd (sh-get-word))
-                      (if (member kwd (sh-feature sh-leading-keywords))
-                          (progn
-                            (setq next (point))
-                            t)
-                        nil))))
-              (goto-char boundary)
-              kwd)))))))
-
-
-(defun sh-this-is-a-continuation ()
-  "Return non-nil if current line is a continuation of previous line."
-  (save-excursion
-    (and (zerop (forward-line -1))
-        (looking-at ".*\\\\$")
-        (not (nth 4 (parse-partial-sexp (match-beginning 0) (match-end 0)
-                                        nil nil nil t))))))
-
-(defun sh-get-kw (&optional where and-move)
-  "Return first word of line from WHERE.
-If AND-MOVE is non-nil then move to end of word."
-  (let ((start (point)))
-    (if where
-       (goto-char where))
-    (prog1
-       (buffer-substring (point)
-                         (progn (skip-chars-forward "^ \t\n;&|")(point)))
-      (unless and-move
-       (goto-char start)))))
-
-(defun sh-find-prev-matching (open close &optional depth)
-  "Find a matching token for a set of opening and closing keywords.
-This takes into account that there may be nested open..close pairings.
-OPEN and CLOSE are regexps denoting the tokens to be matched.
-Optional parameter DEPTH (usually 1) says how many to look for."
-  (let ((parse-sexp-ignore-comments t)
-        (forward-sexp-function nil)
-       prev)
-    (setq depth (or depth 1))
-    (save-excursion
-      (condition-case nil
-         (while (and
-                 (/= 0  depth)
-                 (not (bobp))
-                 (setq prev (sh-prev-stmt)))
-           (goto-char prev)
-           (save-excursion
-             (if (looking-at "\\\\\n")
-                 (progn
-                   (forward-char 2)
-                   (skip-chars-forward " \t")))
-             (cond
-              ((looking-at open)
-               (setq depth (1- depth))
-               (sh-debug "found open at %d - depth = %d" (point) depth))
-              ((looking-at close)
-               (setq depth (1+ depth))
-               (sh-debug "found close - depth = %d" depth))
-              (t
-               ))))
-       (error nil))
-      (if (eq depth 0)
-         prev ;; (point)
-       nil)
-      )))
-
 
 (defun sh-var-value (var &optional ignore-error)
   "Return the value of variable VAR, interpreting symbols.
@@ -3268,620 +2466,16 @@ IGNORE-ERROR is non-nil."
                "Don't know how to handle %s's value of %s" var val)
       0))))
 
-(defun sh-set-var-value (var value &optional no-symbol)
-  "Set variable VAR to VALUE.
-Unless optional argument NO-SYMBOL is non-nil, then if VALUE is
-can be represented by a symbol then do so."
-  (cond
-   (no-symbol
-    (set var value))
-   ((= value sh-basic-offset)
-    (set var '+))
-   ((= value (- sh-basic-offset))
-    (set var '-))
-   ((eq value (* 2 sh-basic-offset))
-    (set var  '++))
-   ((eq value (* 2 (- sh-basic-offset)))
-    (set var  '--))
-   ((eq value (/ sh-basic-offset 2))
-    (set var  '*))
-   ((eq value (/ (- sh-basic-offset) 2))
-    (set var  '/))
-   (t
-    (set var value)))
-  )
-
-
-(defun sh-calculate-indent (&optional info)
-  "Return the indentation for the current line.
-If INFO is supplied it is used, else it is calculated from current line."
-  (let ((ofs 0)
-       (base-value 0)
-       elt a b val)
-    (or info
-       (setq info (sh-get-indent-info)))
-    (when info
-      (while info
-       (sh-debug "info: %s  ofs=%s" info ofs)
-       (setq elt (car info))
-       (cond
-        ((stringp elt)) ;; do nothing?
-        ((listp elt)
-         (setq a (car (car info)))
-         (setq b (nth 1 (car info)))
-         (cond
-          ((eq a t)
-           (save-excursion
-             (goto-char b)
-             (setq val (current-indentation)))
-           (setq base-value val))
-          ((symbolp b)
-           (setq val (sh-var-value b))
-           (cond
-            ((eq a '=)
-             (cond
-              ((null val)
-               ;; no indentation
-               ;; set info to nil so  we stop immediately
-               (setq base-value nil  ofs nil  info nil))
-              ((eq val t) (setq ofs 0)) ;; indent as normal line
-              (t
-               ;; The following assume the (t POS) come first!
-               (setq ofs val  base-value 0)
-               (setq info nil))))      ;; ? stop now
-            ((eq a '+) (setq ofs (+ ofs val)))
-            ((eq a '-) (setq ofs (- ofs val)))
-            (t
-             (error "sh-calculate-indent invalid a a=%s b=%s" a b))))
-          (t
-           (error "sh-calculate-indent invalid elt: a=%s b=%s" a b))))
-        (t
-         (error "sh-calculate-indent invalid elt %s" elt)))
-       (sh-debug "a=%s b=%s val=%s base-value=%s ofs=%s"
-                 a b val base-value ofs)
-       (setq info (cdr info)))
-      ;; return value:
-      (sh-debug "at end:  base-value: %s    ofs: %s" base-value ofs)
-
-      (cond
-       ((or (null base-value)(null ofs))
-       nil)
-       ((and (numberp base-value)(numberp ofs))
-       (sh-debug "base (%d) + ofs (%d) = %d"
-                 base-value ofs (+ base-value ofs))
-       (+ base-value ofs)) ;; return value
-       (t
-       (error "sh-calculate-indent:  Help.  base-value=%s ofs=%s"
-              base-value ofs)
-       nil)))))
+(define-obsolete-function-alias 'sh-show-indent
+  #'smie-config-show-indent "28.1")
 
+(define-obsolete-function-alias 'sh-set-indent #'smie-config-set-indent "28.1")
 
-(defun sh-indent-line ()
-  "Indent the current line."
-  (interactive)
-  (let ((indent (sh-calculate-indent))
-       (pos (- (point-max) (point))))
-    (when indent
-      (beginning-of-line)
-      (skip-chars-forward " \t")
-      (indent-line-to indent)
-      ;; If initial point was within line's indentation,
-      ;; position after the indentation.  Else stay at same point in text.
-      (if (> (- (point-max) pos) (point))
-         (goto-char (- (point-max) pos))))))
-
-
-(defun sh-blink (blinkpos &optional msg)
-  "Move cursor momentarily to BLINKPOS and display MSG."
-  ;; We can get here without it being a number on first line
-  (if (numberp blinkpos)
-      (save-excursion
-       (goto-char blinkpos)
-       (if msg (message "%s" msg) (message nil))
-       (sit-for blink-matching-delay))
-    (if msg (message "%s" msg) (message nil))))
-
-(defun sh-show-indent (arg)
-  "Show how the current line would be indented.
-This tells you which variable, if any, controls the indentation of
-this line.
-If optional arg ARG is non-null (called interactively with a prefix),
-a pop up window describes this variable.
-If variable `sh-blink' is non-nil then momentarily go to the line
-we are indenting relative to, if applicable."
-  (interactive "P")
-  (sh-must-support-indent)
-  (if sh-use-smie
-      (smie-config-show-indent)
-    (let* ((info (sh-get-indent-info))
-           (var (sh-get-indent-var-for-line info))
-           (curr-indent (current-indentation))
-           val msg)
-      (if (stringp var)
-          (message "%s" (setq msg var))
-        (setq val (sh-calculate-indent info))
-
-        (if (eq curr-indent val)
-            (setq msg (format "%s is %s" var (symbol-value var)))
-          (setq msg
-                (if val
-                    (format "%s (%s) would change indent from %d to: %d"
-                            var (symbol-value var) curr-indent val)
-                  (format "%s (%s) would leave line as is"
-                          var (symbol-value var)))
-                ))
-        (if (and arg var)
-            (describe-variable var)))
-      (if sh-blink
-          (let ((info (sh-get-indent-info)))
-            (if (and info (listp (car info))
-                     (eq (car (car info)) t))
-                (sh-blink (nth 1 (car info))  msg)
-              (message "%s" msg)))
-        (message "%s" msg))
-      )))
+(define-obsolete-function-alias 'sh-learn-line-indent
+  #'smie-config-set-indent "28.1")
 
-(defun sh-set-indent ()
-  "Set the indentation for the current line.
-If the current line is controlled by an indentation variable, prompt
-for a new value for it."
-  (interactive)
-  (sh-must-support-indent)
-  (if sh-use-smie
-      (smie-config-set-indent)
-    (let* ((info (sh-get-indent-info))
-           (var (sh-get-indent-var-for-line info))
-           val old-val indent-val)
-      (if (stringp var)
-          (message "Cannot set indent - %s" var)
-        (setq old-val (symbol-value var))
-        (setq val (sh-read-variable var))
-        (condition-case nil
-            (progn
-              (set var val)
-              (setq indent-val (sh-calculate-indent info))
-              (if indent-val
-                  (message "Variable: %s  Value: %s  would indent to: %d"
-                           var (symbol-value var) indent-val)
-                (message "Variable: %s  Value: %s  would leave line as is."
-                         var (symbol-value var)))
-              ;; I'm not sure about this, indenting it now?
-              ;; No.  Because it would give the impression that an undo would
-              ;; restore thing, but the value has been altered.
-              ;; (sh-indent-line)
-              )
-          (error
-           (set var old-val)
-           (message "Bad value for %s, restoring to previous value %s"
-                    var old-val)
-           (sit-for 1)
-           nil))
-        ))))
-
-
-(defun sh-learn-line-indent (arg)
-  "Learn how to indent a line as it currently is indented.
-
-If there is an indentation variable which controls this line's indentation,
-then set it to a value which would indent the line the way it
-presently is.
-
-If the value can be represented by one of the symbols then do so
-unless optional argument ARG (the prefix when interactive) is non-nil."
-  (interactive "*P")
-  (sh-must-support-indent)
-  (if sh-use-smie
-      (smie-config-set-indent)
-    ;; I'm not sure if we show allow learning on an empty line.
-    ;; Though it might occasionally be useful I think it usually
-    ;; would just be confusing.
-    (if (save-excursion
-          (beginning-of-line)
-          (looking-at "\\s-*$"))
-        (message "sh-learn-line-indent ignores empty lines.")
-      (let* ((info (sh-get-indent-info))
-             (var (sh-get-indent-var-for-line info))
-             ival sval diff new-val
-             (no-symbol arg)
-             (curr-indent (current-indentation)))
-        (cond
-         ((stringp var)
-          (message "Cannot learn line - %s" var))
-         ((eq var 'sh-indent-comment)
-          ;; This is arbitrary...
-          ;; - if curr-indent is 0, set to curr-indent
-          ;; - else if it has the indentation of a "normal" line,
-          ;;   then set to t
-          ;; - else set to curr-indent.
-          (setq sh-indent-comment
-                (if (= curr-indent 0)
-                    0
-                  (let* ((sh-indent-comment t)
-                         (val2 (sh-calculate-indent info)))
-                    (if (= val2 curr-indent)
-                        t
-                      curr-indent))))
-          (message "%s set to %s" var (symbol-value var))
-          )
-         ((numberp (setq sval (sh-var-value var)))
-          (setq ival (sh-calculate-indent info))
-          (setq diff (- curr-indent ival))
-
-          (sh-debug "curr-indent: %d   ival: %d  diff: %d  var:%s  sval %s"
-                    curr-indent ival diff  var sval)
-          (setq new-val (+ sval diff))
-          ;; I commented out this because someone might want to replace
-          ;; a value of `+' with the current value of sh-basic-offset
-          ;; or vice-versa.
-          ;;(if (= 0 diff)
-          ;;     (message "No change needed!")
-          (sh-set-var-value var new-val no-symbol)
-          (message "%s set to %s" var (symbol-value var))
-          )
-         (t
-          (debug)
-          (message "Cannot change %s" var)))))))
-
-
-
-(defun sh-mark-init (buffer)
-  "Initialize a BUFFER to be used by `sh-mark-line'."
-  (with-current-buffer (get-buffer-create buffer)
-    (erase-buffer)
-    (occur-mode)))
-
-
-(defun sh-mark-line (message point buffer &optional add-linenum occur-point)
-  "Insert MESSAGE referring to location POINT in current buffer into BUFFER.
-Buffer BUFFER is in `occur-mode'.
-If ADD-LINENUM is non-nil the message is preceded by the line number.
-If OCCUR-POINT is non-nil then the line is marked as a new occurrence
-so that `occur-next' and `occur-prev' will work."
-  (let ((m1 (make-marker))
-       start
-       (line ""))
-    (when point
-      (set-marker m1 point (current-buffer))
-      (if add-linenum
-         (setq line (format "%d: " (1+ (count-lines 1 point))))))
-    (save-excursion
-      (if (get-buffer buffer)
-         (set-buffer (get-buffer buffer))
-       (set-buffer (get-buffer-create buffer))
-       (occur-mode)
-       )
-      (goto-char (point-max))
-      (setq start (point))
-      (let ((inhibit-read-only t))
-        (insert line)
-        (if occur-point
-            (setq occur-point (point)))
-        (insert message)
-        (if point
-            (add-text-properties
-             start (point)
-             '(mouse-face highlight
-                          help-echo "mouse-2: go to the line where I learned 
this")))
-        (insert "\n")
-        (when point
-          (put-text-property start (point) 'occur-target m1)
-          (if occur-point
-              (put-text-property start occur-point
-                                 'occur-match t))
-          )))))
-
-;; Is this really worth having?
-(defvar sh-learned-buffer-hook nil
-  "An abnormal hook, called with an alist of learned variables.")
-;; Example of how to use sh-learned-buffer-hook
-;;
-;; (defun what-i-learned (list)
-;;   (let ((p list))
-;;     (with-current-buffer "*scratch*"
-;;       (goto-char (point-max))
-;;       (insert "(setq\n")
-;;       (while p
-;;     (insert (format "  %s %s \n"
-;;                     (nth 0 (car p)) (nth 1 (car p))))
-;;     (setq p (cdr p)))
-;;       (insert ")\n")
-;;       )))
-;;
-;; (add-hook 'sh-learned-buffer-hook #'what-i-learned)
-
-
-;; Originally this was sh-learn-region-indent (beg end)
-;; However, in practice this was awkward so I changed it to
-;; use the whole buffer.  Use narrowing if need be.
-(defun sh-learn-buffer-indent (&optional arg)
-  "Learn how to indent the buffer the way it currently is.
-
-If `sh-use-smie' is non-nil, call `smie-config-guess'.
-Otherwise, run the sh-script specific indent learning command, as
-described below.
-
-Output in buffer \"*indent*\" shows any lines which have conflicting
-values of a variable, and the final value of all variables learned.
-When called interactively, pop to this buffer automatically if
-there are any discrepancies.
-
-If no prefix ARG is given, then variables are set to numbers.
-If a prefix arg is given, then variables are set to symbols when
-applicable -- e.g. to symbol `+' if the value is that of the
-basic indent.
-If a positive numerical prefix is given, then  `sh-basic-offset'
-is set to the prefix's numerical value.
-Otherwise, sh-basic-offset may or may not be changed, according
-to the value of variable `sh-learn-basic-offset'.
-
-Abnormal hook `sh-learned-buffer-hook' if non-nil is called when the
-function completes.  The function is abnormal because it is called
-with an alist of variables learned.
-
-This command can often take a long time to run."
-  (interactive "P")
-  (sh-must-support-indent)
-  (if sh-use-smie
-      (smie-config-guess)
-    (save-excursion
-      (goto-char (point-min))
-      (let ((learned-var-list nil)
-            (out-buffer "*indent*")
-            (num-diffs 0)
-            previous-set-info
-            (max 17)
-            vec
-            msg
-            (comment-col nil) ;; number if all same, t if seen diff values
-            (comments-always-default t) ;; nil if we see one not default
-            initial-msg
-            (specified-basic-offset (and arg (numberp arg)
-                                         (> arg 0)))
-            (linenum 0)
-            suggested)
-        (setq vec (make-vector max 0))
-        (sh-mark-init out-buffer)
-
-        (if specified-basic-offset
-            (progn
-              (setq sh-basic-offset arg)
-              (setq initial-msg
-                    (format "Using specified sh-basic-offset of %d"
-                            sh-basic-offset)))
-          (setq initial-msg
-                (format "Initial value of sh-basic-offset: %s"
-                        sh-basic-offset)))
-
-        (while (< (point) (point-max))
-          (setq linenum (1+ linenum))
-          ;; (if (zerop (% linenum 10))
-          (message "line %d" linenum)
-          ;; )
-          (unless (looking-at "\\s-*$") ;; ignore empty lines!
-            (let* ((sh-indent-comment t) ;; info must return default indent
-                   (info (sh-get-indent-info))
-                   (var (sh-get-indent-var-for-line info))
-                   sval ival diff new-val
-                   (curr-indent (current-indentation)))
-              (cond
-               ((null var)
-                nil)
-               ((stringp var)
-                nil)
-               ((numberp (setq sval (sh-var-value var 'no-error)))
-                ;; the numberp excludes comments since sval will be t.
-                (setq ival (sh-calculate-indent))
-                (setq diff (- curr-indent ival))
-                (setq new-val (+ sval diff))
-                (sh-set-var-value var new-val 'no-symbol)
-                (unless (looking-at "\\s-*#") ;; don't learn from comments
-                  (if (setq previous-set-info (assoc var learned-var-list))
-                      (progn
-                        ;; it was already there, is it same value ?
-                        (unless (eq (symbol-value var)
-                                    (nth 1 previous-set-info))
-                          (sh-mark-line
-                           (format "Variable %s was set to %s"
-                                   var (symbol-value var))
-                           (point) out-buffer t t)
-                          (sh-mark-line
-                           (format "  but was previously set to %s"
-                                   (nth 1 previous-set-info))
-                           (nth 2 previous-set-info) out-buffer t)
-                          (setq num-diffs (1+ num-diffs))
-                          ;; (delete previous-set-info  learned-var-list)
-                          (setcdr previous-set-info
-                                  (list (symbol-value var) (point)))
-                          )
-                        )
-                    (setq learned-var-list
-                          (append (list (list var (symbol-value var)
-                                              (point)))
-                                  learned-var-list)))
-                  (if (numberp new-val)
-                      (progn
-                        (sh-debug
-                         "This line's indent value: %d"  new-val)
-                        (if (< new-val 0)
-                            (setq new-val (- new-val)))
-                        (if (< new-val max)
-                            (aset vec new-val (1+ (aref vec new-val))))))
-                  ))
-               ((eq var 'sh-indent-comment)
-                (unless (= curr-indent (sh-calculate-indent info))
-                  ;; this is not the default indentation
-                  (setq comments-always-default nil)
-                  (if comment-col ;; then we have see one before
-                      (or (eq comment-col curr-indent)
-                          (setq comment-col t)) ;; seen a different one
-                    (setq comment-col curr-indent))
-                  ))
-               (t
-                (sh-debug "Cannot learn this line!!!")
-                ))
-              (sh-debug
-               "at %s learned-var-list is %s" (point) learned-var-list)
-              ))
-          (forward-line 1)
-          ) ;; while
-        (if sh-debug
-            (progn
-              (setq msg (format
-                         "comment-col = %s  comments-always-default = %s"
-                         comment-col comments-always-default))
-              ;; (message msg)
-              (sh-mark-line  msg nil out-buffer)))
-        (cond
-         ((eq comment-col 0)
-          (setq msg  "\nComments are all in 1st column.\n"))
-         (comments-always-default
-          (setq msg  "\nComments follow default indentation.\n")
-          (setq comment-col t))
-         ((numberp comment-col)
-          (setq msg  (format "\nComments are in col %d." comment-col)))
-         (t
-          (setq msg  "\nComments seem to be mixed, leaving them as is.\n")
-          (setq comment-col nil)
-          ))
-        (sh-debug msg)
-        (sh-mark-line  msg nil out-buffer)
-
-        (sh-mark-line initial-msg nil out-buffer t t)
-
-        (setq suggested (sh-guess-basic-offset vec))
-
-        (if (and suggested (not specified-basic-offset))
-            (let ((new-value
-                   (cond
-                    ;; t => set it if we have a single value as a number
-                    ((and (eq sh-learn-basic-offset t) (numberp suggested))
-                     suggested)
-                    ;; other non-nil => set it if only one value was found
-                    (sh-learn-basic-offset
-                     (if (numberp suggested)
-                         suggested
-                       (if (= (length suggested) 1)
-                           (car suggested))))
-                    (t
-                     nil))))
-              (if new-value
-                  (progn
-                    (setq learned-var-list
-                          (append (list (list 'sh-basic-offset
-                                              (setq sh-basic-offset new-value)
-                                              (point-max)))
-                                  learned-var-list))
-                    ;; Not sure if we need to put this line in, since
-                    ;; it will appear in the "Learned variable settings".
-                    (sh-mark-line
-                     (format "Changed sh-basic-offset to: %d" sh-basic-offset)
-                     nil out-buffer))
-                (sh-mark-line
-                 (if (listp suggested)
-                     (format "Possible value(s) for sh-basic-offset:  %s"
-                             (mapconcat 'int-to-string suggested " "))
-                   (format "Suggested sh-basic-offset:  %d" suggested))
-                 nil out-buffer))))
-
-
-        (setq learned-var-list
-              (append (list (list 'sh-indent-comment comment-col (point-max)))
-                      learned-var-list))
-        (setq sh-indent-comment comment-col)
-        (let ((name (buffer-name)))
-          (sh-mark-line  "\nLearned variable settings:" nil out-buffer)
-          (if arg
-              ;; Set learned variables to symbolic rather than numeric
-              ;; values where possible.
-              (dolist (learned-var (reverse learned-var-list))
-                (let ((var (car learned-var))
-                      (val (nth 1 learned-var)))
-                  (when (and (not (eq var 'sh-basic-offset))
-                             (numberp val))
-                    (sh-set-var-value var val)))))
-          (dolist (learned-var (reverse learned-var-list))
-            (let ((var (car learned-var)))
-              (sh-mark-line (format "  %s %s" var (symbol-value var))
-                            (nth 2 learned-var) out-buffer)))
-          (with-current-buffer out-buffer
-            (goto-char (point-min))
-            (let ((inhibit-read-only t))
-              (insert
-               (format "Indentation values for buffer %s.\n" name)
-               (format "%d indentation variable%s different values%s\n\n"
-                       num-diffs
-                       (if (= num-diffs 1)
-                           " has"   "s have")
-                       (if (zerop num-diffs)
-                           "." ":"))))))
-        (run-hook-with-args 'sh-learned-buffer-hook learned-var-list)
-        (and (called-interactively-p 'any)
-             (or sh-popup-occur-buffer (> num-diffs 0))
-             (pop-to-buffer out-buffer))))))
-
-(defun sh-guess-basic-offset (vec)
-  "See if we can determine a reasonable value for `sh-basic-offset'.
-This is experimental, heuristic and arbitrary!
-Argument VEC is a vector of information collected by
-`sh-learn-buffer-indent'.
-Return values:
-  number          - there appears to be a good single value
-  list of numbers - no obvious one, here is a list of one or more
-                   reasonable choices
-  nil            - we couldn't find a reasonable one."
-  (let* ((max (1- (length vec)))
-        (i 1)
-        (totals (make-vector max 0)))
-    (while (< i max)
-      (cl-incf (aref totals i) (* 4 (aref vec i)))
-      (if (zerop (% i 2))
-         (cl-incf (aref totals i) (aref vec (/ i 2))))
-      (if (< (* i 2) max)
-         (cl-incf (aref totals i) (aref vec (* i 2))))
-      (setq i (1+ i)))
-
-    (let ((x nil)
-         (result nil)
-         tot sum p)
-      (setq i 1)
-      (while (< i max)
-       (if (/= (aref totals i) 0)
-           (push (cons i (aref totals i)) x))
-       (setq i (1+ i)))
-
-      (setq x (sort (nreverse x) (lambda (a b) (> (cdr a) (cdr b)))))
-      (setq tot (apply '+ (append totals nil)))
-      (sh-debug (format "vec: %s\ntotals: %s\ntot: %d"
-                       vec totals tot))
-      (cond
-       ((zerop (length x))
-       (message "no values!")) ;; we return nil
-       ((= (length x) 1)
-       (message "only value is %d" (car (car x)))
-       (setq result (car (car x)))) ;; return single value
-       ((> (cdr (car x)) (/ tot 2))
-       ;; 1st is > 50%
-       (message "basic-offset is probably %d" (car (car x)))
-       (setq result (car (car x)))) ;;   again, return a single value
-       ((>=  (cdr (car x)) (* 2 (cdr (car (cdr x)))))
-       ;; 1st is >= 2 * 2nd
-       (message "basic-offset could be %d" (car (car x)))
-       (setq result (car (car x))))
-       ((>= (+ (cdr (car x))(cdr (car (cdr x)))) (/ tot 2))
-       ;; 1st & 2nd together >= 50%  - return a list
-       (setq p x  sum 0 result nil)
-       (while  (and p
-                    (<= (setq sum (+ sum (cdr (car p)))) (/ tot 2)))
-         (setq result (append result (list (car (car p)))))
-         (setq p (cdr p)))
-       (message "Possible choices for sh-basic-offset: %s"
-                (mapconcat 'int-to-string result " ")))
-       (t
-       (message "No obvious value for sh-basic-offset.  Perhaps %d"
-                (car (car x)))
-       ;; result is nil here
-       ))
-      result)))
+(define-obsolete-function-alias 'sh-learn-buffer-indent
+  #'smie-config-guess "28.1")
 
 ;; ========================================================================
 
diff --git a/lisp/progmodes/vhdl-mode.el b/lisp/progmodes/vhdl-mode.el
index b225a9b..0677d36 100644
--- a/lisp/progmodes/vhdl-mode.el
+++ b/lisp/progmodes/vhdl-mode.el
@@ -16148,7 +16148,7 @@ expansion function)."
 
 ;; initialize speedbar
 (if (not (boundp 'speedbar-frame))
-    (add-hook 'speedbar-load-hook 'vhdl-speedbar-initialize)
+    (with-no-warnings (add-hook 'speedbar-load-hook 'vhdl-speedbar-initialize))
   (vhdl-speedbar-initialize)
   (when speedbar-frame (vhdl-speedbar-refresh)))
 
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index a8ca6f8..1a34456 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -287,6 +287,10 @@ recognize and then delegate the work to an external 
process."
 (cl-defgeneric xref-backend-identifier-completion-table (backend)
   "Return the completion table for identifiers.")
 
+(cl-defgeneric xref-backend-identifier-completion-ignore-case (_backend)
+  "Return t if case is not significant in identifier completion."
+  completion-ignore-case)
+
 
 ;;; misc utilities
 (defun xref--alistify (list key test)
@@ -967,7 +971,9 @@ Accepts the same arguments as `xref-show-xrefs-function'."
 (defun xref--read-identifier (prompt)
   "Return the identifier at point or read it from the minibuffer."
   (let* ((backend (xref-find-backend))
-         (def (xref-backend-identifier-at-point backend)))
+         (def (xref-backend-identifier-at-point backend))
+         (completion-ignore-case
+          (xref-backend-identifier-completion-ignore-case backend)))
     (cond ((or current-prefix-arg
                (not def)
                (xref--prompt-p this-command))
@@ -1218,6 +1224,9 @@ IGNORES is a list of glob patterns for files to ignore."
   #'xref-matches-in-directory
   "27.1")
 
+(declare-function tramp-tramp-file-p "tramp")
+(declare-function tramp-file-local-name "tramp")
+
 ;;;###autoload
 (defun xref-matches-in-files (regexp files)
   "Find all matches for REGEXP in FILES.
@@ -1240,7 +1249,12 @@ FILES must be a list of absolute file names."
                           "")
                         (shell-quote-argument (xref--regexp-to-extended 
regexp)))))
     (when remote-id
-      (setq files (mapcar #'file-local-name files)))
+      (require 'tramp)
+      (setq files (mapcar
+                   (if (tramp-tramp-file-p dir)
+                       #'tramp-file-local-name
+                       #'file-local-name)
+                   files)))
     (with-current-buffer output
       (erase-buffer)
       (with-temp-buffer
diff --git a/lisp/recentf.el b/lisp/recentf.el
index b636e59..27918a9 100644
--- a/lisp/recentf.el
+++ b/lisp/recentf.el
@@ -277,6 +277,8 @@ If `file-name-history' is not empty, do nothing."
    "Normal hook run at end of loading the `recentf' package."
   :group 'recentf
   :type 'hook)
+(make-obsolete-variable 'recentf-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defcustom recentf-filename-handlers nil
   "Functions to post process recent file names.
diff --git a/lisp/sb-image.el b/lisp/sb-image.el
deleted file mode 100644
index 1e8b105..0000000
--- a/lisp/sb-image.el
+++ /dev/null
@@ -1,107 +0,0 @@
-;;; sb-image --- Image management for speedbar
-
-;; Copyright (C) 1999-2003, 2005-2020 Free Software Foundation, Inc.
-
-;; Author: Eric M. Ludlam <address@hidden>
-;; Keywords: file, tags, 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:
-;;
-;; Supporting Image display for Emacs 20 and less, Emacs 21, and XEmacs,
-;; is a challenging task, which doesn't take kindly to being byte compiled.
-;; When sharing speedbar.elc between these three applications, the Image
-;; support can get lost.
-;;
-;; By splitting out that hard part into this file, and avoiding byte
-;; compilation, one copy speedbar can support all these platforms together.
-;;
-;; This file requires the `image' package if it is available.
-
-(require 'ezimage)
-
-;;; Code:
-(defcustom speedbar-use-images ezimage-use-images
-  "Non-nil if speedbar should display icons."
-  :group 'speedbar
-  :version "21.1"
-  :type 'boolean)
-
-(defalias 'defimage-speedbar 'defezimage)
-
-(defvar speedbar-expand-image-button-alist
-  '(("<+>" . ezimage-directory-plus)
-    ("<->" . ezimage-directory-minus)
-    ("< >" . ezimage-directory)
-    ("[+]" . ezimage-page-plus)
-    ("[-]" . ezimage-page-minus)
-    ("[?]" . ezimage-page)
-    ("[ ]" . ezimage-page)
-    ("{+}" . ezimage-box-plus)
-    ("{-}" . ezimage-box-minus)
-    ("<M>" . ezimage-mail)
-    ("<d>" . ezimage-document-tag)
-    ("<i>" . ezimage-info-tag)
-    (" =>" . ezimage-tag)
-    (" +>" . ezimage-tag-gt)
-    (" ->" . ezimage-tag-v)
-    (">"   . ezimage-tag)
-    ("@"   . ezimage-tag-type)
-    ("  @" . ezimage-tag-type)
-    ("*"   . ezimage-checkout)
-    ("#"   . ezimage-object)
-    ("!"   . ezimage-object-out-of-date)
-    ("//"  . ezimage-label)
-    ("%"   . ezimage-lock)
-    )
-  "List of text and image associations.")
-
-(defun speedbar-insert-image-button-maybe (start length)
-  "Insert an image button based on text starting at START for LENGTH chars.
-If buttontext is unknown, just insert that text.
-If we have an image associated with it, use that image."
-  (when speedbar-use-images
-    (let ((ezimage-expand-image-button-alist
-          speedbar-expand-image-button-alist))
-      (ezimage-insert-image-button-maybe start length))))
-
-(defun speedbar-image-dump ()
-  "Dump out the current state of the Speedbar image alist.
-See `speedbar-expand-image-button-alist' for details."
-  (interactive)
-  (with-output-to-temp-buffer "*Speedbar Images*"
-    (with-current-buffer "*Speedbar Images*"
-      (goto-char (point-max))
-      (insert "Speedbar image cache.\n\n")
-      (let ((start (point)) (end nil))
-       (insert "Image\tText\tImage Name")
-       (setq end (point))
-       (insert "\n")
-       (put-text-property start end 'face 'underline))
-      (let ((ia speedbar-expand-image-button-alist))
-       (while ia
-         (let ((start (point)))
-           (insert (car (car ia)))
-           (insert "\t")
-           (speedbar-insert-image-button-maybe start
-                                               (length (car (car ia))))
-           (insert (car (car ia)) "\t" (format "%s" (cdr (car ia))) "\n"))
-         (setq ia (cdr ia)))))))
-
-(provide 'sb-image)
-
-;;; sb-image.el ends here
diff --git a/lisp/shell.el b/lisp/shell.el
index 98e830e..ecebf93 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -428,7 +428,7 @@ Thus, this does not include the shell's current directory.")
     (save-excursion
       (goto-char begin)
       (while (< (point) end)
-       (skip-chars-forward " \t\n")
+       (skip-chars-forward " \t\n;")
        (push (point) begins)
         (let ((arg ()))
           (while (looking-at
diff --git a/lisp/simple.el b/lisp/simple.el
index f9f1efc..0944790 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -503,9 +503,7 @@ This hook is run by `delete-selection-uses-region-p', which 
see.")
 
 (defun newline (&optional arg interactive)
   "Insert a newline, and move to left margin of the new line if it's blank.
-If option `use-hard-newlines' is non-nil, the newline is marked with the
-text-property `hard'.
-With ARG, insert that many newlines.
+With prefix argument ARG, insert that many newlines.
 
 If `electric-indent-mode' is enabled, this indents the final new line
 that it adds, and reindents the preceding line.  To just insert
@@ -514,6 +512,9 @@ a newline, use \\[electric-indent-just-newline].
 If `auto-fill-mode' is enabled, this may cause automatic line
 breaking of the preceding line.  A non-nil ARG inhibits this.
 
+If `use-hard-newlines' is enabled, the newline is marked with the
+text-property `hard'.
+
 A non-nil INTERACTIVE argument means to run the `post-self-insert-hook'."
   (interactive "*P\np")
   (barf-if-buffer-read-only)
@@ -1787,23 +1788,36 @@ to get different commands to edit and resubmit."
             ;; and it serves as a shorthand for "Extended command: ".
             "M-x ")
      (lambda (string pred action)
-       (let ((pred
-              (if (memq action '(nil t))
-                  ;; Exclude obsolete commands from completions.
-                  (lambda (sym)
-                    (and (funcall pred sym)
-                         (or (equal string (symbol-name sym))
-                             (not (get sym 'byte-obsolete-info)))))
-                pred)))
-         (complete-with-action action obarray string pred)))
+       (if (and suggest-key-bindings (eq action 'metadata))
+          '(metadata
+            (annotation-function . read-extended-command--annotation)
+            (category . command))
+         (let ((pred
+                (if (memq action '(nil t))
+                    ;; Exclude obsolete commands from completions.
+                    (lambda (sym)
+                      (and (funcall pred sym)
+                           (or (equal string (symbol-name sym))
+                               (not (get sym 'byte-obsolete-info)))))
+                  pred)))
+           (complete-with-action action obarray string pred))))
      #'commandp t nil 'extended-command-history)))
 
+(defun read-extended-command--annotation (command-name)
+  (let* ((function (and (stringp command-name) (intern-soft command-name)))
+         (binding (where-is-internal function overriding-local-map t)))
+    (when (and binding (not (stringp binding)))
+      (format " (%s)" (key-description binding)))))
+
 (defcustom suggest-key-bindings t
   "Non-nil means show the equivalent key-binding when M-x command has one.
 The value can be a length of time to show the message for.
 If the value is non-nil and not a number, we wait 2 seconds.
 
-Also see `extended-command-suggest-shorter'."
+Also see `extended-command-suggest-shorter'.
+
+Equivalent key-bindings are also shown in the completion list of
+M-x for all commands that have them."
   :group 'keyboard
   :type '(choice (const :tag "off" nil)
                  (integer :tag "time" 2)
@@ -3436,19 +3450,28 @@ This affects `shell-command' and `async-shell-command'."
   :version "27.1")
 
 (defcustom shell-command-dont-erase-buffer nil
-  "If non-nil, output buffer is not erased between shell commands.
-Also, a non-nil value sets the point in the output buffer
-once the command completes.
+  "Control if the output buffer is erased before the command.
+
+A nil value erases the output buffer before execution of the
+shell command, except when the output buffer is the current one.
+
+The value `erase' ensures the output buffer is erased before
+execution of the shell command.
+
+Other non-nil values prevent the output buffer from being erased and
+set the point after execution of the shell command.
+
 The value `beg-last-out' sets point at the beginning of the output,
 `end-last-out' sets point at the end of the buffer, `save-point'
 restores the buffer position before the command."
   :type '(choice
-          (const :tag "Erase buffer" nil)
+          (const :tag "Erase output buffer if not the current one" nil)
+          (const :tag "Always erase output buffer" erase)
           (const :tag "Set point to beginning of last output" beg-last-out)
           (const :tag "Set point to end of last output" end-last-out)
           (const :tag "Save point" save-point))
   :group 'shell
-  :version "26.1")
+  :version "27.1")
 
 (defvar shell-command-saved-pos nil
   "Record of point positions in output buffers after command completion.
@@ -3457,8 +3480,11 @@ where BUFFER is the output buffer, and POS is the point 
position
 in BUFFER once the command finishes.
 This variable is used when `shell-command-dont-erase-buffer' is non-nil.")
 
-(defun shell-command--save-pos-or-erase ()
+(defun shell-command-save-pos-or-erase (&optional output-to-current-buffer)
   "Store a buffer position or erase the buffer.
+Optional argument OUTPUT-TO-CURRENT-BUFFER, if non-nil, means that the output
+of the shell command goes to the caller current buffer.
+
 See `shell-command-dont-erase-buffer'."
   (let ((sym shell-command-dont-erase-buffer)
         pos)
@@ -3469,7 +3495,9 @@ See `shell-command-dont-erase-buffer'."
     (setq pos
           (cond ((eq sym 'save-point) (point))
                 ((eq sym 'beg-last-out) (point-max))
-                ((not sym)
+                ;;((not sym)
+                ((or (eq sym 'erase)
+                     (and (null sym) (not output-to-current-buffer)))
                  (let ((inhibit-read-only t))
                    (erase-buffer) nil))))
     (when pos
@@ -3477,7 +3505,7 @@ See `shell-command-dont-erase-buffer'."
       (push (cons (current-buffer) pos)
             shell-command-saved-pos))))
 
-(defun shell-command--set-point-after-cmd (&optional buffer)
+(defun shell-command-set-point-after-cmd (&optional buffer)
   "Set point in BUFFER after command complete.
 BUFFER is the output buffer of the command; if nil, then defaults
 to the current BUFFER.
@@ -3492,12 +3520,18 @@ whose `car' is BUFFER."
       (when (buffer-live-p buf)
         (let ((win   (car (get-buffer-window-list buf)))
               (pmax  (with-current-buffer buf (point-max))))
-          (unless (and pos (memq sym '(save-point beg-last-out)))
+
+          ;; The first time we run a command in a freshly created buffer
+          ;; we have not saved positions yet; advance to `point-max', so that
+          ;; successive commands know where to start.
+          (unless (and pos (memq sym '(save-point beg-last-out end-last-out)))
             (setq pos pmax))
           ;; Set point in the window displaying buf, if any; otherwise
           ;; display buf temporary in selected frame and set the point.
           (if win
               (set-window-point win pos)
+            (when pos
+              (with-current-buffer buf (goto-char pos)))
             (save-window-excursion
               (let ((win (display-buffer
                           buf
@@ -3625,8 +3659,11 @@ impose the use of a shell (with its need to quote 
arguments)."
     (if handler
        (funcall handler 'shell-command command output-buffer error-buffer)
       (if (and output-buffer
-              (not (or (bufferp output-buffer)  (stringp output-buffer))))
-         ;; Output goes in current buffer.
+               (not (string-match "[ \t]*&[ \t]*\\'" command))
+               (or (eq output-buffer (current-buffer))
+                   (and (stringp output-buffer) (eq (get-buffer output-buffer) 
(current-buffer)))
+                  (not (or (bufferp output-buffer) (stringp output-buffer))))) 
; Bug#39067
+         ;; Synchronous command with output in current buffer.
          (let ((error-file
                  (and error-buffer
                       (make-temp-file
@@ -3635,6 +3672,7 @@ impose the use of a shell (with its need to quote 
arguments)."
                                              temporary-file-directory))))))
            (barf-if-buffer-read-only)
            (push-mark nil t)
+            (shell-command-save-pos-or-erase 'output-to-current-buffer)
            ;; We do not use -f for csh; we will not support broken use of
            ;; .cshrcs.  Even the BSD csh manual says to use
            ;; "if ($?prompt) exit" before things that are not useful
@@ -3663,7 +3701,8 @@ impose the use of a shell (with its need to quote 
arguments)."
            ;; because we inserted text.
            (goto-char (prog1 (mark t)
                         (set-marker (mark-marker) (point)
-                                    (current-buffer)))))
+                                    (current-buffer))))
+            (shell-command-set-point-after-cmd))
        ;; Output goes in a separate buffer.
        ;; Preserve the match data in case called from a program.
         ;; FIXME: It'd be ridiculous for an Elisp function to call
@@ -3708,7 +3747,7 @@ impose the use of a shell (with its need to quote 
arguments)."
                      (rename-uniquely))
                     (setq buffer (get-buffer-create bname)))))
                (with-current-buffer buffer
-                  (shell-command--save-pos-or-erase)
+                  (shell-command-save-pos-or-erase)
                  (setq default-directory directory)
                  (let ((process-environment
                         (if (natnump async-shell-command-width)
@@ -3814,7 +3853,7 @@ and are used only if a pop-up buffer is displayed."
 ;; `shell-command-dont-erase-buffer' is non-nil.
 (defun shell-command-sentinel (process signal)
   (when (memq (process-status process) '(exit signal))
-    (shell-command--set-point-after-cmd (process-buffer process))
+    (shell-command-set-point-after-cmd (process-buffer process))
     (message "%s: %s."
              (car (cdr (cdr (process-command process))))
              (substring signal 0 -1))))
@@ -3933,7 +3972,7 @@ interactively, this is t."
           (set-buffer-major-mode buffer) ; Enable globalized modes (bug#38111)
           (unwind-protect
               (if (and (eq buffer (current-buffer))
-                       (or (not shell-command-dont-erase-buffer)
+                       (or (memq shell-command-dont-erase-buffer '(nil erase))
                            (and (not (eq buffer (get-buffer "*Shell Command 
Output*")))
                                 (not (region-active-p)))))
                   ;; If the input is the same buffer as the output,
@@ -3956,7 +3995,7 @@ interactively, this is t."
                   (with-current-buffer buffer
                     (if (not output-buffer)
                         (setq default-directory directory))
-                    (shell-command--save-pos-or-erase)))
+                    (shell-command-save-pos-or-erase)))
                 (setq exit-status
                       (call-shell-region start end command nil
                                            (if error-file
@@ -3975,7 +4014,7 @@ interactively, this is t."
                 ;; There's some output, display it
                 (progn
                   (display-message-or-buffer buffer)
-                  (shell-command--set-point-after-cmd buffer))
+                  (shell-command-set-point-after-cmd buffer))
             ;; No output; error?
               (let ((output
                      (if (and error-file
@@ -8953,7 +8992,7 @@ and setting it to nil."
 
 (defun messages-buffer ()
   "Return the \"*Messages*\" buffer.
-If it does not exist, create and it switch it to `messages-buffer-mode'."
+If it does not exist, create it and switch it to `messages-buffer-mode'."
   (or (get-buffer "*Messages*")
       (with-current-buffer (get-buffer-create "*Messages*")
         (messages-buffer-mode)
diff --git a/lisp/so-long.el b/lisp/so-long.el
index dcf7e62..6b05f48 100644
--- a/lisp/so-long.el
+++ b/lisp/so-long.el
@@ -353,7 +353,7 @@
 ;; this caveat is the `mode' pseudo-variable, which is processed early in all
 ;; versions of Emacs, and can be set to `so-long-mode' if desired.
 
-;;; * Change Log:
+;; * Change Log:
 ;;
 ;; 1.0   - Included in Emacs 27.1, and in GNU ELPA for prior versions of Emacs.
 ;;       - New global mode `global-so-long-mode' to enable/disable the library.
@@ -944,8 +944,10 @@ This command calls `so-long' with the selected action as 
an argument.")
     (cl-letf (((symbol-function 'finder-summary) #'ignore))
       (finder-commentary "so-long"))
     (let ((inhibit-read-only t))
-      (when (looking-at "^Commentary:\n\n")
-        (replace-match "so-long.el\n\n"))
+      (if (looking-at "^Commentary:\n\n")
+          (replace-match "so-long.el\n\n")
+        (insert "so-long.el\n")
+        (forward-line 1))
       (save-excursion
         (while (re-search-forward "^-+$" nil :noerror)
           (replace-match ""))))
diff --git a/lisp/speedbar.el b/lisp/speedbar.el
index 646f328..faa0bcc 100644
--- a/lisp/speedbar.el
+++ b/lisp/speedbar.el
@@ -115,7 +115,7 @@ this version is not backward compatible to 0.14 or 
earlier.")
 
 (require 'easymenu)
 (require 'dframe)
-(require 'sb-image)
+(require 'ezimage)
 
 ;; customization stuff
 (defgroup speedbar nil
@@ -141,6 +141,12 @@ this version is not backward compatible to 0.14 or 
earlier.")
   :prefix "speedbar-"
   :group 'speedbar)
 
+(defcustom speedbar-use-images ezimage-use-images
+  "Non-nil if speedbar should display icons."
+  :group 'speedbar
+  :version "21.1"
+  :type 'boolean)
+
 ;;; Code:
 
 ;; Note: `inversion-test' requires parts of the CEDET package that are
@@ -296,6 +302,8 @@ The default buffer is the buffer in the selected window in 
the attached frame."
   "Hooks run when speedbar is loaded."
   :group 'speedbar
   :type 'hook)
+(make-obsolete-variable 'speedbar-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defcustom speedbar-reconfigure-keymaps-hook nil
   "Hooks run when the keymaps are regenerated."
@@ -1703,7 +1711,7 @@ argument."
       (put-text-property start end 'help-echo #'dframe-help-echo))
   (if function (put-text-property start end 'speedbar-function function))
   (if token (put-text-property start end 'speedbar-token token))
-  ;; So far the only text we have is less that 3 chars.
+  ;; So far the only text we have is less than 3 chars.
   (if (<= (- end start) 3)
       (speedbar-insert-image-button-maybe start (- end start)))
   )
@@ -4022,6 +4030,68 @@ TEXT is the buffer's name, TOKEN and INDENT are unused."
         (setq font-lock-global-modes (delq 'speedbar-mode
                                            font-lock-global-modes)))))
 
+;;; Image management
+
+(defvar speedbar-expand-image-button-alist
+  '(("<+>" . ezimage-directory-plus)
+    ("<->" . ezimage-directory-minus)
+    ("< >" . ezimage-directory)
+    ("[+]" . ezimage-page-plus)
+    ("[-]" . ezimage-page-minus)
+    ("[?]" . ezimage-page)
+    ("[ ]" . ezimage-page)
+    ("{+}" . ezimage-box-plus)
+    ("{-}" . ezimage-box-minus)
+    ("<M>" . ezimage-mail)
+    ("<d>" . ezimage-document-tag)
+    ("<i>" . ezimage-info-tag)
+    (" =>" . ezimage-tag)
+    (" +>" . ezimage-tag-gt)
+    (" ->" . ezimage-tag-v)
+    (">"   . ezimage-tag)
+    ("@"   . ezimage-tag-type)
+    ("  @" . ezimage-tag-type)
+    ("*"   . ezimage-checkout)
+    ("#"   . ezimage-object)
+    ("!"   . ezimage-object-out-of-date)
+    ("//"  . ezimage-label)
+    ("%"   . ezimage-lock)
+    )
+  "List of text and image associations.")
+
+(defun speedbar-insert-image-button-maybe (start length)
+  "Insert an image button based on text starting at START for LENGTH chars.
+If buttontext is unknown, just insert that text.
+If we have an image associated with it, use that image."
+  (when speedbar-use-images
+    (let ((ezimage-expand-image-button-alist
+          speedbar-expand-image-button-alist))
+      (ezimage-insert-image-button-maybe start length))))
+
+(defun speedbar-image-dump ()
+  "Dump out the current state of the Speedbar image alist.
+See `speedbar-expand-image-button-alist' for details."
+  (interactive)
+  (with-output-to-temp-buffer "*Speedbar Images*"
+    (with-current-buffer "*Speedbar Images*"
+      (goto-char (point-max))
+      (insert "Speedbar image cache.\n\n")
+      (let ((start (point)) (end nil))
+       (insert "Image\tText\tImage Name")
+       (setq end (point))
+       (insert "\n")
+       (put-text-property start end 'face 'underline))
+      (let ((ia speedbar-expand-image-button-alist))
+       (while ia
+         (let ((start (point)))
+           (insert (car (car ia)))
+           (insert "\t")
+           (speedbar-insert-image-button-maybe start
+                                               (length (car (car ia))))
+           (insert (car (car ia)) "\t" (format "%s" (cdr (car ia))) "\n"))
+         (setq ia (cdr ia)))))))
+
+
 (provide 'speedbar)
 
 ;; run load-time hooks
diff --git a/lisp/startup.el b/lisp/startup.el
index c27af72..1f545c6 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -497,28 +497,28 @@ DIRS are relative."
 (defvar startup--xdg-config-home-emacs)
 
 ;; Return the name of the init file directory for Emacs, assuming
-;; XDG-DIR is the XDG location and USER-NAME is the user name.
-;; If USER-NAME is nil or "", use the current user.
-;; Prefer the XDG location unless it does does not exist and the
-;; .emacs.d location does exist.
+;; XDG-DIR is the XDG location and USER-NAME is the user name.  If
+;; USER-NAME is nil or "", use the current user.  Prefer the XDG
+;; location only if the .emacs.d location does not exist.
 (defun startup--xdg-or-homedot (xdg-dir user-name)
-  (if (file-exists-p xdg-dir)
-      xdg-dir
-    (let ((emacs-d-dir (concat "~" user-name
-                              (if (eq system-type 'ms-dos)
-                                  "/_emacs.d/"
-                                "/.emacs.d/"))))
-      (if (or (file-exists-p emacs-d-dir)
-             (if (eq system-type 'windows-nt)
-                  (if (file-directory-p (concat "~" user-name))
-                      (directory-files (concat "~" user-name) nil
-                                       "\\`[._]emacs\\(\\.elc?\\)?\\'"))
-               (file-exists-p (concat "~" init-file-user
-                                      (if (eq system-type 'ms-dos)
-                                          "/_emacs"
-                                        "/.emacs")))))
-         emacs-d-dir
-       xdg-dir))))
+  (let ((emacs-d-dir (concat "~" user-name
+                             (if (eq system-type 'ms-dos)
+                                 "/_emacs.d/"
+                               "/.emacs.d/"))))
+    (cond
+     ((or (file-exists-p emacs-d-dir)
+          (if (eq system-type 'windows-nt)
+              (if (file-directory-p (concat "~" user-name))
+                  (directory-files (concat "~" user-name) nil
+                                   "\\`[._]emacs\\(\\.elc?\\)?\\'"))
+            (file-exists-p (concat "~" init-file-user
+                                   (if (eq system-type 'ms-dos)
+                                       "/_emacs"
+                                     "/.emacs")))))
+      emacs-d-dir)
+     ((file-exists-p xdg-dir)
+      xdg-dir)
+     (t emacs-d-dir))))
 
 (defun normal-top-level ()
   "Emacs calls this function when it first starts up.
@@ -1435,8 +1435,7 @@ please check its value")
   (if (get-buffer "*scratch*")
       (with-current-buffer "*scratch*"
        (if (eq major-mode 'fundamental-mode)
-           (funcall initial-major-mode))
-        (setq-local lexical-binding t)))
+           (funcall initial-major-mode))))
 
   ;; Load library for our terminal type.
   ;; User init file can set term-file-prefix to nil to prevent this.
@@ -2317,7 +2316,6 @@ A fancy display is used on graphic displays, normal 
otherwise."
   (or (get-buffer "*scratch*")
       (with-current-buffer (get-buffer-create "*scratch*")
         (set-buffer-major-mode (current-buffer))
-        (setq-local lexical-binding t)
         (current-buffer))))
 
 (defun command-line-1 (args-left)
diff --git a/lisp/strokes.el b/lisp/strokes.el
index 7a88744..7c00305 100644
--- a/lisp/strokes.el
+++ b/lisp/strokes.el
@@ -296,6 +296,8 @@ the corresponding interactive function.")
 
 (defvar strokes-load-hook nil
   "Functions to be called when Strokes is loaded.")
+(make-obsolete-variable 'strokes-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 ;;; ### NOT IMPLEMENTED YET ###
 ;;(defvar edit-strokes-menu
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index e4ff732..ebb0c56 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -319,6 +319,8 @@ from all windows in the window configuration."
                         tab-bar-tab-name-current)
                  (const :tag "Selected window buffer with window count"
                         tab-bar-tab-name-current-with-count)
+                 (const :tag "Truncated buffer name"
+                        tab-bar-tab-name-truncated)
                  (const :tag "All window buffers"
                         tab-bar-tab-name-all)
                  (function  :tag "Function"))
@@ -350,6 +352,29 @@ Also add the number of windows in the window 
configuration."
                                                  'nomini)))
              ", "))
 
+(defcustom tab-bar-tab-name-truncated-max 20
+  "Maximum length of the tab name from the current buffer.
+Effective when `tab-bar-tab-name-function' is customized
+to `tab-bar-tab-name-truncated'."
+  :type 'integer
+  :group 'tab-bar
+  :version "27.1")
+
+(defvar tab-bar-tab-name-ellipsis
+  (if (char-displayable-p ?…) "…" "..."))
+
+(defun tab-bar-tab-name-truncated ()
+  "Generate tab name from the buffer of the selected window.
+Truncate it to the length specified by `tab-bar-tab-name-truncated-max'.
+Append ellipsis `tab-bar-tab-name-ellipsis' in this case."
+  (let ((tab-name (buffer-name (window-buffer (minibuffer-selected-window)))))
+    (if (< (length tab-name) tab-bar-tab-name-truncated-max)
+        tab-name
+      (propertize (truncate-string-to-width
+                   tab-name tab-bar-tab-name-truncated-max nil nil
+                   tab-bar-tab-name-ellipsis)
+                  'help-echo tab-name))))
+
 
 (defvar tab-bar-tabs-function #'tab-bar-tabs
   "Function to get a list of tabs to display in the tab bar.
@@ -697,11 +722,14 @@ Interactively, ARG selects the ARGth different frame to 
move to."
 If `leftmost', create as the first tab.
 If `left', create to the left from the current tab.
 If `right', create to the right from the current tab.
-If `rightmost', create as the last tab."
+If `rightmost', create as the last tab.
+If the value is a function, it should return a number as a position
+on the tab bar specifying where to insert a new tab."
   :type '(choice (const :tag "First tab" leftmost)
                  (const :tag "To the left" left)
                  (const :tag "To the right" right)
-                 (const :tag "Last tab" rightmost))
+                 (const :tag "Last tab" rightmost)
+                 (function :tag "Function"))
   :group 'tab-bar
   :version "27.1")
 
@@ -748,7 +776,9 @@ After the tab is created, the hooks in
                           ('leftmost 0)
                           ('rightmost (length tabs))
                           ('left (1- (or from-index 1)))
-                          ('right (1+ (or from-index 0)))))))
+                          ('right (1+ (or from-index 0)))
+                          ((pred functionp)
+                           (funcall tab-bar-new-tab-to))))))
       (setq to-index (max 0 (min (or to-index 0) (length tabs))))
       (cl-pushnew to-tab (nthcdr to-index tabs))
 
@@ -1093,7 +1123,7 @@ function `tab-bar-tab-name-function'."
 
 (define-minor-mode tab-bar-history-mode
   "Toggle tab history mode for the tab bar."
-  :global t
+  :global t :group 'tab-bar
   (if tab-bar-history-mode
       (progn
         (when (and tab-bar-mode (not (get-text-property 0 'display 
tab-bar-back-button)))
@@ -1370,7 +1400,7 @@ in the selected frame."
    ((framep all-frames) (list all-frames))
    (t (list (selected-frame)))))
 
-(defun tab-bar-get-buffer-tab (buffer-or-name &optional all-frames)
+(defun tab-bar-get-buffer-tab (buffer-or-name &optional all-frames 
ignore-current-tab)
   "Return a tab owning a window whose buffer is BUFFER-OR-NAME.
 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
 the current buffer.
@@ -1384,7 +1414,10 @@ The optional argument ALL-FRAMES specifies the frames to 
consider:
 - A frame means consider all tabs on that frame only.
 
 Any other value of ALL-FRAMES means consider all tabs on the
-selected frame and no others."
+selected frame and no others.
+
+When the optional argument IGNORE-CURRENT-TAB is non-nil,
+don't take into account the buffers in the currently selected tab."
   (let ((buffer (if buffer-or-name
                     (get-buffer buffer-or-name)
                   (current-buffer))))
@@ -1394,7 +1427,8 @@ selected frame and no others."
          (seq-some
           (lambda (tab)
             (when (if (eq (car tab) 'current-tab)
-                      (get-buffer-window buffer frame)
+                      (unless ignore-current-tab
+                        (get-buffer-window buffer frame))
                     (let* ((state (alist-get 'ws tab))
                            (buffers (when state
                                       (window-state-buffers state))))
diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 8e561c7..149fe82 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -81,9 +81,7 @@
   '((default
       :inherit tab-line-tab)
     (((class color) (min-colors 88))
-     :background "grey85")
-    (t
-     :inverse-video t))
+     :background "grey85"))
   "Tab line face for tab with current buffer in selected window."
   :version "27.1"
   :group 'tab-line-faces)
@@ -215,9 +213,6 @@ If nil, don't show it at all."
 
 (defvar tab-line-separator nil)
 
-(defvar tab-line-tab-name-ellipsis
-  (if (char-displayable-p ?…) "…" "..."))
-
 
 (defcustom tab-line-tab-name-function #'tab-line-tab-name-buffer
   "Function to get a tab name.
@@ -242,23 +237,30 @@ This function can be overridden by changing the default 
value of the
 variable `tab-line-tab-name-function'."
   (buffer-name buffer))
 
-(defun tab-line-tab-name-truncated-buffer (buffer &optional buffers)
+(defcustom tab-line-tab-name-truncated-max 20
+  "Maximum length of the tab name from the current buffer.
+Effective when `tab-line-tab-name-function' is customized
+to `tab-line-tab-name-truncated-buffer'."
+  :type 'integer
+  :group 'tab-line
+  :version "27.1")
+
+(defvar tab-line-tab-name-ellipsis
+  (if (char-displayable-p ?…) "…" "..."))
+
+(defun tab-line-tab-name-truncated-buffer (buffer &optional _buffers)
   "Generate tab name from BUFFER.
-Reduce tab width proportionally to space taken by other tabs."
-  (let ((tab-name (buffer-name buffer))
-        (limit (when buffers
-                 (max 1 (- (/ (window-width) (length buffers)) 3)))))
-    (if (or (not limit) (< (length tab-name) limit))
+Truncate it to the length specified by `tab-line-tab-name-truncated-max'.
+Append ellipsis `tab-line-tab-name-ellipsis' in this case."
+  (let ((tab-name (buffer-name buffer)))
+    (if (< (length tab-name) tab-line-tab-name-truncated-max)
         tab-name
-      (propertize (truncate-string-to-width tab-name limit nil nil
-                                            tab-line-tab-name-ellipsis)
+      (propertize (truncate-string-to-width
+                   tab-name tab-line-tab-name-truncated-max nil nil
+                   tab-line-tab-name-ellipsis)
                   'help-echo tab-name))))
 
 
-(defvar tab-line-tabs-limit nil
-  "Maximum number of buffer tabs displayed in the tab line.
-If nil, no limit.")
-
 (defcustom tab-line-tabs-function #'tab-line-tabs-window-buffers
   "Function to get a list of tabs to display in the tab line.
 This function should return either a list of buffers whose names will
@@ -397,22 +399,9 @@ variable `tab-line-tabs-function'."
          (prev-buffers (seq-filter #'buffer-live-p prev-buffers))
          ;; Remove next-buffers from prev-buffers
          (prev-buffers (seq-difference prev-buffers next-buffers)))
-    (if (natnump tab-line-tabs-limit)
-        (let* ((half-limit (/ tab-line-tabs-limit 2))
-               (prev-buffers-limit
-                (if (> (length prev-buffers) half-limit)
-                    (if (> (length next-buffers) half-limit)
-                        half-limit
-                      (+ half-limit (- half-limit (length next-buffers))))
-                  (length prev-buffers)))
-               (next-buffers-limit
-                (- tab-line-tabs-limit prev-buffers-limit)))
-          (append (reverse (seq-take prev-buffers prev-buffers-limit))
-                  (list buffer)
-                  (seq-take next-buffers next-buffers-limit)))
-      (append (reverse prev-buffers)
-              (list buffer)
-              next-buffers))))
+    (append (reverse prev-buffers)
+            (list buffer)
+            next-buffers)))
 
 
 (defun tab-line-format-template (tabs)
@@ -522,12 +511,14 @@ the selected tab visible."
             (add-face-text-property (point-min) (point-max) 'tab-line)
             (if (> (vertical-motion 1) 0)
                 (let* ((point (previous-single-property-change (point) 'tab))
-                       (tab-prop (or (get-pos-property point 'tab)
-                                     (get-pos-property
-                                      (previous-single-property-change point 
'tab) 'tab)))
-                       (new-hscroll (seq-position strings tab-prop
-                                                  (lambda (str tab)
-                                                    (eq (get-pos-property 1 
'tab str) tab)))))
+                       (tab-prop (when point
+                                   (or (get-pos-property point 'tab)
+                                       (and (setq point 
(previous-single-property-change point 'tab))
+                                            (get-pos-property point 'tab)))))
+                       (new-hscroll (when tab-prop
+                                      (seq-position strings tab-prop
+                                                    (lambda (str tab)
+                                                      (eq (get-pos-property 1 
'tab str) tab))))))
                   (when new-hscroll
                     (setq hscroll (- new-hscroll))
                     (set-window-parameter nil 'tab-line-hscroll hscroll)))
@@ -547,12 +538,14 @@ the selected tab visible."
               (add-face-text-property (point-min) (point-max) 'tab-line)
               (when (> (vertical-motion 1) 0)
                 (let* ((point (previous-single-property-change (point) 'tab))
-                       (tab-prop (or (get-pos-property point 'tab)
-                                     (get-pos-property
-                                      (previous-single-property-change point 
'tab) 'tab)))
-                       (new-hscroll (seq-position strings tab-prop
-                                                  (lambda (str tab)
-                                                    (eq (get-pos-property 1 
'tab str) tab)))))
+                       (tab-prop (when point
+                                   (or (get-pos-property point 'tab)
+                                       (and (setq point 
(previous-single-property-change point 'tab))
+                                            (get-pos-property point 'tab)))))
+                       (new-hscroll (when tab-prop
+                                      (seq-position strings tab-prop
+                                                    (lambda (str tab)
+                                                      (eq (get-pos-property 1 
'tab str) tab))))))
                   (when new-hscroll
                     (setq hscroll (- new-hscroll))
                     (set-window-parameter nil 'tab-line-hscroll 
hscroll)))))))))
@@ -679,15 +672,17 @@ Its effect is the same as using the `next-buffer' command
             (switch-to-buffer buffer)))))))
 
 
-(defcustom tab-line-close-tab-action 'bury-buffer
+(defcustom tab-line-close-tab-function 'bury-buffer
   "Defines what to do on closing the tab.
 If `bury-buffer', put the tab's buffer at the end of the list of all
 buffers that effectively hides the buffer's tab from the tab line.
 If `kill-buffer', kills the tab's buffer.
+When a function, it is called with the tab as its argument.
 This option is useful when `tab-line-tabs-function' has the value
 `tab-line-tabs-window-buffers'."
   :type '(choice (const :tag "Bury buffer" bury-buffer)
-                 (const :tag "Kill buffer" kill-buffer))
+                 (const :tag "Kill buffer" kill-buffer)
+                 (function :tag "Function"))
   :group 'tab-line
   :version "27.1")
 
@@ -701,18 +696,20 @@ from the tab line."
          (window (and posnp (posn-window posnp)))
          (tab (get-pos-property 1 'tab (car (posn-string posnp))))
          (buffer (if (bufferp tab) tab (cdr (assq 'buffer tab))))
-         (close-action (unless (bufferp tab) (cdr (assq 'close tab)))))
+         (close-function (unless (bufferp tab) (cdr (assq 'close tab)))))
     (with-selected-window (or window (selected-window))
       (cond
-       ((functionp close-action)
-        (funcall close-action))
-       ((eq tab-line-close-tab-action 'kill-buffer)
+       ((functionp close-function)
+        (funcall close-function))
+       ((eq tab-line-close-tab-function 'kill-buffer)
         (kill-buffer buffer))
-       ((eq tab-line-close-tab-action 'bury-buffer)
+       ((eq tab-line-close-tab-function 'bury-buffer)
         (if (eq buffer (current-buffer))
             (bury-buffer)
           (set-window-prev-buffers nil (assq-delete-all buffer 
(window-prev-buffers)))
-          (set-window-next-buffers nil (delq buffer (window-next-buffers))))))
+          (set-window-next-buffers nil (delq buffer (window-next-buffers)))))
+       ((functionp tab-line-close-tab-function)
+        (funcall tab-line-close-tab-function tab)))
       (force-mode-line-update))))
 
 
diff --git a/lisp/textmodes/dns-mode.el b/lisp/textmodes/dns-mode.el
index 3bdea94..6dfea8f 100644
--- a/lisp/textmodes/dns-mode.el
+++ b/lisp/textmodes/dns-mode.el
@@ -134,6 +134,7 @@ manually with \\[dns-mode-soa-increment-serial]."
   :type '(choice (const :tag "Always" t)
                 (const :tag "Ask" ask)
                 (const :tag "Never" nil))
+  :safe 'symbolp
   :group 'dns-mode)
 
 ;; Syntax table.
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index 53a4543..a9fbd2f 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -1951,18 +1951,7 @@ quit          spell session exited."
       (or quietly
          (message "Checking spelling of %s..."
                   (funcall ispell-format-word-function word)))
-      (ispell-send-string "%\n")       ; put in verbose mode
-      (ispell-send-string (concat "^" word "\n"))
-      ;; wait until ispell has processed word
-      (while (progn
-              (ispell-accept-output)
-              (not (string= "" (car ispell-filter)))))
-      ;;(ispell-send-string "!\n") ;back to terse mode.
-      (setq ispell-filter (cdr ispell-filter)) ; remove extra \n
-      (if (and ispell-filter (listp ispell-filter))
-         (if (> (length ispell-filter) 1)
-             (error "Ispell and its process have different character maps")
-           (setq poss (ispell-parse-output (car ispell-filter)))))
+      (setq poss (ispell--run-on-word word))
       (cond ((eq poss t)
             (or quietly
                 (message "%s is correct"
@@ -2024,6 +2013,43 @@ quit          spell session exited."
       (goto-char cursor-location)      ; return to original location
       replace))))
 
+(defun ispell--run-on-word (word)
+  "Run ispell on WORD."
+  (ispell-send-string "%\n")   ; Put the speller in verbose mode.
+  (ispell-send-string (concat "^" word "\n"))
+  ;; wait until ispell has processed word
+  (while (progn
+           (ispell-accept-output)
+           (not (string= "" (car ispell-filter)))))
+  (setq ispell-filter (cdr ispell-filter))
+  (when (and ispell-filter (listp ispell-filter))
+    (if (> (length ispell-filter) 1)
+        (error "Ispell and its process have different character maps: %s" 
ispell-filter)
+      (ispell-parse-output (car ispell-filter)))))
+
+(defun ispell-error-checking-word (word)
+  "Return a string describing that checking for WORD failed."
+  (format "Error checking word %s using %s with %s dictionary"
+          (funcall ispell-format-word-function word)
+          (file-name-nondirectory ispell-program-name)
+          (or ispell-current-dictionary "default")))
+
+(defun ispell-correct-p (&optional following)
+  "Return t if the word at point is correct, nil otherwise.
+
+If optional argument FOLLOWING is non-nil then the following
+word (rather than preceding) is checked when the cursor is not
+over a word."
+  (save-excursion
+    ;; Reset ispell-filter so it only contains the result of
+    ;; spell-checking the current-word:
+    (setq ispell-filter nil)
+    (let* ((word-and-boundaries (ispell-get-word following))
+           (word (car word-and-boundaries))
+           (poss (ispell--run-on-word word)))
+      (unless poss (error (ispell-error-checking-word word)))
+      (or (eq poss t)
+          (stringp poss)))))
 
 (defun ispell-get-word (following &optional extra-otherchars)
   "Return the word for spell-checking according to ispell syntax.
diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el
index 67c8d16..e22e3f4 100644
--- a/lisp/textmodes/paragraphs.el
+++ b/lisp/textmodes/paragraphs.el
@@ -35,7 +35,7 @@
 
 (put 'use-hard-newlines 'permanent-local t)
 (define-minor-mode use-hard-newlines
-  "Toggle distinguishing between hard and soft newlines.
+  "Toggle between hard and soft newlines in the current buffer.
 
 When enabled, the functions `newline' and `open-line' add the
 text-property `hard' to newlines that they insert, and a line is
diff --git a/lisp/textmodes/reftex-vars.el b/lisp/textmodes/reftex-vars.el
index ca92541..50dd6cd 100644
--- a/lisp/textmodes/reftex-vars.el
+++ b/lisp/textmodes/reftex-vars.el
@@ -2100,6 +2100,8 @@ construct:  \\bbb [xxx] {aaa}."
   "Hook which is being run when loading reftex.el."
   :group 'reftex-miscellaneous-configurations
   :type 'hook)
+(make-obsolete-variable 'reftex-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defcustom reftex-mode-hook nil
   "Hook which is being run when turning on RefTeX mode."
diff --git a/lisp/textmodes/reftex.el b/lisp/textmodes/reftex.el
index 542f1fe..4071c0d 100644
--- a/lisp/textmodes/reftex.el
+++ b/lisp/textmodes/reftex.el
@@ -2371,7 +2371,7 @@ what in fact did happen.
 Check if the bug is reproducible with an up-to-date version of
 RefTeX available from https://www.gnu.org/software/auctex/.
 
-If the bug is triggered by a specific \(La)TeX file, you should try
+If the bug is triggered by a specific (La)TeX file, you should try
 to produce a minimal sample file showing the problem and include it
 in your report.
 
diff --git a/lisp/textmodes/table.el b/lisp/textmodes/table.el
index 4482e7d..7f87ee3 100644
--- a/lisp/textmodes/table.el
+++ b/lisp/textmodes/table.el
@@ -793,6 +793,8 @@ simply by any key input."
   "List of functions to be called after the table is first loaded."
   :type 'hook
   :group 'table-hooks)
+(make-obsolete-variable 'table-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defcustom table-point-entered-cell-hook nil
   "List of functions to be called after point entered a table cell."
@@ -3206,11 +3208,7 @@ CALS (DocBook DTD):
          (while (and (re-search-forward "$" nil t)
                      (not (eobp)))
            (insert "<br />")
-           (forward-char 1)))
-       (unless (and table-html-delegate-spacing-to-user-agent
-                    (progn
-                      (goto-char (point-min))
-                      (looking-at "\\s *\\'")))))
+           (forward-char 1))))
        ((eq language 'cals)
        (table--remove-eol-spaces (point-min) (point-max))
        (if (re-search-forward "\\s +\\'" nil t)
diff --git a/lisp/thread.el b/lisp/thread.el
index d40d7be..00a0084 100644
--- a/lisp/thread.el
+++ b/lisp/thread.el
@@ -43,8 +43,6 @@ An EVENT has the format
             (err (cddr event)))
         (message "Error %s: %S" thread err))))
 
-(make-obsolete 'thread-alive-p 'thread-live-p "27.1")
-
 ;;; The thread list buffer and list-threads command
 
 (defcustom thread-list-refresh-seconds 0.5
diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el
index a09294d..7c64f29 100644
--- a/lisp/time-stamp.el
+++ b/lisp/time-stamp.el
@@ -94,6 +94,13 @@ edited by older versions of Emacs also, do not use this 
format yet."
 (defcustom time-stamp-active t
   "Non-nil to enable time-stamping of buffers by \\[time-stamp].
 Can be toggled by \\[time-stamp-toggle-active].
+
+This option does not affect when `time-stamp' is run, only what it
+does when it runs.  To activate automatic time-stamping of buffers
+when they are saved, either add this line to your init file:
+    (add-hook \\='before-save-hook \\='time-stamp)
+or customize option `before-save-hook'.
+
 See also the variable `time-stamp-warn-inactive'."
   :type 'boolean
   :group 'time-stamp)
@@ -269,7 +276,7 @@ time-stamped file itself.")
 A template in a file can be automatically updated with a new time stamp
 every time you save the file.  Add this line to your init file:
     (add-hook \\='before-save-hook \\='time-stamp)
-or customize `before-save-hook' through Custom.
+or customize option `before-save-hook'.
 Normally the template must appear in the first 8 lines of a file and
 look like one of the following:
       Time-stamp: <>
@@ -606,24 +613,24 @@ and all `time-stamp-format' compatibility."
         ((eq cur-char ?F)              ;buffer-file-name, full path
          (or buffer-file-name
              time-stamp-no-file))
-        ((eq cur-char ?s)              ;system name
+        ((eq cur-char ?s)              ;system name, legacy
          (system-name))
-        ((eq cur-char ?u)              ;user name
+        ((eq cur-char ?u)              ;user name, legacy
          (user-login-name))
-        ((eq cur-char ?U)              ;user full name
+        ((eq cur-char ?U)              ;user full name, legacy
          (user-full-name))
-        ((eq cur-char ?l)              ;logname (undocumented user name alt)
+        ((eq cur-char ?l)              ;login name
          (user-login-name))
-        ((eq cur-char ?L)              ;(undocumented alt user full name)
+        ((eq cur-char ?L)              ;full name of logged-in user
          (user-full-name))
         ((eq cur-char ?h)              ;mail host name
          (or mail-host-address (system-name)))
-        ((eq cur-char ?q)              ;(undocumented unqual hostname)
+        ((eq cur-char ?q)              ;unqualified host name
          (let ((qualname (system-name)))
            (if (string-match "\\." qualname)
                (substring qualname 0 (match-beginning 0))
              qualname)))
-        ((eq cur-char ?Q)              ;(undocumented fully-qualified host)
+        ((eq cur-char ?Q)              ;fully-qualified host name
          (system-name))
         ))
         (and (numberp field-result)
diff --git a/lisp/url/url-vars.el b/lisp/url/url-vars.el
index 82617b7..4e44eed 100644
--- a/lisp/url/url-vars.el
+++ b/lisp/url/url-vars.el
@@ -430,6 +430,8 @@ Should be one of:
   "Hook run after initializing the URL library."
   :group 'url
   :type 'hook)
+(make-obsolete-variable 'url-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defconst url-working-buffer " *url-work")
 
diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el
index 676a587..cbd8c0d 100644
--- a/lisp/vc/ediff-init.el
+++ b/lisp/vc/ediff-init.el
@@ -452,6 +452,8 @@ For each buffer, the hooks are run with that buffer made 
current."
   "Hook run after Ediff is loaded.  Can be used to change defaults."
   :type 'hook
   :group 'ediff-hook)
+(make-obsolete-variable 'ediff-load-hook
+                        "use `with-eval-after-load' instead." "28.1")
 
 (defcustom ediff-mode-hook nil
   "Hook run just after ediff-mode is set up in the control buffer.
diff --git a/lisp/vc/smerge-mode.el b/lisp/vc/smerge-mode.el
index d4984bb..85868b9 100644
--- a/lisp/vc/smerge-mode.el
+++ b/lisp/vc/smerge-mode.el
@@ -797,7 +797,10 @@ An error is raised if not inside a conflict."
               (filename (or (match-string 1) ""))
 
               (_ (re-search-forward smerge-end-re))
-              (_ (cl-assert (< orig-point (match-end 0))))
+              (_ (when (< (match-end 0) orig-point)
+                   ;; Point is not within the conflict we found,
+                    ;; so this conflict is not ours.
+                   (signal 'search-failed (list smerge-begin-re))))
 
               (lower-end (match-beginning 0))
               (end (match-end 0))
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 37bc53b..2caa287 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -1785,13 +1785,12 @@ The difference to vc-do-command is that this function 
always invokes
        (process-environment
         (append
          `("GIT_DIR"
-           "PAGER="
            ;; Avoid repository locking during background operations
            ;; (bug#21559).
            ,@(when revert-buffer-in-progress-p
                '("GIT_OPTIONAL_LOCKS=0")))
          process-environment)))
-    (apply 'process-file vc-git-program nil buffer nil command args)))
+    (apply 'process-file vc-git-program nil buffer nil "--no-pager" command 
args)))
 
 (defun vc-git--out-ok (command &rest args)
   (zerop (apply 'vc-git--call '(t nil) command args)))
diff --git a/lisp/wdired.el b/lisp/wdired.el
index d470e0a..d91853e 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -357,6 +357,8 @@ non-nil means return old filename."
     (remove-text-properties
      (point-min) (point-max)
      '(front-sticky nil rear-nonsticky nil read-only nil keymap nil)))
+  (remove-function (local 'isearch-filter-predicate)
+                   #'wdired-isearch-filter-read-only)
   (use-local-map dired-mode-map)
   (force-mode-line-update)
   (setq buffer-read-only t)
diff --git a/lisp/window.el b/lisp/window.el
index 4334863..40c4bf5 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4970,9 +4970,11 @@ WINDOW must be a live window and defaults to the 
selected one.
 
 According to information stored in WINDOW's `quit-restore' window
 parameter either (1) delete WINDOW and its frame, (2) delete
-WINDOW, (3) restore the buffer previously displayed in WINDOW,
-or (4) make WINDOW display some other buffer than the present
-one.  If non-nil, reset `quit-restore' parameter to nil.
+WINDOW but leave its frame alone, (3) restore the buffer
+previously shown in WINDOW, or (4) make WINDOW display some other
+buffer.  If WINDOW is not deleted, reset its `quit-restore'
+parameter to nil.  See Info node `(elisp) Quitting Windows' for
+more details.
 
 Optional second argument BURY-OR-KILL tells how to proceed with
 the buffer of WINDOW.  The following values are handled:
@@ -5083,11 +5085,9 @@ WINDOW must be a live window and defaults to the 
selected one.
 With prefix argument KILL non-nil, kill the buffer instead of
 burying it.
 
-According to information stored in WINDOW's `quit-restore' window
-parameter either (1) delete WINDOW and its frame, (2) delete
-WINDOW, (3) restore the buffer previously displayed in WINDOW,
-or (4) make WINDOW display some other buffer than the present
-one.  If non-nil, reset `quit-restore' parameter to nil.
+This calls the function `quit-restore-window' to delete WINDOW or
+show some other buffer in it.  See Info node `(elisp) Quitting
+Windows' for more details.
 
 The functions in `quit-window-hook' will be run before doing
 anything else."
diff --git a/lisp/woman.el b/lisp/woman.el
index c41cb49..beebde9 100644
--- a/lisp/woman.el
+++ b/lisp/woman.el
@@ -138,7 +138,7 @@
 ;; Customization, Hooks and Imenu
 ;; ==============================
 
-;; WoMan supports the GNU Emacs 20+ customization facility, and puts
+;; WoMan supports the GNU Emacs customization facility, and puts
 ;; a customization group called `WoMan' in the `Help' group under the
 ;; top-level `Emacs' group.  In order to be able to customize WoMan
 ;; without first loading it, add the following sexp to your .emacs:
diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el
index ea9d119..b22af5cc 100644
--- a/lisp/x-dnd.el
+++ b/lisp/x-dnd.el
@@ -412,19 +412,13 @@ FRAME is the frame and W is the window where the drop 
happened.
 If W is a window, return its absolute coordinates,
 otherwise return the frame coordinates."
   (let* ((frame-left (frame-parameter frame 'left))
-        ;; If the frame is outside the display, frame-left looks like
-        ;; '(0 -16).  Extract the -16.
-        (frame-real-left (if (consp frame-left) (car (cdr frame-left))
-                           frame-left))
-        (frame-top (frame-parameter frame 'top))
-        (frame-real-top (if (consp frame-top) (car (cdr frame-top))
-                          frame-top)))
+        (frame-top (frame-parameter frame 'top)))
     (if (windowp w)
        (let ((edges (window-inside-pixel-edges w)))
          (cons
-          (+ frame-real-left (nth 0 edges))
-          (+ frame-real-top (nth 1 edges))))
-      (cons frame-real-left frame-real-top))))
+          (+ frame-left (nth 0 edges))
+          (+ frame-top (nth 1 edges))))
+      (cons frame-left frame-top))))
 
 (declare-function x-get-atom-name "xselect.c" (value &optional frame))
 (declare-function x-send-client-message "xselect.c"
@@ -434,15 +428,11 @@ otherwise return the frame coordinates."
 
 (defun x-dnd-version-from-flags (flags)
   "Return the version byte from the 32 bit FLAGS in an XDndEnter message."
-  (if (consp flags)   ;; Long as cons
-      (ash (car flags) -8)
-    (ash flags -24))) ;; Ordinary number
+  (ash flags -24))
 
 (defun x-dnd-more-than-3-from-flags (flags)
   "Return the nmore-than3 bit from the 32 bit FLAGS in an XDndEnter message."
-  (if (consp flags)
-      (logand (cdr flags) 1)
-    (logand flags 1)))
+  (logand flags 1))
 
 (defun x-dnd-handle-xdnd (event frame window message _format data)
   "Receive one XDND event (client message) and send the appropriate reply.
@@ -454,7 +444,7 @@ FORMAT is 32 (not used).  MESSAGE is the data part of an 
XClientMessageEvent."
                (version (x-dnd-version-from-flags flags))
                (more-than-3 (x-dnd-more-than-3-from-flags flags))
                (dnd-source (aref data 0)))
-       (message "%s %s" version  more-than-3)
+          (message "%s %s" version more-than-3)
           (if version  ;; If flags is bad, version will be nil.
               (x-dnd-save-state
                window nil nil
@@ -495,10 +485,12 @@ FORMAT is 32 (not used).  MESSAGE is the data part of an 
XClientMessageEvent."
        ((equal "XdndDrop" message)
         (if (windowp window) (select-window window))
         (let* ((dnd-source (aref data 0))
+               (timestamp (aref data 2))
                (value (and (x-dnd-current-type window)
                            (x-get-selection-internal
                             'XdndSelection
-                            (intern (x-dnd-current-type window)))))
+                            (intern (x-dnd-current-type window))
+                            timestamp)))
                success action)
 
           (setq action (if value
@@ -545,14 +537,14 @@ FORMAT is 32 (not used).  MESSAGE is the data part of an 
XClientMessageEvent."
 
        ((eq size 4)
         (if (eq byteorder ?l)
-            (cons (+ (ash (aref data (+ 3 offset)) 8)
-                     (aref data (+ 2 offset)))
-                  (+ (ash (aref data (1+ offset)) 8)
-                     (aref data offset)))
-          (cons (+ (ash (aref data offset) 8)
-                   (aref data (1+ offset)))
-                (+ (ash (aref data (+ 2 offset)) 8)
-                   (aref data (+ 3 offset))))))))
+            (+ (ash (aref data (+ 3 offset)) 24)
+               (ash (aref data (+ 2 offset)) 16)
+               (ash (aref data (1+ offset)) 8)
+               (aref data offset))
+          (+ (ash (aref data offset) 24)
+             (ash (aref data (1+ offset)) 16)
+             (ash (aref data (+ 2 offset)) 8)
+             (aref data (+ 3 offset)))))))
 
 (defun x-dnd-motif-value-to-list (value size byteorder)
   (let ((bytes (cond ((eq size 2)
@@ -560,15 +552,10 @@ FORMAT is 32 (not used).  MESSAGE is the data part of an 
XClientMessageEvent."
                            (logand value ?\xff)))
 
                     ((eq size 4)
-                     (if (consp value)
-                         (list (logand (ash (car value) -8) ?\xff)
-                               (logand (car value) ?\xff)
-                               (logand (ash (cdr value) -8) ?\xff)
-                               (logand (cdr value) ?\xff))
-                       (list (logand (ash value -24) ?\xff)
-                             (logand (ash value -16) ?\xff)
-                             (logand (ash value -8) ?\xff)
-                             (logand value ?\xff)))))))
+                     (list (logand (ash value -24) ?\xff)
+                           (logand (ash value -16) ?\xff)
+                           (logand (ash value -8) ?\xff)
+                           (logand value ?\xff))))))
     (if (eq byteorder ?l)
        (reverse bytes)
       bytes)))
diff --git a/m4/00gnulib.m4 b/m4/00gnulib.m4
index 1a1a1d7..06eff4f 100644
--- a/m4/00gnulib.m4
+++ b/m4/00gnulib.m4
@@ -1,13 +1,14 @@
-# 00gnulib.m4 serial 3
+# 00gnulib.m4 serial 7
 dnl Copyright (C) 2009-2020 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.
 
 dnl This file must be named something that sorts before all other
-dnl gnulib-provided .m4 files.  It is needed until such time as we can
-dnl assume Autoconf 2.64, with its improved AC_DEFUN_ONCE and
-dnl m4_divert semantics.
+dnl gnulib-provided .m4 files.  The first part is needed until such time
+dnl as we can assume Autoconf 2.64, with its improved AC_DEFUN_ONCE and
+dnl m4_divert semantics.  The second part is needed until the clang fix
+dnl has been included in Autoconf.
 
 # Until autoconf 2.63, handling of the diversion stack required m4_init
 # to be called first; but this does not happen with aclocal.  Wrapping
@@ -39,6 +40,76 @@ m4_version_prereq([2.63.263], [],
       [m4_indir([_gl_DEFUN_ONCE([$1])])])])]dnl
 [AC][_DEFUN([_gl_DEFUN_ONCE([$1])], [$2])])])
 
+# The following definitions arrange to use a compiler option
+# -Werror=implicit-function-declaration in AC_CHECK_DECL, when the
+# compiler is clang.  Without it, clang implicitly declares "known"
+# library functions in C mode, but not in C++ mode, which would cause
+# Gnulib to omit a declaration and thus later produce an error in C++
+# mode.  As of clang 9.0, these "known" functions are identified through
+# LIBBUILTIN invocations in the LLVM source file
+# llvm/tools/clang/include/clang/Basic/Builtins.def.
+# It's not possible to AC_REQUIRE the extra tests from AC_CHECK_DECL,
+# because AC_CHECK_DECL, like other Autoconf built-ins, is not supposed
+# to AC_REQUIRE anything: some configure.ac files have their first
+# AC_CHECK_DECL executed conditionally.  Therefore append the extra tests
+# to AC_PROG_CC.
+AC_DEFUN([gl_COMPILER_CLANG],
+[
+dnl AC_REQUIRE([AC_PROG_CC])
+  AC_CACHE_CHECK([whether the compiler is clang],
+    [gl_cv_compiler_clang],
+    [dnl Use _AC_COMPILE_IFELSE instead of AC_EGREP_CPP, to avoid error
+     dnl "circular dependency of AC_LANG_COMPILER(C)" if AC_PROG_CC has
+     dnl not yet been invoked.
+     _AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM([[
+           #ifdef __clang__
+           barfbarf
+           #endif
+           ]],[[]])
+        ],
+        [gl_cv_compiler_clang=no],
+        [gl_cv_compiler_clang=yes])
+    ])
+])
+AC_DEFUN([gl_COMPILER_PREPARE_CHECK_DECL],
+[
+dnl AC_REQUIRE([AC_PROG_CC])
+dnl AC_REQUIRE([gl_COMPILER_CLANG])
+  AC_CACHE_CHECK([for compiler option needed when checking for declarations],
+    [gl_cv_compiler_check_decl_option],
+    [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"
+       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"
+     else
+       gl_cv_compiler_check_decl_option=none
+     fi
+    ])
+  if test "x$gl_cv_compiler_check_decl_option" != xnone; then
+    ac_compile_for_check_decl="$ac_compile $gl_cv_compiler_check_decl_option"
+  else
+    ac_compile_for_check_decl="$ac_compile"
+  fi
+])
+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"
+  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"
+])
+
 # gl_00GNULIB
 # -----------
 # Witness macro that this file has been included.  Needed to force
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
index 6c4cad6..276ed1a 100644
--- a/m4/gnulib-common.m4
+++ b/m4/gnulib-common.m4
@@ -1,4 +1,4 @@
-# gnulib-common.m4 serial 46
+# gnulib-common.m4 serial 47
 dnl Copyright (C) 2007-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -12,6 +12,7 @@ AC_DEFUN([gl_COMMON], [
   dnl Use AC_REQUIRE here, so that the code is expanded once only.
   AC_REQUIRE([gl_00GNULIB])
   AC_REQUIRE([gl_COMMON_BODY])
+  AC_REQUIRE([gl_ZZGNULIB])
 ])
 AC_DEFUN([gl_COMMON_BODY], [
   AH_VERBATIM([_Noreturn],
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 85a6056..48d8030 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -133,7 +133,6 @@ AC_DEFUN([gl_EARLY],
   # Code from module pipe2:
   # Code from module pselect:
   # Code from module pthread_sigmask:
-  # Code from module putenv:
   # Code from module qcopy-acl:
   # Code from module readlink:
   # Code from module readlinkat:
@@ -303,6 +302,7 @@ AC_DEFUN([gl_INIT],
     GNULIB_GL_UNISTD_H_GETOPT=1
   fi
   AC_SUBST([GNULIB_GL_UNISTD_H_GETOPT])
+  gl_UNISTD_MODULE_INDICATOR([getopt-posix])
   gl_GETTIME
   gl_FUNC_GETTIMEOFDAY
   if test $HAVE_GETTIMEOFDAY = 0 || test $REPLACE_GETTIMEOFDAY = 1; then
@@ -367,12 +367,6 @@ AC_DEFUN([gl_INIT],
     gl_PREREQ_PTHREAD_SIGMASK
   fi
   gl_SIGNAL_MODULE_INDICATOR([pthread_sigmask])
-  gl_FUNC_PUTENV
-  if test $REPLACE_PUTENV = 1; then
-    AC_LIBOBJ([putenv])
-    gl_PREREQ_PUTENV
-  fi
-  gl_STDLIB_MODULE_INDICATOR([putenv])
   gl_FUNC_READLINK
   if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then
     AC_LIBOBJ([readlink])
@@ -972,7 +966,6 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/pipe2.c
   lib/pselect.c
   lib/pthread_sigmask.c
-  lib/putenv.c
   lib/qcopy-acl.c
   lib/readlink.c
   lib/readlinkat.c
@@ -1111,7 +1104,6 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/pipe2.m4
   m4/pselect.m4
   m4/pthread_sigmask.m4
-  m4/putenv.m4
   m4/readlink.m4
   m4/readlinkat.m4
   m4/regex.m4
@@ -1158,4 +1150,5 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/warnings.m4
   m4/wchar_t.m4
   m4/wint_t.m4
+  m4/zzgnulib.m4
 ])
diff --git a/m4/largefile.m4 b/m4/largefile.m4
index 40b16bc..e381339 100644
--- a/m4/largefile.m4
+++ b/m4/largefile.m4
@@ -1,4 +1,5 @@
 # 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-2020 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
@@ -73,6 +74,9 @@ rm -rf conftest*[]dnl
 # one must use special compiler options to get large-file access to work.
 # For more details about this brain damage please see:
 # http://www.unix.org/version2/whatsnew/lfs20mar.html
+# Additionally, on Linux file systems with 64-bit inodes a file that happens
+# to have a 64-bit inode number cannot be accessed by 32-bit applications on
+# Linux x86/x86_64.  This can occur with file systems such as XFS and NFS.
 AC_DEFUN([AC_SYS_LARGEFILE],
 [AC_ARG_ENABLE(largefile,
                [  --disable-largefile     omit support for large files])
diff --git a/m4/putenv.m4 b/m4/putenv.m4
deleted file mode 100644
index e38f8c5..0000000
--- a/m4/putenv.m4
+++ /dev/null
@@ -1,60 +0,0 @@
-# putenv.m4 serial 24
-dnl Copyright (C) 2002-2020 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.
-
-dnl From Jim Meyering.
-dnl
-dnl Check whether putenv ("FOO") removes FOO from the environment.
-dnl The putenv in libc on at least SunOS 4.1.4 does *not* do that.
-
-AC_DEFUN([gl_FUNC_PUTENV],
-[
-  AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
-  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
-  AC_CACHE_CHECK([for putenv compatible with GNU and SVID],
-   [gl_cv_func_svid_putenv],
-   [AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],[[
-    /* Put it in env.  */
-    if (putenv ("CONFTEST_putenv=val"))
-      return 1;
-
-    /* Try to remove it.  */
-    if (putenv ("CONFTEST_putenv"))
-      return 2;
-
-    /* Make sure it was deleted.  */
-    if (getenv ("CONFTEST_putenv") != 0)
-      return 3;
-
-    return 0;
-              ]])],
-             gl_cv_func_svid_putenv=yes,
-             gl_cv_func_svid_putenv=no,
-             dnl When crosscompiling, assume putenv is broken.
-             [case "$host_os" in
-                               # Guess yes on glibc systems.
-                *-gnu* | gnu*) gl_cv_func_svid_putenv="guessing yes" ;;
-                               # Guess yes on musl systems.
-                *-musl*)       gl_cv_func_svid_putenv="guessing yes" ;;
-                               # Guess no on native Windows.
-                mingw*)        gl_cv_func_svid_putenv="guessing no" ;;
-                               # If we don't know, obey --enable-cross-guesses.
-                *)             gl_cv_func_svid_putenv="$gl_cross_guess_normal" 
;;
-              esac
-             ])
-   ])
-  case "$gl_cv_func_svid_putenv" in
-    *yes) ;;
-    *)
-      REPLACE_PUTENV=1
-      ;;
-  esac
-])
-
-# Prerequisites of lib/putenv.c.
-AC_DEFUN([gl_PREREQ_PUTENV],
-[
-  AC_CHECK_DECLS([_putenv])
-])
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index 7453866..ea2bb01 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 76
+# unistd_h.m4 serial 77
 dnl Copyright (C) 2006-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -84,6 +84,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   GNULIB_GETHOSTNAME=0;          AC_SUBST([GNULIB_GETHOSTNAME])
   GNULIB_GETLOGIN=0;             AC_SUBST([GNULIB_GETLOGIN])
   GNULIB_GETLOGIN_R=0;           AC_SUBST([GNULIB_GETLOGIN_R])
+  GNULIB_GETOPT_POSIX=0;         AC_SUBST([GNULIB_GETOPT_POSIX])
   GNULIB_GETPAGESIZE=0;          AC_SUBST([GNULIB_GETPAGESIZE])
   GNULIB_GETPASS=0;              AC_SUBST([GNULIB_GETPASS])
   GNULIB_GETUSERSHELL=0;         AC_SUBST([GNULIB_GETUSERSHELL])
diff --git a/m4/zzgnulib.m4 b/m4/zzgnulib.m4
new file mode 100644
index 0000000..98fa68f
--- /dev/null
+++ b/m4/zzgnulib.m4
@@ -0,0 +1,23 @@
+# zzgnulib.m4 serial 1
+dnl Copyright (C) 2020 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.
+
+dnl This file must be named something that sorts after all other
+dnl package- or gnulib-provided .m4 files - at least for those packages
+dnl that redefine AC_PROG_CC.
+
+dnl Redefine AC_PROG_CC so that it ends with invocations of gl_COMPILER_CLANG
+dnl and gl_COMPILER_PREPARE_CHECK_DECL.
+m4_define([AC_PROG_CC],
+  m4_defn([AC_PROG_CC])[
+gl_COMPILER_CLANG
+gl_COMPILER_PREPARE_CHECK_DECL
+])
+
+# gl_ZZGNULIB
+# -----------
+# Witness macro that this file has been included.  Needed to force
+# Automake to include this file after all other gnulib .m4 files.
+AC_DEFUN([gl_ZZGNULIB])
diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h
index 6d20c95..1cce2c3 100644
--- a/nt/inc/ms-w32.h
+++ b/nt/inc/ms-w32.h
@@ -63,8 +63,8 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
    Look in <sys/time.h> for a timeval structure.  */
 #define HAVE_TIMEVAL 1
 
-/* And the select implementation does 1-byte read-ahead waiting
-   for received packets, so datagrams are broken too.  */
+/* Our select emulation does 1-byte read-ahead waiting for received
+   packets, so datagrams are broken.  */
 #define BROKEN_DATAGRAM_SOCKETS 1
 
 #define MAIL_USE_SYSTEM_LOCK 1
@@ -499,6 +499,8 @@ extern void *malloc_after_dump_9x(size_t);
 extern void *realloc_after_dump_9x(void *, size_t);
 extern void free_after_dump_9x(void *);
 
+extern void *sys_calloc(size_t, size_t);
+
 extern malloc_fn the_malloc_fn;
 extern realloc_fn the_realloc_fn;
 extern free_fn the_free_fn;
@@ -506,6 +508,7 @@ extern free_fn the_free_fn;
 #define malloc(size) (*the_malloc_fn)(size)
 #define free(ptr)   (*the_free_fn)(ptr)
 #define realloc(ptr, size) (*the_realloc_fn)(ptr, size)
+#define calloc(num, size) sys_calloc(num, size)
 
 #endif
 
diff --git a/src/Makefile.in b/src/Makefile.in
index 6a151d1..52d8ddd 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -295,8 +295,8 @@ EMACSRES = @EMACSRES@
 W32_RES_LINK=@W32_RES_LINK@
 
 ## Empty if !HAVE_X_WINDOWS
-## xfont.o ftfont.o xftfont.o ftxfont.o if HAVE_XFT
-## xfont.o ftfont.o ftxfont.o if HAVE_FREETYPE
+## xfont.o ftfont.o xftfont.o if HAVE_XFT
+## xfont.o ftfont.o if HAVE_FREETYPE
 ## xfont.o ftfont.o ftcrfont.o if USE_CAIRO
 ## else xfont.o
 ## if HAVE_HARFBUZZ, hbfont.o is added regardless of the rest
@@ -440,7 +440,7 @@ SOME_MACHINE_OBJECTS = dosfns.o msdos.o \
   nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o macfont.o \
   w32.o w32console.o w32cygwinx.o w32fns.o w32heap.o w32inevt.o w32notify.o \
   w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o \
-  w16select.o widget.o xfont.o ftfont.o xftfont.o ftxfont.o gtkutil.o \
+  w16select.o widget.o xfont.o ftfont.o xftfont.o gtkutil.o \
   xsettings.o xgselect.o termcap.o hbfont.o
 
 ## gmalloc.o if !SYSTEM_MALLOC && !DOUG_LEA_MALLOC, else empty.
diff --git a/src/alloc.c b/src/alloc.c
index faa8e70..354c6f0 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -104,6 +104,26 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #include "w32heap.h"   /* for sbrk */
 #endif
 
+/* MALLOC_SIZE_NEAR (N) is a good number to pass to malloc when
+   allocating a block of memory with size close to N bytes.
+   For best results N should be a power of 2.
+
+   When calculating how much memory to allocate, GNU malloc (SIZE)
+   adds sizeof (size_t) to SIZE for internal overhead, and then rounds
+   up to a multiple of MALLOC_ALIGNMENT.  Emacs can improve
+   performance a bit on GNU platforms by arranging for the resulting
+   size to be a power of two.  This heuristic is good for glibc 2.0
+   (1997) through at least glibc 2.31 (2020), and does not affect
+   correctness on other platforms.  */
+
+#define MALLOC_SIZE_NEAR(n) \
+  (ROUNDUP (max (n, sizeof (size_t)), MALLOC_ALIGNMENT) - sizeof (size_t))
+#ifdef __i386
+enum { MALLOC_ALIGNMENT = 16 };
+#else
+enum { MALLOC_ALIGNMENT = max (2 * sizeof (size_t), alignof (long double)) };
+#endif
+
 #ifdef DOUG_LEA_MALLOC
 
 /* Specify maximum number of areas to mmap.  It would be nice to use a
@@ -694,7 +714,7 @@ malloc_unblock_input (void)
       malloc_probe (size);                     \
   } while (0)
 
-static void *lmalloc (size_t) ATTRIBUTE_MALLOC_SIZE ((1));
+static void *lmalloc (size_t, bool) ATTRIBUTE_MALLOC_SIZE ((1));
 static void *lrealloc (void *, size_t);
 
 /* Like malloc but check for no memory and block interrupt input.  */
@@ -705,7 +725,7 @@ xmalloc (size_t size)
   void *val;
 
   MALLOC_BLOCK_INPUT;
-  val = lmalloc (size);
+  val = lmalloc (size, false);
   MALLOC_UNBLOCK_INPUT;
 
   if (!val && size)
@@ -722,12 +742,11 @@ xzalloc (size_t size)
   void *val;
 
   MALLOC_BLOCK_INPUT;
-  val = lmalloc (size);
+  val = lmalloc (size, true);
   MALLOC_UNBLOCK_INPUT;
 
   if (!val && size)
     memory_full (size);
-  memset (val, 0, size);
   MALLOC_PROBE (size);
   return val;
 }
@@ -743,7 +762,7 @@ xrealloc (void *block, size_t size)
   /* We must call malloc explicitly when BLOCK is 0, since some
      reallocs don't do this.  */
   if (! block)
-    val = lmalloc (size);
+    val = lmalloc (size, false);
   else
     val = lrealloc (block, size);
   MALLOC_UNBLOCK_INPUT;
@@ -939,7 +958,7 @@ void *lisp_malloc_loser EXTERNALLY_VISIBLE;
 #endif
 
 static void *
-lisp_malloc (size_t nbytes, enum mem_type type)
+lisp_malloc (size_t nbytes, bool clearit, enum mem_type type)
 {
   register void *val;
 
@@ -949,7 +968,7 @@ lisp_malloc (size_t nbytes, enum mem_type type)
   allocated_mem_type = type;
 #endif
 
-  val = lmalloc (nbytes);
+  val = lmalloc (nbytes, clearit);
 
 #if ! USE_LSB_TAG
   /* If the memory just allocated cannot be addressed thru a Lisp
@@ -1290,16 +1309,21 @@ laligned (void *p, size_t size)
    that's never really exercised) for little benefit.  */
 
 static void *
-lmalloc (size_t size)
+lmalloc (size_t size, bool clearit)
 {
 #ifdef USE_ALIGNED_ALLOC
   if (! MALLOC_IS_LISP_ALIGNED && size % LISP_ALIGNMENT == 0)
-    return aligned_alloc (LISP_ALIGNMENT, size);
+    {
+      void *p = aligned_alloc (LISP_ALIGNMENT, size);
+      if (clearit && p)
+       memclear (p, size);
+      return p;
+    }
 #endif
 
   while (true)
     {
-      void *p = malloc (size);
+      void *p = clearit ? calloc (1, size) : malloc (size);
       if (laligned (p, size))
        return p;
       free (p);
@@ -1328,11 +1352,11 @@ lrealloc (void *p, size_t size)
                         Interval Allocation
  ***********************************************************************/
 
-/* Number of intervals allocated in an interval_block structure.
-   The 1020 is 1024 minus malloc overhead.  */
+/* Number of intervals allocated in an interval_block structure.  */
 
-#define INTERVAL_BLOCK_SIZE \
-  ((1020 - sizeof (struct interval_block *)) / sizeof (struct interval))
+enum { INTERVAL_BLOCK_SIZE
+         = ((MALLOC_SIZE_NEAR (1024) - sizeof (struct interval_block *))
+           / sizeof (struct interval)) };
 
 /* Intervals are allocated in chunks in the form of an interval_block
    structure.  */
@@ -1377,7 +1401,7 @@ make_interval (void)
       if (interval_block_index == INTERVAL_BLOCK_SIZE)
        {
          struct interval_block *newi
-           = lisp_malloc (sizeof *newi, MEM_TYPE_NON_LISP);
+           = lisp_malloc (sizeof *newi, false, MEM_TYPE_NON_LISP);
 
          newi->next = interval_block;
          interval_block = newi;
@@ -1444,10 +1468,9 @@ mark_interval_tree (INTERVAL i)
    longer used, can be easily recognized, and it's easy to compact the
    sblocks of small strings which we do in compact_small_strings.  */
 
-/* Size in bytes of an sblock structure used for small strings.  This
-   is 8192 minus malloc overhead.  */
+/* Size in bytes of an sblock structure used for small strings.  */
 
-#define SBLOCK_SIZE 8188
+enum { SBLOCK_SIZE = MALLOC_SIZE_NEAR (8192) };
 
 /* Strings larger than this are considered large strings.  String data
    for large strings is allocated from individual sblocks.  */
@@ -1522,11 +1545,11 @@ struct sblock
   sdata data[FLEXIBLE_ARRAY_MEMBER];
 };
 
-/* Number of Lisp strings in a string_block structure.  The 1020 is
-   1024 minus malloc overhead.  */
+/* Number of Lisp strings in a string_block structure.  */
 
-#define STRING_BLOCK_SIZE \
-  ((1020 - sizeof (struct string_block *)) / sizeof (struct Lisp_String))
+enum { STRING_BLOCK_SIZE
+         = ((MALLOC_SIZE_NEAR (1024) - sizeof (struct string_block *))
+           / sizeof (struct Lisp_String)) };
 
 /* Structure describing a block from which Lisp_String structures
    are allocated.  */
@@ -1730,7 +1753,7 @@ allocate_string (void)
      add all the Lisp_Strings in it to the free-list.  */
   if (string_free_list == NULL)
     {
-      struct string_block *b = lisp_malloc (sizeof *b, MEM_TYPE_STRING);
+      struct string_block *b = lisp_malloc (sizeof *b, false, MEM_TYPE_STRING);
       int i;
 
       b->next = string_blocks;
@@ -1778,15 +1801,16 @@ allocate_string (void)
    plus a NUL byte at the end.  Allocate an sdata structure DATA for
    S, and set S->u.s.data to SDATA->u.data.  Store a NUL byte at the
    end of S->u.s.data.  Set S->u.s.size to NCHARS and S->u.s.size_byte
-   to NBYTES.  Free S->u.s.data if it was initially non-null.  */
+   to NBYTES.  Free S->u.s.data if it was initially non-null.
 
-void
+   If CLEARIT, also clear the other bytes of S->u.s.data.  */
+
+static void
 allocate_string_data (struct Lisp_String *s,
-                     EMACS_INT nchars, EMACS_INT nbytes)
+                     EMACS_INT nchars, EMACS_INT nbytes, bool clearit)
 {
-  sdata *data, *old_data;
+  sdata *data;
   struct sblock *b;
-  ptrdiff_t old_nbytes;
 
   if (STRING_BYTES_MAX < nbytes)
     string_overflow ();
@@ -1794,13 +1818,6 @@ allocate_string_data (struct Lisp_String *s,
   /* Determine the number of bytes needed to store NBYTES bytes
      of string data.  */
   ptrdiff_t needed = sdata_size (nbytes);
-  if (s->u.s.data)
-    {
-      old_data = SDATA_OF_STRING (s);
-      old_nbytes = STRING_BYTES (s);
-    }
-  else
-    old_data = NULL;
 
   MALLOC_BLOCK_INPUT;
 
@@ -1813,7 +1830,7 @@ allocate_string_data (struct Lisp_String *s,
         mallopt (M_MMAP_MAX, 0);
 #endif
 
-      b = lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP);
+      b = lisp_malloc (size + GC_STRING_EXTRA, clearit, MEM_TYPE_NON_LISP);
 
 #ifdef DOUG_LEA_MALLOC
       if (!mmap_lisp_allowed_p ())
@@ -1825,27 +1842,30 @@ allocate_string_data (struct Lisp_String *s,
       b->next_free = data;
       large_sblocks = b;
     }
-  else if (current_sblock == NULL
-          || (((char *) current_sblock + SBLOCK_SIZE
-               - (char *) current_sblock->next_free)
-              < (needed + GC_STRING_EXTRA)))
-    {
-      /* Not enough room in the current sblock.  */
-      b = lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP);
-      data = b->data;
-      b->next = NULL;
-      b->next_free = data;
-
-      if (current_sblock)
-       current_sblock->next = b;
-      else
-       oldest_sblock = b;
-      current_sblock = b;
-    }
   else
     {
       b = current_sblock;
+
+      if (b == NULL
+         || (SBLOCK_SIZE - GC_STRING_EXTRA
+             < (char *) b->next_free - (char *) b + needed))
+       {
+         /* Not enough room in the current sblock.  */
+         b = lisp_malloc (SBLOCK_SIZE, false, MEM_TYPE_NON_LISP);
+         data = b->data;
+         b->next = NULL;
+         b->next_free = data;
+
+         if (current_sblock)
+           current_sblock->next = b;
+         else
+           oldest_sblock = b;
+         current_sblock = b;
+       }
+
       data = b->next_free;
+      if (clearit)
+       memset (SDATA_DATA (data), 0, nbytes);
     }
 
   data->string = s;
@@ -1866,16 +1886,55 @@ allocate_string_data (struct Lisp_String *s,
          GC_STRING_OVERRUN_COOKIE_SIZE);
 #endif
 
-  /* Note that Faset may call to this function when S has already data
-     assigned.  In this case, mark data as free by setting it's string
-     back-pointer to null, and record the size of the data in it.  */
-  if (old_data)
+  tally_consing (needed);
+}
+
+/* Reallocate multibyte STRING data when a single character is replaced.
+   The character is at byte offset CIDX_BYTE in the string.
+   The character being replaced is CLEN bytes long,
+   and the character that will replace it is NEW_CLEN bytes long.
+   Return the address of where the caller should store the
+   the new character.  */
+
+unsigned char *
+resize_string_data (Lisp_Object string, ptrdiff_t cidx_byte,
+                   int clen, int new_clen)
+{
+  eassume (STRING_MULTIBYTE (string));
+  sdata *old_sdata = SDATA_OF_STRING (XSTRING (string));
+  ptrdiff_t nchars = SCHARS (string);
+  ptrdiff_t nbytes = SBYTES (string);
+  ptrdiff_t new_nbytes = nbytes + (new_clen - clen);
+  unsigned char *data = SDATA (string);
+  unsigned char *new_charaddr;
+
+  if (sdata_size (nbytes) == sdata_size (new_nbytes))
     {
-      SDATA_NBYTES (old_data) = old_nbytes;
-      old_data->string = NULL;
+      /* No need to reallocate, as the size change falls within the
+        alignment slop.  */
+      XSTRING (string)->u.s.size_byte = new_nbytes;
+      new_charaddr = data + cidx_byte;
+      memmove (new_charaddr + new_clen, new_charaddr + clen,
+              nbytes - (cidx_byte + (clen - 1)));
+    }
+  else
+    {
+      allocate_string_data (XSTRING (string), nchars, new_nbytes, false);
+      unsigned char *new_data = SDATA (string);
+      new_charaddr = new_data + cidx_byte;
+      memcpy (new_charaddr + new_clen, data + cidx_byte + clen,
+             nbytes - (cidx_byte + clen));
+      memcpy (new_data, data, cidx_byte);
+
+      /* Mark old string data as free by setting its string back-pointer
+        to null, and record the size of the data in it.  */
+      SDATA_NBYTES (old_sdata) = nbytes;
+      old_sdata->string = NULL;
     }
 
-  tally_consing (needed);
+  clear_string_char_byte_cache ();
+
+  return new_charaddr;
 }
 
 
@@ -2110,6 +2169,9 @@ string_overflow (void)
   error ("Maximum string size exceeded");
 }
 
+static Lisp_Object make_clear_string (EMACS_INT, bool);
+static Lisp_Object make_clear_multibyte_string (EMACS_INT, EMACS_INT, bool);
+
 DEFUN ("make-string", Fmake_string, Smake_string, 2, 3, 0,
        doc: /* Return a newly created string of length LENGTH, with INIT in 
each element.
 LENGTH must be an integer.
@@ -2118,19 +2180,20 @@ If optional argument MULTIBYTE is non-nil, the result 
will be
 a multibyte string even if INIT is an ASCII character.  */)
   (Lisp_Object length, Lisp_Object init, Lisp_Object multibyte)
 {
-  register Lisp_Object val;
-  int c;
+  Lisp_Object val;
   EMACS_INT nbytes;
 
   CHECK_FIXNAT (length);
   CHECK_CHARACTER (init);
 
-  c = XFIXNAT (init);
+  int c = XFIXNAT (init);
+  bool clearit = !c;
+
   if (ASCII_CHAR_P (c) && NILP (multibyte))
     {
       nbytes = XFIXNUM (length);
-      val = make_uninit_string (nbytes);
-      if (nbytes)
+      val = make_clear_string (nbytes, clearit);
+      if (nbytes && !clearit)
        {
          memset (SDATA (val), c, nbytes);
          SDATA (val)[nbytes] = 0;
@@ -2141,26 +2204,27 @@ a multibyte string even if INIT is an ASCII character.  
*/)
       unsigned char str[MAX_MULTIBYTE_LENGTH];
       ptrdiff_t len = CHAR_STRING (c, str);
       EMACS_INT string_len = XFIXNUM (length);
-      unsigned char *p, *beg, *end;
 
       if (INT_MULTIPLY_WRAPV (len, string_len, &nbytes))
        string_overflow ();
-      val = make_uninit_multibyte_string (string_len, nbytes);
-      for (beg = SDATA (val), p = beg, end = beg + nbytes; p < end; p += len)
+      val = make_clear_multibyte_string (string_len, nbytes, clearit);
+      if (!clearit)
        {
-         /* First time we just copy `str' to the data of `val'.  */
-         if (p == beg)
-           memcpy (p, str, len);
-         else
+         unsigned char *beg = SDATA (val), *end = beg + nbytes;
+         for (unsigned char *p = beg; p < end; p += len)
            {
-             /* Next time we copy largest possible chunk from
-                initialized to uninitialized part of `val'.  */
-             len = min (p - beg, end - p);
-             memcpy (p, beg, len);
+             /* First time we just copy STR to the data of VAL.  */
+             if (p == beg)
+               memcpy (p, str, len);
+             else
+               {
+                 /* Next time we copy largest possible chunk from
+                    initialized to uninitialized part of VAL.  */
+                 len = min (p - beg, end - p);
+                 memcpy (p, beg, len);
+               }
            }
        }
-      if (nbytes)
-       *p = 0;
     }
 
   return val;
@@ -2330,26 +2394,37 @@ make_specified_string (const char *contents,
 
 
 /* Return a unibyte Lisp_String set up to hold LENGTH characters
-   occupying LENGTH bytes.  */
+   occupying LENGTH bytes.  If CLEARIT, clear its contents to null
+   bytes; otherwise, the contents are uninitialized.  */
 
-Lisp_Object
-make_uninit_string (EMACS_INT length)
+static Lisp_Object
+make_clear_string (EMACS_INT length, bool clearit)
 {
   Lisp_Object val;
 
   if (!length)
     return empty_unibyte_string;
-  val = make_uninit_multibyte_string (length, length);
+  val = make_clear_multibyte_string (length, length, clearit);
   STRING_SET_UNIBYTE (val);
   return val;
 }
 
+/* Return a unibyte Lisp_String set up to hold LENGTH characters
+   occupying LENGTH bytes.  */
+
+Lisp_Object
+make_uninit_string (EMACS_INT length)
+{
+  return make_clear_string (length, false);
+}
+
 
 /* Return a multibyte Lisp_String set up to hold NCHARS characters
-   which occupy NBYTES bytes.  */
+   which occupy NBYTES bytes.  If CLEARIT, clear its contents to null
+   bytes; otherwise, the contents are uninitialized.  */
 
-Lisp_Object
-make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes)
+static Lisp_Object
+make_clear_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes, bool clearit)
 {
   Lisp_Object string;
   struct Lisp_String *s;
@@ -2361,12 +2436,21 @@ make_uninit_multibyte_string (EMACS_INT nchars, 
EMACS_INT nbytes)
 
   s = allocate_string ();
   s->u.s.intervals = NULL;
-  allocate_string_data (s, nchars, nbytes);
+  allocate_string_data (s, nchars, nbytes, clearit);
   XSETSTRING (string, s);
   string_chars_consed += nbytes;
   return string;
 }
 
+/* Return a multibyte Lisp_String set up to hold NCHARS characters
+   which occupy NBYTES bytes.  */
+
+Lisp_Object
+make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes)
+{
+  return make_clear_multibyte_string (nchars, nbytes, false);
+}
+
 /* Print arguments to BUF according to a FORMAT, then return
    a Lisp_String initialized with the data from BUF.  */
 
@@ -3023,6 +3107,14 @@ cleanup_vector (struct Lisp_Vector *vector)
       if (uptr->finalizer)
        uptr->finalizer (uptr->p);
     }
+#ifdef HAVE_MODULES
+  else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MODULE_FUNCTION))
+    {
+      ATTRIBUTE_MAY_ALIAS struct Lisp_Module_Function *function
+        = (struct Lisp_Module_Function *) vector;
+      module_finalize_function (function);
+    }
+#endif
   else if (NATIVE_COMP_FLAG
           && PSEUDOVECTOR_TYPEP (&vector->header, PVEC_NATIVE_COMP_UNIT))
     {
@@ -3145,7 +3237,7 @@ sweep_vectors (void)
    at most VECTOR_ELTS_MAX.  */
 
 static struct Lisp_Vector *
-allocate_vectorlike (ptrdiff_t len)
+allocate_vectorlike (ptrdiff_t len, bool clearit)
 {
   eassert (0 < len && len <= VECTOR_ELTS_MAX);
   ptrdiff_t nbytes = header_size + len * word_size;
@@ -3159,11 +3251,15 @@ allocate_vectorlike (ptrdiff_t len)
 #endif
 
   if (nbytes <= VBLOCK_BYTES_MAX)
-    p = allocate_vector_from_block (vroundup (nbytes));
+    {
+      p = allocate_vector_from_block (vroundup (nbytes));
+      if (clearit)
+       memclear (p, nbytes);
+    }
   else
     {
       struct large_vector *lv = lisp_malloc (large_vector_offset + nbytes,
-                                            MEM_TYPE_VECTORLIKE);
+                                            clearit, MEM_TYPE_VECTORLIKE);
       lv->next = large_vectors;
       large_vectors = lv;
       p = large_vector_vec (lv);
@@ -3186,20 +3282,37 @@ allocate_vectorlike (ptrdiff_t len)
 }
 
 
-/* Allocate a vector with LEN slots.  */
+/* Allocate a vector with LEN slots.  If CLEARIT, clear its slots;
+   otherwise the vector's slots are uninitialized.  */
 
-struct Lisp_Vector *
-allocate_vector (ptrdiff_t len)
+static struct Lisp_Vector *
+allocate_clear_vector (ptrdiff_t len, bool clearit)
 {
   if (len == 0)
     return XVECTOR (zero_vector);
   if (VECTOR_ELTS_MAX < len)
     memory_full (SIZE_MAX);
-  struct Lisp_Vector *v = allocate_vectorlike (len);
+  struct Lisp_Vector *v = allocate_vectorlike (len, clearit);
   v->header.size = len;
   return v;
 }
 
+/* Allocate a vector with LEN uninitialized slots.  */
+
+struct Lisp_Vector *
+allocate_vector (ptrdiff_t len)
+{
+  return allocate_clear_vector (len, false);
+}
+
+/* Allocate a vector with LEN nil slots.  */
+
+struct Lisp_Vector *
+allocate_nil_vector (ptrdiff_t len)
+{
+  return allocate_clear_vector (len, true);
+}
+
 
 /* Allocate other vector-like structures.  */
 
@@ -3216,7 +3329,7 @@ allocate_pseudovector (int memlen, int lisplen,
   eassert (lisplen <= size_max);
   eassert (memlen <= size_max + rest_max);
 
-  struct Lisp_Vector *v = allocate_vectorlike (memlen);
+  struct Lisp_Vector *v = allocate_vectorlike (memlen, false);
   /* Only the first LISPLEN slots will be traced normally by the GC.  */
   memclear (v->contents, zerolen * word_size);
   XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen);
@@ -3226,7 +3339,7 @@ allocate_pseudovector (int memlen, int lisplen,
 struct buffer *
 allocate_buffer (void)
 {
-  struct buffer *b = lisp_malloc (sizeof *b, MEM_TYPE_BUFFER);
+  struct buffer *b = lisp_malloc (sizeof *b, false, MEM_TYPE_BUFFER);
 
   BUFFER_PVEC_INIT (b);
   /* Put B on the chain of all buffers including killed ones.  */
@@ -3246,7 +3359,7 @@ allocate_record (EMACS_INT count)
   if (count > PSEUDOVECTOR_SIZE_MASK)
     error ("Attempt to allocate a record of %"pI"d slots; max is %d",
           count, PSEUDOVECTOR_SIZE_MASK);
-  struct Lisp_Vector *p = allocate_vectorlike (count);
+  struct Lisp_Vector *p = allocate_vectorlike (count, false);
   p->header.size = count;
   XSETPVECTYPE (p, PVEC_RECORD);
   return p;
@@ -3299,9 +3412,11 @@ See also the function `vector'.  */)
 Lisp_Object
 make_vector (ptrdiff_t length, Lisp_Object init)
 {
-  struct Lisp_Vector *p = allocate_vector (length);
-  for (ptrdiff_t i = 0; i < length; i++)
-    p->contents[i] = init;
+  bool clearit = NIL_IS_ZERO && NILP (init);
+  struct Lisp_Vector *p = allocate_clear_vector (length, clearit);
+  if (!clearit)
+    for (ptrdiff_t i = 0; i < length; i++)
+      p->contents[i] = init;
   return make_lisp_ptr (p, Lisp_Vectorlike);
 }
 
@@ -3450,7 +3565,7 @@ Its value is void, and its function definition and 
property list are nil.  */)
       if (symbol_block_index == SYMBOL_BLOCK_SIZE)
        {
          struct symbol_block *new
-           = lisp_malloc (sizeof *new, MEM_TYPE_SYMBOL);
+           = lisp_malloc (sizeof *new, false, MEM_TYPE_SYMBOL);
          new->next = symbol_block;
          symbol_block = new;
          symbol_block_index = 0;
@@ -3912,10 +4027,10 @@ refill_memory_reserve (void)
                                         MEM_TYPE_SPARE);
   if (spare_memory[5] == 0)
     spare_memory[5] = lisp_malloc (sizeof (struct string_block),
-                                  MEM_TYPE_SPARE);
+                                  false, MEM_TYPE_SPARE);
   if (spare_memory[6] == 0)
     spare_memory[6] = lisp_malloc (sizeof (struct string_block),
-                                  MEM_TYPE_SPARE);
+                                  false, MEM_TYPE_SPARE);
   if (spare_memory[0] && spare_memory[1] && spare_memory[5])
     Vmemory_full = Qnil;
 #endif
diff --git a/src/bytecode.c b/src/bytecode.c
index 9e75c90..4624379 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -220,10 +220,10 @@ DEFINE (Bdup, 0211)                                       
                \
 DEFINE (Bsave_excursion, 0212)                                         \
 DEFINE (Bsave_window_excursion, 0213) /* Obsolete since Emacs-24.1.  */        
\
 DEFINE (Bsave_restriction, 0214)                                       \
-DEFINE (Bcatch, 0215)                                                  \
+DEFINE (Bcatch, 0215)          /* Obsolete since Emacs-25.  */         \
                                                                        \
 DEFINE (Bunwind_protect, 0216)                                         \
-DEFINE (Bcondition_case, 0217)                                         \
+DEFINE (Bcondition_case, 0217) /* Obsolete since Emacs-25.  */         \
 DEFINE (Btemp_output_buffer_setup, 0220) /* Obsolete since Emacs-24.1.  */ \
 DEFINE (Btemp_output_buffer_show, 0221)  /* Obsolete since Emacs-24.1.  */ \
                                                                        \
@@ -763,7 +763,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, 
Lisp_Object maxdepth,
                                 save_restriction_save ());
          NEXT;
 
-       CASE (Bcatch):          /* Obsolete since 24.4.  */
+       CASE (Bcatch):          /* Obsolete since 25.  */
          {
            Lisp_Object v1 = POP;
            TOP = internal_catch (TOP, eval_sub, v1);
@@ -807,7 +807,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, 
Lisp_Object maxdepth,
            NEXT;
          }
 
-       CASE (Bcondition_case):         /* Obsolete since 24.4.  */
+       CASE (Bcondition_case):         /* Obsolete since 25.  */
          {
            Lisp_Object handlers = POP, body = POP;
            TOP = internal_lisp_condition_case (TOP, body, handlers);
diff --git a/src/callproc.c b/src/callproc.c
index 52b8950..07dcc4c 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -746,6 +746,8 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int 
filefd,
       int carryover = 0;
       bool display_on_the_fly = display_p;
       struct coding_system saved_coding = process_coding;
+      ptrdiff_t prepared_pos = 0; /* prepare_to_modify_buffer was last
+                                     called here.  */
 
       while (1)
        {
@@ -773,6 +775,33 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int 
filefd,
              if (display_on_the_fly)
                break;
            }
+          /* CHANGE FUNCTIONS
+             For each iteration of the enclosing while (1) loop which
+             yields data (i.e. nread > 0), before- and
+             after-change-functions are each invoked exactly once.
+             This is done directly from the current function only, by
+             calling prepare_to_modify_buffer and signal_after_change.
+             It is not done here by directing another function such as
+             insert_1_both to call them.  The call to
+             prepare_to_modify_buffer follows this comment, and there
+             is one call to signal_after_change in each of the
+             branches of the next `else if'.
+
+             Exceptionally, the insertion into the buffer is aborted
+             at the call to del_range_2 ~45 lines further down, this
+             function removing the newly inserted data.  At this stage
+             prepare_to_modify_buffer has been called, but
+             signal_after_change hasn't.  A continue statement
+             restarts the enclosing while (1) loop.  A second,
+             unwanted, call to `prepare_to_modify_buffer' is inhibited
+            by the test prepared_pos < PT.  The data are inserted
+             again, and this time signal_after_change gets called,
+             balancing the previous call to prepare_to_modify_buffer.  */
+          if ((prepared_pos < PT) && nread)
+            {
+              prepare_to_modify_buffer (PT, PT, NULL);
+              prepared_pos = PT;
+            }
 
          /* Now NREAD is the total amount of data in the buffer.  */
 
@@ -780,15 +809,16 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int 
filefd,
            ;
          else if (NILP (BVAR (current_buffer, enable_multibyte_characters))
                   && ! CODING_MAY_REQUIRE_DECODING (&process_coding))
-           insert_1_both (buf, nread, nread, 0, 1, 0);
+            {
+              insert_1_both (buf, nread, nread, 0, 0, 0);
+              signal_after_change (PT, 0, nread);
+            }
          else
            {                   /* We have to decode the input.  */
              Lisp_Object curbuf;
              ptrdiff_t count1 = SPECPDL_INDEX ();
 
              XSETBUFFER (curbuf, current_buffer);
-             /* FIXME: Call signal_after_change!  */
-             prepare_to_modify_buffer (PT, PT, NULL);
              /* We cannot allow after-change-functions be run
                 during decoding, because that might modify the
                 buffer, while we rely on process_coding.produced to
@@ -824,6 +854,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int 
filefd,
 
              TEMP_SET_PT_BOTH (PT + process_coding.produced_char,
                                PT_BYTE + process_coding.produced);
+              signal_after_change (PT, 0, process_coding.produced_char);
              carryover = process_coding.carryover_bytes;
              if (carryover > 0)
                memcpy (buf, process_coding.carryover,
diff --git a/src/coding.c b/src/coding.c
index ed755b1..8b54281 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -11745,6 +11745,8 @@ syms_of_coding (void)
 
   DEFSYM (Qignored, "ignored");
 
+  DEFSYM (Qutf_8_string_p, "utf-8-string-p");
+
   defsubr (&Scoding_system_p);
   defsubr (&Sread_coding_system);
   defsubr (&Sread_non_nil_coding_system);
diff --git a/src/data.c b/src/data.c
index b7337b1..7e3400e 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2326,61 +2326,45 @@ bool-vector.  IDX starts at 0.  */)
     }
   else /* STRINGP */
     {
-      int c;
-
       CHECK_IMPURE (array, XSTRING (array));
       if (idxval < 0 || idxval >= SCHARS (array))
        args_out_of_range (array, idx);
       CHECK_CHARACTER (newelt);
-      c = XFIXNAT (newelt);
+      int c = XFIXNAT (newelt);
+      ptrdiff_t idxval_byte;
+      int prev_bytes;
+      unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *p0 = workbuf, *p1;
 
       if (STRING_MULTIBYTE (array))
        {
-         ptrdiff_t idxval_byte, nbytes;
-         int prev_bytes, new_bytes;
-         unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *p0 = workbuf, *p1;
-
-         nbytes = SBYTES (array);
          idxval_byte = string_char_to_byte (array, idxval);
          p1 = SDATA (array) + idxval_byte;
          prev_bytes = BYTES_BY_CHAR_HEAD (*p1);
-         new_bytes = CHAR_STRING (c, p0);
-         if (prev_bytes != new_bytes)
-           {
-             /* We must relocate the string data.  */
-             ptrdiff_t nchars = SCHARS (array);
-             USE_SAFE_ALLOCA;
-             unsigned char *str = SAFE_ALLOCA (nbytes);
-
-             memcpy (str, SDATA (array), nbytes);
-             allocate_string_data (XSTRING (array), nchars,
-                                   nbytes + new_bytes - prev_bytes);
-             memcpy (SDATA (array), str, idxval_byte);
-             p1 = SDATA (array) + idxval_byte;
-             memcpy (p1 + new_bytes, str + idxval_byte + prev_bytes,
-                     nbytes - (idxval_byte + prev_bytes));
-             SAFE_FREE ();
-             clear_string_char_byte_cache ();
-           }
-         while (new_bytes--)
-           *p1++ = *p0++;
        }
-      else
+      else if (SINGLE_BYTE_CHAR_P (c))
        {
-         if (! SINGLE_BYTE_CHAR_P (c))
-           {
-             ptrdiff_t i;
-
-             for (i = SBYTES (array) - 1; i >= 0; i--)
-               if (SREF (array, i) >= 0x80)
-                 args_out_of_range (array, newelt);
-             /* ARRAY is an ASCII string.  Convert it to a multibyte
-                string, and try `aset' again.  */
-             STRING_SET_MULTIBYTE (array);
-             return Faset (array, idx, newelt);
-           }
          SSET (array, idxval, c);
+         return newelt;
        }
+      else
+       {
+         for (ptrdiff_t i = SBYTES (array) - 1; i >= 0; i--)
+           if (!ASCII_CHAR_P (SREF (array, i)))
+             args_out_of_range (array, newelt);
+         /* ARRAY is an ASCII string.  Convert it to a multibyte string.  */
+         STRING_SET_MULTIBYTE (array);
+         idxval_byte = idxval;
+         p1 = SDATA (array) + idxval_byte;
+         prev_bytes = 1;
+       }
+
+      int new_bytes = CHAR_STRING (c, p0);
+      if (prev_bytes != new_bytes)
+       p1 = resize_string_data (array, idxval_byte, prev_bytes, new_bytes);
+
+      do
+       *p1++ = *p0++;
+      while (--new_bytes != 0);
     }
 
   return newelt;
diff --git a/src/deps.mk b/src/deps.mk
index a7e1b55..4d162ee 100644
--- a/src/deps.mk
+++ b/src/deps.mk
@@ -239,9 +239,6 @@ xfont.o: dispextern.h xterm.h frame.h blockinput.h 
character.h charset.h \
 xftfont.o: xftfont.c dispextern.h xterm.h frame.h blockinput.h character.h \
    charset.h font.h lisp.h globals.h $(config_h) atimer.h systime.h \
    fontset.h ccl.h ftfont.h composite.h
-ftxfont.o: ftxfont.c dispextern.h xterm.h frame.h blockinput.h character.h \
-   charset.h font.h lisp.h globals.h $(config_h) atimer.h systime.h \
-   fontset.h ccl.h
 menu.o: menu.c lisp.h keyboard.h keymap.h frame.h termhooks.h blockinput.h \
    dispextern.h $(srcdir)/../lwlib/lwlib.h xterm.h gtkutil.h menu.h \
    lisp.h globals.h $(config_h) systime.h coding.h composite.h window.h \
diff --git a/src/dired.c b/src/dired.c
index 611477a..f013a4c 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -937,7 +937,7 @@ file_attributes (int fd, char const *name,
   int err = EINVAL;
 
 #if defined O_PATH && !defined HAVE_CYGWIN_O_PATH_BUG
-  int namefd = openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW);
+  int namefd = emacs_openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW, 0);
   if (namefd < 0)
     err = errno;
   else
@@ -970,7 +970,7 @@ file_attributes (int fd, char const *name,
         information to be accurate.  */
       w32_stat_get_owner_group = 1;
 #endif
-      err = fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW) == 0 ? 0 : errno;
+      err = emacs_fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW) == 0 ? 0 : errno;
 #ifdef WINDOWSNT
       w32_stat_get_owner_group = 0;
 #endif
diff --git a/src/dispnew.c b/src/dispnew.c
index b2a2570..d79ae83 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -534,6 +534,14 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix 
*matrix, int x, int y
       eassert (left >= 0 && right >= 0);
       matrix->left_margin_glyphs = left;
       matrix->right_margin_glyphs = right;
+
+      /* If we are resizing a window, make sure the previous mode-line
+        row of the window's current matrix is no longer marked as such.  */
+      if (w && matrix == w->current_matrix
+         && matrix->nrows > 0
+         && dim.height != matrix->nrows
+         && matrix->nrows <= matrix->rows_allocated)
+       MATRIX_MODE_LINE_ROW (matrix)->mode_line_p = false;
     }
 
   /* Number of rows to be used by MATRIX.  */
@@ -3735,11 +3743,10 @@ gui_update_window_end (struct window *w, bool 
cursor_on_p,
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
 
-  block_input ();
-
   /* Pseudo windows don't have cursors, so don't display them here.  */
   if (!w->pseudo_window_p)
     {
+      block_input ();
 
       if (cursor_on_p)
        display_and_set_cursor (w, true,
@@ -3753,6 +3760,7 @@ gui_update_window_end (struct window *w, bool cursor_on_p,
          else
            gui_draw_vertical_border (w);
        }
+      unblock_input ();
     }
 
   /* If a row with mouse-face was overwritten, arrange for
@@ -3770,7 +3778,6 @@ gui_update_window_end (struct window *w, bool cursor_on_p,
     FRAME_RIF (f)->update_window_end_hook (w,
                                            cursor_on_p,
                                            mouse_face_overwritten_p);
-  unblock_input ();
 }
 
 #endif /* HAVE_WINDOW_SYSTEM  */
@@ -4352,6 +4359,14 @@ scrolling_window (struct window *w, int tab_line_p)
     return 0;
 #endif
 
+  /* Can't scroll the display of w32 GUI frames when position of point
+     is indicated by the system caret, because scrolling the display
+     will then "copy" the pixels used by the caret.  */
+#ifdef HAVE_NTGUI
+  if (w32_use_visible_system_caret)
+    return 0;
+#endif
+
   /* Give up if some rows in the desired matrix are not enabled.  */
   if (! MATRIX_ROW_ENABLED_P (desired_matrix, i))
     return -1;
diff --git a/src/editfns.c b/src/editfns.c
index 4e35784..3f1b3aa 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -3031,7 +3031,7 @@ width, and precision specifiers, as follows:
   %<field><flags><width><precision>character
 
 where field is [0-9]+ followed by a literal dollar "$", flags is
-[+ #-0]+, width is [0-9]+, and precision is a literal period "."
+[+ #0-]+, width is [0-9]+, and precision is a literal period "."
 followed by [0-9]+.
 
 If a %-sequence is numbered with a field with positive value N, the
diff --git a/src/emacs-module.c b/src/emacs-module.c
index bbb0e3d..60f1641 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -213,6 +213,25 @@ static bool value_storage_contains_p (const struct 
emacs_value_storage *,
 
 static bool module_assertions = false;
 
+
+/* Small helper functions.  */
+
+/* Interprets the string at STR with length LEN as UTF-8 string.
+   Signals an error if it's not a valid UTF-8 string.  */
+
+static Lisp_Object
+module_decode_utf_8 (const char *str, ptrdiff_t len)
+{
+  /* We set HANDLE-8-BIT and HANDLE-OVER-UNI to nil to signal an error
+     if the argument is not a valid UTF-8 string.  While it isn't
+     documented how make_string and make_function behave in this case,
+     signaling an error is the most defensive and obvious reaction. */
+  Lisp_Object s = decode_string_utf_8 (Qnil, str, len, Qnil, false, Qnil, 
Qnil);
+  CHECK_TYPE (!NILP (s), Qutf_8_string_p, make_string_from_utf8 (str, len));
+  return s;
+}
+
+
 /* Convenience macros for non-local exit handling.  */
 
 /* FIXME: The following implementation for non-local exit handling
@@ -327,6 +346,12 @@ static bool module_assertions = false;
   MODULE_HANDLE_NONLOCAL_EXIT (error_retval)
 
 static void
+CHECK_MODULE_FUNCTION (Lisp_Object obj)
+{
+  CHECK_TYPE (MODULE_FUNCTIONP (obj), Qmodule_function_p, obj);
+}
+
+static void
 CHECK_USER_PTR (Lisp_Object obj)
 {
   CHECK_TYPE (USER_PTRP (obj), Quser_ptrp, obj);
@@ -478,6 +503,7 @@ struct Lisp_Module_Function
   ptrdiff_t min_arity, max_arity;
   emacs_function subr;
   void *data;
+  emacs_finalizer finalizer;
 } GCALIGNED_STRUCT;
 
 static struct Lisp_Module_Function *
@@ -511,9 +537,11 @@ module_make_function (emacs_env *env, ptrdiff_t min_arity, 
ptrdiff_t max_arity,
   function->max_arity = max_arity;
   function->subr = func;
   function->data = data;
+  function->finalizer = NULL;
 
   if (docstring)
-    function->documentation = build_string_from_utf8 (docstring);
+    function->documentation
+      = module_decode_utf_8 (docstring, strlen (docstring));
 
   Lisp_Object result;
   XSET_MODULE_FUNCTION (result, function);
@@ -522,6 +550,32 @@ module_make_function (emacs_env *env, ptrdiff_t min_arity, 
ptrdiff_t max_arity,
   return lisp_to_value (env, result);
 }
 
+static emacs_finalizer
+module_get_function_finalizer (emacs_env *env, emacs_value arg)
+{
+  MODULE_FUNCTION_BEGIN (NULL);
+  Lisp_Object lisp = value_to_lisp (arg);
+  CHECK_MODULE_FUNCTION (lisp);
+  return XMODULE_FUNCTION (lisp)->finalizer;
+}
+
+static void
+module_set_function_finalizer (emacs_env *env, emacs_value arg,
+                               emacs_finalizer fin)
+{
+  MODULE_FUNCTION_BEGIN ();
+  Lisp_Object lisp = value_to_lisp (arg);
+  CHECK_MODULE_FUNCTION (lisp);
+  XMODULE_FUNCTION (lisp)->finalizer = fin;
+}
+
+void
+module_finalize_function (const struct Lisp_Module_Function *func)
+{
+  if (func->finalizer != NULL)
+    func->finalizer (func->data);
+}
+
 static emacs_value
 module_funcall (emacs_env *env, emacs_value func, ptrdiff_t nargs,
                emacs_value *args)
@@ -660,7 +714,7 @@ module_make_string (emacs_env *env, const char *str, 
ptrdiff_t len)
   MODULE_FUNCTION_BEGIN (NULL);
   if (! (0 <= len && len <= STRING_BYTES_BOUND))
     overflow_error ();
-  Lisp_Object lstr = make_string_from_utf8 (str, len);
+  Lisp_Object lstr = module_decode_utf_8 (str, len);
   return lisp_to_value (env, lstr);
 }
 
@@ -1064,6 +1118,12 @@ module_function_address (const struct 
Lisp_Module_Function *function)
   return (module_funcptr) function->subr;
 }
 
+void *
+module_function_data (const struct Lisp_Module_Function *function)
+{
+  return function->data;
+}
+
 
 /* Helper functions.  */
 
@@ -1329,6 +1389,8 @@ initialize_environment (emacs_env *env, struct 
emacs_env_private *priv)
   env->make_time = module_make_time;
   env->extract_big_integer = module_extract_big_integer;
   env->make_big_integer = module_make_big_integer;
+  env->get_function_finalizer = module_get_function_finalizer;
+  env->set_function_finalizer = module_set_function_finalizer;
   Vmodule_environments = Fcons (make_mint_ptr (env), Vmodule_environments);
   return env;
 }
diff --git a/src/emacs-module.h.in b/src/emacs-module.h.in
index 7065f13..cd75c09 100644
--- a/src/emacs-module.h.in
+++ b/src/emacs-module.h.in
@@ -42,6 +42,12 @@ information how to write modules and use this header file.
 # define EMACS_NOEXCEPT
 #endif
 
+#if defined __cplusplus && __cplusplus >= 201703L
+# define EMACS_NOEXCEPT_TYPEDEF noexcept
+#else
+# define EMACS_NOEXCEPT_TYPEDEF
+#endif
+
 #ifdef __has_attribute
 #if __has_attribute(__nonnull__)
 # define EMACS_ATTRIBUTE_NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
@@ -88,11 +94,11 @@ struct emacs_runtime
 typedef emacs_value (*emacs_function) (emacs_env *env, ptrdiff_t nargs,
                                        emacs_value *args,
                                        void *data)
-  EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL (1);
+  EMACS_NOEXCEPT_TYPEDEF EMACS_ATTRIBUTE_NONNULL (1);
 
-/* Function prototype for module user-pointer finalizers.  These must
-   not throw C++ exceptions.  */
-typedef void (*emacs_finalizer) (void *data) EMACS_NOEXCEPT;
+/* Function prototype for module user-pointer and function finalizers.
+   These must not throw C++ exceptions.  */
+typedef void (*emacs_finalizer) (void *data) EMACS_NOEXCEPT_TYPEDEF;
 
 /* Possible Emacs function call outcomes.  */
 enum emacs_funcall_exit
diff --git a/src/emacs.c b/src/emacs.c
index 90ab7ac..da08aeb 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -930,7 +930,6 @@ main (int argc, char **argv)
      for pointers.  */
   void *stack_bottom_variable;
 
-  bool do_initial_setlocale;
   bool no_loadup = false;
   char *junk = 0;
   char *dname_arg = 0;
@@ -1235,19 +1234,20 @@ main (int argc, char **argv)
   set_binary_mode (STDOUT_FILENO, O_BINARY);
 #endif /* MSDOS */
 
-  /* Skip initial setlocale if LC_ALL is "C", as it's not needed in that case.
-     The build procedure uses this while dumping, to ensure that the
-     dumped Emacs does not have its system locale tables initialized,
-     as that might cause screwups when the dumped Emacs starts up.  */
-  {
-    char *lc_all = getenv ("LC_ALL");
-    do_initial_setlocale = ! lc_all || strcmp (lc_all, "C");
-  }
-
-  /* Set locale now, so that initial error messages are localized properly.
-     fixup_locale must wait until later, since it builds strings.  */
-  if (do_initial_setlocale)
-    setlocale (LC_ALL, "");
+  /* Set locale, so that initial error messages are localized properly.
+     However, skip this if LC_ALL is "C", as it's not needed in that case.
+     Skipping helps if dumping with unexec, to ensure that the dumped
+     Emacs does not have its system locale tables initialized, as that
+     might cause screwups when the dumped Emacs starts up.  */
+  char *lc_all = getenv ("LC_ALL");
+  if (! (lc_all && strcmp (lc_all, "C") == 0))
+    {
+      #ifdef HAVE_NS
+        ns_init_locale ();
+      #endif
+      setlocale (LC_ALL, "");
+      fixup_locale ();
+    }
   text_quoting_flag = using_utf8 ();
 
   inhibit_window_system = 0;
@@ -1576,14 +1576,6 @@ Using an Emacs configured with --with-x-toolkit=lucid 
does not have this problem
   init_alloc ();
   init_bignum ();
   init_threads ();
-
-  if (do_initial_setlocale)
-    {
-      fixup_locale ();
-      Vsystem_messages_locale = Vprevious_system_messages_locale;
-      Vsystem_time_locale = Vprevious_system_time_locale;
-    }
-
   init_eval ();
   init_atimer ();
   running_asynch_code = 0;
@@ -1626,10 +1618,6 @@ Using an Emacs configured with --with-x-toolkit=lucid 
does not have this problem
 
 #ifdef HAVE_NS
   ns_pool = ns_alloc_autorelease_pool ();
-#ifdef NS_IMPL_GNUSTEP
-  /* GNUstep stupidly resets our locale settings after we made them.  */
-  fixup_locale ();
-#endif
 
   if (!noninteractive)
     {
@@ -1740,11 +1728,6 @@ Using an Emacs configured with --with-x-toolkit=lucid 
does not have this problem
   globals_of_gfilenotify ();
 #endif
 
-#ifdef HAVE_NS
-  /* Initialize the locale from user defaults.  */
-  ns_init_locale ();
-#endif
-
   /* Initialize and GC-protect Vinitial_environment and
      Vprocess_environment before set_initial_environment fills them
      in.  */
@@ -2622,25 +2605,25 @@ synchronize_locale (int category, Lisp_Object *plocale, 
Lisp_Object desired_loca
   if (! EQ (*plocale, desired_locale))
     {
       *plocale = desired_locale;
-#ifdef WINDOWSNT
+      char const *locale_string
+       = STRINGP (desired_locale) ? SSDATA (desired_locale) : "";
+# ifdef WINDOWSNT
       /* Changing categories like LC_TIME usually requires specifying
         an encoding suitable for the new locale, but MS-Windows's
         'setlocale' will only switch the encoding when LC_ALL is
         specified.  So we ignore CATEGORY, use LC_ALL instead, and
         then restore LC_NUMERIC to "C", so reading and printing
         numbers is unaffected.  */
-      setlocale (LC_ALL, (STRINGP (desired_locale)
-                         ? SSDATA (desired_locale)
-                         : ""));
+      setlocale (LC_ALL, locale_string);
       fixup_locale ();
-#else  /* !WINDOWSNT */
-      setlocale (category, (STRINGP (desired_locale)
-                           ? SSDATA (desired_locale)
-                           : ""));
-#endif /* !WINDOWSNT */
+# else /* !WINDOWSNT */
+      setlocale (category, locale_string);
+# endif        /* !WINDOWSNT */
     }
 }
 
+static Lisp_Object Vprevious_system_time_locale;
+
 /* Set system time locale to match Vsystem_time_locale, if possible.  */
 void
 synchronize_system_time_locale (void)
@@ -2649,15 +2632,19 @@ synchronize_system_time_locale (void)
                      Vsystem_time_locale);
 }
 
+# ifdef LC_MESSAGES
+static Lisp_Object Vprevious_system_messages_locale;
+# endif
+
 /* Set system messages locale to match Vsystem_messages_locale, if
    possible.  */
 void
 synchronize_system_messages_locale (void)
 {
-#ifdef LC_MESSAGES
+# ifdef LC_MESSAGES
   synchronize_locale (LC_MESSAGES, &Vprevious_system_messages_locale,
                      Vsystem_messages_locale);
-#endif
+# endif
 }
 #endif /* HAVE_SETLOCALE */
 
@@ -2979,19 +2966,16 @@ build directory.  */);
   DEFVAR_LISP ("system-messages-locale", Vsystem_messages_locale,
               doc: /* System locale for messages.  */);
   Vsystem_messages_locale = Qnil;
-
-  DEFVAR_LISP ("previous-system-messages-locale",
-              Vprevious_system_messages_locale,
-              doc: /* Most recently used system locale for messages.  */);
+#ifdef LC_MESSAGES
   Vprevious_system_messages_locale = Qnil;
+  staticpro (&Vprevious_system_messages_locale);
+#endif
 
   DEFVAR_LISP ("system-time-locale", Vsystem_time_locale,
               doc: /* System locale for time.  */);
   Vsystem_time_locale = Qnil;
-
-  DEFVAR_LISP ("previous-system-time-locale", Vprevious_system_time_locale,
-              doc: /* Most recently used system locale for time.  */);
   Vprevious_system_time_locale = Qnil;
+  staticpro (&Vprevious_system_time_locale);
 
   DEFVAR_LISP ("before-init-time", Vbefore_init_time,
               doc: /* Value of `current-time' before Emacs begins 
initialization.  */);
diff --git a/src/fileio.c b/src/fileio.c
index 6e2fe2f..87a17ea 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1952,7 +1952,10 @@ barf_or_query_if_file_exists (Lisp_Object absname, bool 
known_to_exist,
 
   encoded_filename = ENCODE_FILE (absname);
 
-  if (! known_to_exist && lstat (SSDATA (encoded_filename), &statbuf) == 0)
+  if (! known_to_exist
+      && (emacs_fstatat (AT_FDCWD, SSDATA (encoded_filename),
+                        &statbuf, AT_SYMLINK_NOFOLLOW)
+         == 0))
     {
       if (S_ISDIR (statbuf.st_mode))
        xsignal2 (Qfile_error,
@@ -2555,7 +2558,9 @@ This is what happens in interactive use with M-x.  */)
   bool dirp = !NILP (Fdirectory_name_p (file));
   if (!dirp)
     {
-      if (lstat (SSDATA (encoded_file), &file_st) != 0)
+      if (emacs_fstatat (AT_FDCWD, SSDATA (encoded_file),
+                        &file_st, AT_SYMLINK_NOFOLLOW)
+         != 0)
        report_file_error ("Renaming", list2 (file, newname));
       dirp = S_ISDIR (file_st.st_mode) != 0;
     }
@@ -2928,7 +2933,8 @@ file_directory_p (Lisp_Object file)
 #else
 # ifdef O_PATH
   /* Use O_PATH if available, as it avoids races and EOVERFLOW issues.  */
-  int fd = openat (AT_FDCWD, SSDATA (file), O_PATH | O_CLOEXEC | O_DIRECTORY);
+  int fd = emacs_openat (AT_FDCWD, SSDATA (file),
+                        O_PATH | O_CLOEXEC | O_DIRECTORY, 0);
   if (0 <= fd)
     {
       emacs_close (fd);
@@ -2939,9 +2945,9 @@ file_directory_p (Lisp_Object file)
   /* O_PATH is defined but evidently this Linux kernel predates 2.6.39.
      Fall back on generic POSIX code.  */
 # endif
-  /* Use file_accessible_directory_p, as it avoids stat EOVERFLOW
+  /* Use file_accessible_directory_p, as it avoids fstatat EOVERFLOW
      problems and could be cheaper.  However, if it fails because FILE
-     is inaccessible, fall back on stat; if the latter fails with
+     is inaccessible, fall back on fstatat; if the latter fails with
      EOVERFLOW then FILE must have been a directory unless a race
      condition occurred (a problem hard to work around portably).  */
   if (file_accessible_directory_p (file))
@@ -2949,7 +2955,7 @@ file_directory_p (Lisp_Object file)
   if (errno != EACCES)
     return false;
   struct stat st;
-  if (stat (SSDATA (file), &st) != 0)
+  if (emacs_fstatat (AT_FDCWD, SSDATA (file), &st, 0) != 0)
     return errno == EOVERFLOW;
   if (S_ISDIR (st.st_mode))
     return true;
@@ -3080,7 +3086,7 @@ See `file-symlink-p' to distinguish symlinks.  */)
   Vw32_get_true_file_attributes = Qt;
 #endif
 
-  int stat_result = stat (SSDATA (absname), &st);
+  int stat_result = emacs_fstatat (AT_FDCWD, SSDATA (absname), &st, 0);
 
 #ifdef WINDOWSNT
   Vw32_get_true_file_attributes = true_attributes;
@@ -3340,7 +3346,7 @@ Return nil if FILENAME does not exist.  */)
   if (!NILP (handler))
     return call2 (handler, Qfile_modes, absname);
 
-  if (stat (SSDATA (ENCODE_FILE (absname)), &st) != 0)
+  if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (absname)), &st, 0) != 0)
     return file_attribute_errno (absname, errno);
   return make_fixnum (st.st_mode & 07777);
 }
@@ -3486,7 +3492,7 @@ otherwise, if FILE2 does not exist, the answer is t.  */)
     return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
 
   int err1;
-  if (stat (SSDATA (ENCODE_FILE (absname1)), &st1) == 0)
+  if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (absname1)), &st1, 0) == 0)
     err1 = 0;
   else
     {
@@ -3494,7 +3500,7 @@ otherwise, if FILE2 does not exist, the answer is t.  */)
       if (err1 != EOVERFLOW)
        return file_attribute_errno (absname1, err1);
     }
-  if (stat (SSDATA (ENCODE_FILE (absname2)), &st2) != 0)
+  if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (absname2)), &st2, 0) != 0)
     {
       file_attribute_errno (absname2, errno);
       return Qt;
@@ -3880,7 +3886,7 @@ by calling `format-decode', which see.  */)
          if (end_offset < 0)
            buffer_overflow ();
 
-         /* The file size returned from stat may be zero, but data
+         /* The file size returned from fstat may be zero, but data
             may be readable nonetheless, for example when this is a
             file in the /proc filesystem.  */
          if (end_offset == 0)
@@ -4975,6 +4981,7 @@ Optional fourth argument APPEND if non-nil means
 Optional fifth argument VISIT, if t or a string, means
   set the last-save-file-modtime of buffer to this file's modtime
   and mark buffer not modified.
+If VISIT is t, the buffer is marked as visiting FILENAME.
 If VISIT is a string, it is a second file name;
   the output goes to FILENAME, but the buffer is marked as visiting VISIT.
   VISIT is also the file name to lock and unlock for clash detection.
@@ -5624,7 +5631,7 @@ See Info node `(elisp)Modification Time' for more 
details.  */)
 
   filename = ENCODE_FILE (BVAR (b, filename));
 
-  mtime = (stat (SSDATA (filename), &st) == 0
+  mtime = (emacs_fstatat (AT_FDCWD, SSDATA (filename), &st, 0) == 0
           ? get_stat_mtime (&st)
           : time_error_value (errno));
   if (timespec_cmp (mtime, b->modtime) == 0
@@ -5688,7 +5695,8 @@ in `current-time' or an integer flag as returned by 
`visited-file-modtime'.  */)
        /* The handler can find the file name the same way we did.  */
        return call2 (handler, Qset_visited_file_modtime, Qnil);
 
-      if (stat (SSDATA (ENCODE_FILE (filename)), &st) == 0)
+      if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (filename)), &st, 0)
+         == 0)
         {
          current_buffer->modtime = get_stat_mtime (&st);
           current_buffer->modtime_size = st.st_size;
@@ -5727,12 +5735,14 @@ auto_save_1 (void)
   /* Get visited file's mode to become the auto save file's mode.  */
   if (! NILP (BVAR (current_buffer, filename)))
     {
-      if (stat (SSDATA (BVAR (current_buffer, filename)), &st) >= 0)
+      if (emacs_fstatat (AT_FDCWD, SSDATA (BVAR (current_buffer, filename)),
+                        &st, 0)
+         == 0)
        /* But make sure we can overwrite it later!  */
        auto_save_mode_bits = (st.st_mode | 0600) & 0777;
       else if (modes = Ffile_modes (BVAR (current_buffer, filename)),
               FIXNUMP (modes))
-       /* Remote files don't cooperate with stat.  */
+       /* Remote files don't cooperate with fstatat.  */
        auto_save_mode_bits = (XFIXNUM (modes) | 0600) & 0777;
     }
 
diff --git a/src/filelock.c b/src/filelock.c
index b28f16e..73202f0 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -347,7 +347,8 @@ rename_lock_file (char const *old, char const *new, bool 
force)
         potential race condition since some other process may create
         NEW immediately after the existence check, but it's the best
         we can portably do here.  */
-      if (lstat (new, &st) == 0 || errno == EOVERFLOW)
+      if (emacs_fstatat (AT_FDCWD, new, &st, AT_SYMLINK_NOFOLLOW) == 0
+         || errno == EOVERFLOW)
        {
          errno = EEXIST;
          return -1;
diff --git a/src/fns.c b/src/fns.c
index 3b5feac..436ef1c 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -47,6 +47,7 @@ static void sort_vector_copy (Lisp_Object, ptrdiff_t,
 enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES };
 static bool internal_equal (Lisp_Object, Lisp_Object,
                            enum equal_kind, int, Lisp_Object);
+static EMACS_UINT sxhash_obj (Lisp_Object, int);
 
 DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
        doc: /* Return the ARGUMENT unchanged.  */
@@ -2433,6 +2434,9 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum 
equal_kind equal_kind,
           same size.  */
        if (ASIZE (o2) != size)
          return false;
+
+       /* Compare bignums, overlays, markers, and boolvectors
+          specially, by comparing their values.  */
        if (BIGNUMP (o1))
          return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0;
        if (OVERLAYP (o1))
@@ -2453,21 +2457,12 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum 
equal_kind equal_kind,
                    && (XMARKER (o1)->buffer == 0
                        || XMARKER (o1)->bytepos == XMARKER (o2)->bytepos));
          }
-       /* Boolvectors are compared much like strings.  */
        if (BOOL_VECTOR_P (o1))
          {
            EMACS_INT size = bool_vector_size (o1);
-           if (size != bool_vector_size (o2))
-             return false;
-           if (memcmp (bool_vector_data (o1), bool_vector_data (o2),
-                       bool_vector_bytes (size)))
-             return false;
-           return true;
-         }
-       if (WINDOW_CONFIGURATIONP (o1))
-         {
-           eassert (equal_kind != EQUAL_NO_QUIT);
-           return compare_window_configurations (o1, o2, false);
+           return (size == bool_vector_size (o2)
+                   && !memcmp (bool_vector_data (o1), bool_vector_data (o2),
+                               bool_vector_bytes (size)));
          }
 
        /* Aside from them, only true vectors, char-tables, compiled
@@ -2493,16 +2488,11 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum 
equal_kind equal_kind,
       break;
 
     case Lisp_String:
-      if (SCHARS (o1) != SCHARS (o2))
-       return false;
-      if (SBYTES (o1) != SBYTES (o2))
-       return false;
-      if (memcmp (SDATA (o1), SDATA (o2), SBYTES (o1)))
-       return false;
-      if (equal_kind == EQUAL_INCLUDING_PROPERTIES
-         && !compare_string_intervals (o1, o2))
-       return false;
-      return true;
+      return (SCHARS (o1) == SCHARS (o2)
+             && SBYTES (o1) == SBYTES (o2)
+             && !memcmp (SDATA (o1), SDATA (o2), SBYTES (o1))
+             && (equal_kind != EQUAL_INCLUDING_PROPERTIES
+                 || compare_string_intervals (o1, o2)));
 
     default:
       break;
@@ -4022,7 +4012,7 @@ hashfn_eq (Lisp_Object key, struct Lisp_Hash_Table *h)
 Lisp_Object
 hashfn_equal (Lisp_Object key, struct Lisp_Hash_Table *h)
 {
-  return make_ufixnum (sxhash (key, 0));
+  return make_ufixnum (sxhash (key));
 }
 
 /* Ignore HT and return a hash code for KEY which uses 'eql' to compare keys.
@@ -4042,7 +4032,7 @@ hashfn_user_defined (Lisp_Object key, struct 
Lisp_Hash_Table *h)
 {
   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, 0));
+  return FIXNUMP (hash) ? hash : make_ufixnum (sxhash (hash));
 }
 
 struct hash_table_test const
@@ -4606,13 +4596,13 @@ sxhash_list (Lisp_Object list, int depth)
         CONSP (list) && i < SXHASH_MAX_LEN;
         list = XCDR (list), ++i)
       {
-       EMACS_UINT hash2 = sxhash (XCAR (list), depth + 1);
+       EMACS_UINT hash2 = sxhash_obj (XCAR (list), depth + 1);
        hash = sxhash_combine (hash, hash2);
       }
 
   if (!NILP (list))
     {
-      EMACS_UINT hash2 = sxhash (list, depth + 1);
+      EMACS_UINT hash2 = sxhash_obj (list, depth + 1);
       hash = sxhash_combine (hash, hash2);
     }
 
@@ -4632,7 +4622,7 @@ sxhash_vector (Lisp_Object vec, int depth)
   n = min (SXHASH_MAX_LEN, hash & PSEUDOVECTOR_FLAG ? PVSIZE (vec) : hash);
   for (i = 0; i < n; ++i)
     {
-      EMACS_UINT hash2 = sxhash (AREF (vec, i), depth + 1);
+      EMACS_UINT hash2 = sxhash_obj (AREF (vec, i), depth + 1);
       hash = sxhash_combine (hash, hash2);
     }
 
@@ -4675,58 +4665,78 @@ sxhash_bignum (Lisp_Object bignum)
    structure.  Value is an unsigned integer clipped to INTMASK.  */
 
 EMACS_UINT
-sxhash (Lisp_Object obj, int depth)
+sxhash (Lisp_Object obj)
 {
-  EMACS_UINT hash;
+  return sxhash_obj (obj, 0);
+}
 
+static EMACS_UINT
+sxhash_obj (Lisp_Object obj, int depth)
+{
   if (depth > SXHASH_MAX_DEPTH)
     return 0;
 
   switch (XTYPE (obj))
     {
     case_Lisp_Int:
-      hash = XUFIXNUM (obj);
-      break;
+      return XUFIXNUM (obj);
 
     case Lisp_Symbol:
-      hash = XHASH (obj);
-      break;
+      return XHASH (obj);
 
     case Lisp_String:
-      hash = sxhash_string (SSDATA (obj), SBYTES (obj));
-      break;
+      return sxhash_string (SSDATA (obj), SBYTES (obj));
 
-      /* This can be everything from a vector to an overlay.  */
     case Lisp_Vectorlike:
-      if (BIGNUMP (obj))
-       hash = sxhash_bignum (obj);
-      else if (VECTORP (obj) || RECORDP (obj))
-       /* According to the CL HyperSpec, two arrays are equal only if
-          they are `eq', except for strings and bit-vectors.  In
-          Emacs, this works differently.  We have to compare element
-          by element.  Same for records.  */
-       hash = sxhash_vector (obj, depth);
-      else if (BOOL_VECTOR_P (obj))
-       hash = sxhash_bool_vector (obj);
-      else
-       /* Others are `equal' if they are `eq', so let's take their
-          address as hash.  */
-       hash = XHASH (obj);
-      break;
+      {
+       enum pvec_type pvec_type = PSEUDOVECTOR_TYPE (XVECTOR (obj));
+       if (! (PVEC_NORMAL_VECTOR < pvec_type && pvec_type < PVEC_COMPILED))
+         {
+           /* According to the CL HyperSpec, two arrays are equal only if
+              they are 'eq', except for strings and bit-vectors.  In
+              Emacs, this works differently.  We have to compare element
+              by element.  Same for pseudovectors that internal_equal
+              examines the Lisp contents of.  */
+           return (SUB_CHAR_TABLE_P (obj)
+                   /* 'sxhash_vector' can't be applies to a sub-char-table and
+                     it's probably not worth looking into them anyway!  */
+                   ? 42
+                   : sxhash_vector (obj, depth));
+         }
+       else if (pvec_type == PVEC_BIGNUM)
+         return sxhash_bignum (obj);
+       else if (pvec_type == PVEC_MARKER)
+         {
+           ptrdiff_t bytepos
+             = XMARKER (obj)->buffer ? XMARKER (obj)->bytepos : 0;
+           EMACS_UINT hash
+             = sxhash_combine ((intptr_t) XMARKER (obj)->buffer, bytepos);
+           return SXHASH_REDUCE (hash);
+         }
+       else if (pvec_type == PVEC_BOOL_VECTOR)
+         return sxhash_bool_vector (obj);
+       else if (pvec_type == PVEC_OVERLAY)
+         {
+           EMACS_UINT hash = sxhash_obj (OVERLAY_START (obj), depth);
+           hash = sxhash_combine (hash, sxhash_obj (OVERLAY_END (obj), depth));
+           hash = sxhash_combine (hash, sxhash_obj (XOVERLAY (obj)->plist, 
depth));
+           return SXHASH_REDUCE (hash);
+         }
+       else
+         /* Others are 'equal' if they are 'eq', so take their
+            address as hash.  */
+         return XHASH (obj);
+      }
 
     case Lisp_Cons:
-      hash = sxhash_list (obj, depth);
-      break;
+      return sxhash_list (obj, depth);
 
     case Lisp_Float:
-      hash = sxhash_float (XFLOAT_DATA (obj));
-      break;
+      return sxhash_float (XFLOAT_DATA (obj));
 
     default:
       emacs_abort ();
     }
-
-  return hash;
 }
 
 
diff --git a/src/font.c b/src/font.c
index 2b90903..bb39aef 100644
--- a/src/font.c
+++ b/src/font.c
@@ -5545,7 +5545,6 @@ cause Xft crashes.  Only has an effect in Xft builds.  
*/);
 #ifdef USE_CAIRO
   syms_of_ftcrfont ();
 #else
-  syms_of_ftxfont ();
 #ifdef HAVE_XFT
   syms_of_xftfont ();
 #endif  /* HAVE_XFT */
diff --git a/src/font.h b/src/font.h
index 633d927..0561e3c 100644
--- a/src/font.h
+++ b/src/font.h
@@ -69,8 +69,8 @@ INLINE_HEADER_BEGIN
 
 enum font_property_index
   {
-    /* FONT-TYPE is a symbol indicating a font backend; currently `x',
-       `xft', and `ftx' are available on X, `uniscribe' and `gdi' on
+    /* FONT-TYPE is a symbol indicating a font backend; currently `x'
+       and `xft' are available on X, `uniscribe' and `gdi' on
        Windows, and `ns' under Cocoa / GNUstep.  */
     FONT_TYPE_INDEX,
 
@@ -938,7 +938,6 @@ extern void syms_of_ftfont (void);
 extern struct font_driver const xfont_driver;
 extern Lisp_Object xfont_get_cache (struct frame *);
 extern void syms_of_xfont (void);
-extern void syms_of_ftxfont (void);
 #ifdef HAVE_XFT
 extern struct font_driver const xftfont_driver;
 #ifdef HAVE_HARFBUZZ
@@ -946,7 +945,6 @@ extern struct font_driver xfthbfont_driver;
 #endif /* HAVE_HARFBUZZ */
 #endif
 #if defined HAVE_FREETYPE || defined HAVE_XFT
-extern struct font_driver const ftxfont_driver;
 extern void syms_of_xftfont (void);
 #endif
 #ifdef HAVE_BDFFONT
diff --git a/src/frame.c b/src/frame.c
index 88d6f22..51fc78a 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -904,7 +904,7 @@ make_frame (bool mini_p)
   f->last_tool_bar_item = -1;
 #endif
 #ifdef NS_IMPL_COCOA
-  f->ns_appearance = ns_appearance_aqua;
+  f->ns_appearance = ns_appearance_system_default;
   f->ns_transparent_titlebar = false;
 #endif
 #endif
diff --git a/src/frame.h b/src/frame.h
index 6ab690c..68dc0ce 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -69,8 +69,9 @@ enum internal_border_part
 #ifdef NS_IMPL_COCOA
 enum ns_appearance_type
   {
-   ns_appearance_aqua,
-   ns_appearance_vibrant_dark
+    ns_appearance_system_default,
+    ns_appearance_aqua,
+    ns_appearance_vibrant_dark
   };
 #endif
 #endif /* HAVE_WINDOW_SYSTEM */
diff --git a/src/ftxfont.c b/src/ftxfont.c
deleted file mode 100644
index 9bbb2c0..0000000
--- a/src/ftxfont.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/* ftxfont.c -- FreeType font driver on X (without using XFT).
-   Copyright (C) 2006-2020 Free Software Foundation, Inc.
-   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
-     National Institute of Advanced Industrial Science and Technology (AIST)
-     Registration Number H13PRO009
-
-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/>.  */
-
-#include <config.h>
-#include <X11/Xlib.h>
-
-#include "lisp.h"
-#include "xterm.h"
-#include "frame.h"
-#include "blockinput.h"
-#include "font.h"
-#include "pdumper.h"
-
-/* FTX font driver.  */
-
-struct ftxfont_frame_data
-{
-  /* Background and foreground colors.  */
-  XColor colors[2];
-  /* GCs interpolating the above colors.  gcs[0] is for a color
-   closest to BACKGROUND, and gcs[5] is for a color closest to
-   FOREGROUND.  */
-  GC gcs[6];
-  struct ftxfont_frame_data *next;
-};
-
-
-/* Return an array of 6 GCs for antialiasing.  */
-
-static GC *
-ftxfont_get_gcs (struct frame *f, unsigned long foreground, unsigned long 
background)
-{
-  XColor color;
-  XGCValues xgcv;
-  int i;
-  struct ftxfont_frame_data *data = font_get_frame_data (f, Qftx);
-  struct ftxfont_frame_data *prev = NULL, *this = NULL, *new;
-
-  if (data)
-    {
-      for (this = data; this; prev = this, this = this->next)
-       {
-         if (this->colors[0].pixel < background)
-           continue;
-         if (this->colors[0].pixel > background)
-           break;
-         if (this->colors[1].pixel < foreground)
-           continue;
-         if (this->colors[1].pixel > foreground)
-           break;
-         return this->gcs;
-       }
-    }
-
-  new = xmalloc (sizeof *new);
-  new->next = this;
-  if (prev)
-      prev->next = new;
-  font_put_frame_data (f, Qftx, new);
-
-  new->colors[0].pixel = background;
-  new->colors[1].pixel = foreground;
-
-  block_input ();
-  XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), new->colors, 2);
-  for (i = 1; i < 7; i++)
-    {
-      /* Interpolate colors linearly.  Any better algorithm?  */
-      color.red
-       = (new->colors[1].red * i + new->colors[0].red * (8 - i)) / 8;
-      color.green
-       = (new->colors[1].green * i + new->colors[0].green * (8 - i)) / 8;
-      color.blue
-       = (new->colors[1].blue * i + new->colors[0].blue * (8 - i)) / 8;
-      if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color))
-       break;
-      xgcv.foreground = color.pixel;
-      new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
-                                  GCForeground, &xgcv);
-    }
-  unblock_input ();
-
-  if (i < 7)
-    {
-      block_input ();
-      for (i--; i >= 0; i--)
-       XFreeGC (FRAME_X_DISPLAY (f), new->gcs[i]);
-      unblock_input ();
-      if (prev)
-       prev->next = new->next;
-      else if (data)
-       font_put_frame_data (f, Qftx, new->next);
-      xfree (new);
-      return NULL;
-    }
-  return new->gcs;
-}
-
-static int
-ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font,
-                     unsigned int code, int x, int y, XPoint *p, int size,
-                     int *n, bool flush)
-{
-  struct font_bitmap bitmap;
-  unsigned char *b;
-  int i, j;
-
-  if (ftfont_get_bitmap (font, code, &bitmap, size > 0x100 ? 1 : 8) < 0)
-    return 0;
-  if (size > 0x100)
-    {
-      for (i = 0, b = bitmap.buffer; i < bitmap.rows;
-          i++, b += bitmap.pitch)
-       {
-         for (j = 0; j < bitmap.width; j++)
-           if (b[j / 8] & (1 << (7 - (j % 8))))
-             {
-               p[n[0]].x = x + bitmap.left + j;
-               p[n[0]].y = y - bitmap.top + i;
-               if (++n[0] == size)
-                 {
-                    XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
-                                gc_fore, p, size, CoordModeOrigin);
-                   n[0] = 0;
-                 }
-             }
-       }
-      if (flush && n[0] > 0)
-        XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
-                    gc_fore, p, n[0], CoordModeOrigin);
-    }
-  else
-    {
-      for (i = 0, b = bitmap.buffer; i < bitmap.rows;
-          i++, b += bitmap.pitch)
-       {
-         for (j = 0; j < bitmap.width; j++)
-           {
-             int idx = (bitmap.bits_per_pixel == 1
-                        ? ((b[j / 8] & (1 << (7 - (j % 8)))) ? 6 : -1)
-                        : (b[j] >> 5) - 1);
-
-             if (idx >= 0)
-               {
-                 XPoint *pp = p + size * idx;
-
-                 pp[n[idx]].x = x + bitmap.left + j;
-                 pp[n[idx]].y = y - bitmap.top + i;
-                 if (++(n[idx]) == size)
-                   {
-                      XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
-                                  idx == 6 ? gc_fore : gcs[idx], pp, size,
-                                  CoordModeOrigin);
-                     n[idx] = 0;
-                   }
-               }
-           }
-       }
-      if (flush)
-       {
-         for (i = 0; i < 6; i++)
-           if (n[i] > 0)
-              XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
-                          gcs[i], p + 0x100 * i, n[i], CoordModeOrigin);
-         if (n[6] > 0)
-            XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
-                        gc_fore, p + 0x600, n[6], CoordModeOrigin);
-       }
-    }
-
-  /* There is no ftfont_free_bitmap, so do not try to free BITMAP.  */
-
-  return bitmap.advance;
-}
-
-static void
-ftxfont_draw_background (struct frame *f, struct font *font, GC gc, int x, int 
y,
-                        int width)
-{
-  XGCValues xgcv;
-
-  XGetGCValues (FRAME_X_DISPLAY (f), gc,
-               GCForeground | GCBackground, &xgcv);
-  XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
-  XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), gc,
-                 x, y - FONT_BASE (font), width, FONT_HEIGHT (font));
-  XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
-}
-
-static Lisp_Object
-ftxfont_list (struct frame *f, Lisp_Object spec)
-{
-  return ftfont_list2 (f, spec, Qftx);
-}
-
-static Lisp_Object
-ftxfont_match (struct frame *f, Lisp_Object spec)
-{
-  return ftfont_match2 (f, spec, Qftx);
-}
-
-static Lisp_Object
-ftxfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
-{
-  Lisp_Object font_object = ftfont_open (f, entity, pixel_size);
-  if (NILP (font_object))
-    return Qnil;
-  struct font *font = XFONT_OBJECT (font_object);
-  font->driver = &ftxfont_driver;
-  return font_object;
-}
-
-static void
-ftxfont_close (struct font *font)
-{
-  ftfont_close (font);
-}
-
-static int
-ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y,
-              bool with_background)
-{
-  struct frame *f = s->f;
-  struct face *face = s->face;
-  struct font *font = s->font;
-  XPoint p[0x700];
-  int n[7];
-  unsigned *code = s->char2b + from;
-  int len = to - from;
-  int i;
-  GC *gcs;
-  int xadvance;
-
-  n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = 0;
-
-  block_input ();
-  if (with_background)
-    ftxfont_draw_background (f, font, s->gc, x, y, s->width);
-
-  if (face->gc == s->gc)
-    {
-      gcs = ftxfont_get_gcs (f, face->foreground, face->background);
-    }
-  else
-    {
-      XGCValues xgcv;
-      unsigned long mask = GCForeground | GCBackground;
-
-      XGetGCValues (FRAME_X_DISPLAY (f), s->gc, mask, &xgcv);
-      gcs = ftxfont_get_gcs (f, xgcv.foreground, xgcv.background);
-    }
-
-  if (gcs)
-    {
-      if (s->num_clips)
-       for (i = 0; i < 6; i++)
-         XSetClipRectangles (FRAME_X_DISPLAY (f), gcs[i], 0, 0,
-                             s->clip, s->num_clips, Unsorted);
-
-      for (i = 0; i < len; i++)
-       {
-         xadvance = ftxfont_draw_bitmap (f, s->gc, gcs, font, code[i], x, y,
-                                         p, 0x100, n, i + 1 == len);
-         x += (s->padding_p ? 1 : xadvance);
-       }
-      if (s->num_clips)
-       for (i = 0; i < 6; i++)
-         XSetClipMask (FRAME_X_DISPLAY (f), gcs[i], None);
-    }
-  else
-    {
-      /* We can't draw with antialiasing.
-        s->gc should already have a proper clipping setting. */
-      for (i = 0; i < len; i++)
-       {
-         xadvance = ftxfont_draw_bitmap (f, s->gc, NULL, font, code[i], x, y,
-                                         p, 0x700, n, i + 1 == len);
-         x += (s->padding_p ? 1 : xadvance);
-       }
-    }
-
-  unblock_input ();
-
-  return len;
-}
-
-static int
-ftxfont_end_for_frame (struct frame *f)
-{
-  struct ftxfont_frame_data *data = font_get_frame_data (f, Qftx);
-
-  block_input ();
-  while (data)
-    {
-      struct ftxfont_frame_data *next = data->next;
-      int i;
-
-      for (i = 0; i < 6; i++)
-       XFreeGC (FRAME_X_DISPLAY (f), data->gcs[i]);
-      xfree (data);
-      data = next;
-    }
-  unblock_input ();
-  font_put_frame_data (f, Qftx, NULL);
-  return 0;
-}
-
-
-
-static void syms_of_ftxfont_for_pdumper (void);
-
-struct font_driver const ftxfont_driver =
-  {
-  /* We can't draw a text without device dependent functions.  */
-  .type = LISPSYM_INITIALLY (Qftx),
-  .get_cache = ftfont_get_cache,
-  .list = ftxfont_list,
-  .match = ftxfont_match,
-  .list_family = ftfont_list_family,
-  .open_font = ftxfont_open,
-  .close_font = ftxfont_close,
-  .has_char = ftfont_has_char,
-  .encode_char = ftfont_encode_char,
-  .text_extents = ftfont_text_extents,
-  .draw = ftxfont_draw,
-  .get_bitmap = ftfont_get_bitmap,
-  .anchor_point = ftfont_anchor_point,
-#ifdef HAVE_LIBOTF
-  .otf_capability = ftfont_otf_capability,
-#endif
-  .end_for_frame = ftxfont_end_for_frame,
-#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
-  .shape = ftfont_shape,
-#endif
-#if defined HAVE_OTF_GET_VARIATION_GLYPHS || defined 
HAVE_FT_FACE_GETCHARVARIANTINDEX
-  .get_variation_glyphs = ftfont_variation_glyphs,
-#endif
-  .filter_properties = ftfont_filter_properties,
-  .combining_capability = ftfont_combining_capability,
-  };
-
-void
-syms_of_ftxfont (void)
-{
-  DEFSYM (Qftx, "ftx");
-  pdumper_do_now_and_after_load (syms_of_ftxfont_for_pdumper);
-}
-
-static void
-syms_of_ftxfont_for_pdumper (void)
-{
-  register_font_driver (&ftxfont_driver, NULL);
-}
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 6308c38..5e7cf3d 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -22,6 +22,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #ifdef USE_GTK
 #include <float.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include <c-ctype.h>
 
diff --git a/src/image.c b/src/image.c
index 5fe0d71..65d5925 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1242,6 +1242,10 @@ prepare_image_for_display (struct frame *f, struct image 
*img)
       if (img->cr_data == NULL || (cairo_pattern_get_type (img->cr_data)
                                   != CAIRO_PATTERN_TYPE_SURFACE))
        {
+         /* Fill in the background/background_transparent field while
+            we have img->pixmap->data/img->mask->data.  */
+         IMAGE_BACKGROUND (img, f, img->pixmap);
+         IMAGE_BACKGROUND_TRANSPARENT (img, f, img->mask);
          cr_put_image_to_cr_data (img);
          if (img->cr_data == NULL)
            {
@@ -1616,7 +1620,7 @@ search_image_cache (struct frame *f, Lisp_Object spec, 
EMACS_UINT hash)
 static void
 uncache_image (struct frame *f, Lisp_Object spec)
 {
-  struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
+  struct image *img = search_image_cache (f, spec, sxhash (spec));
   if (img)
     {
       free_image (f, img);
@@ -2281,7 +2285,7 @@ lookup_image (struct frame *f, Lisp_Object spec)
   eassert (valid_image_p (spec));
 
   /* Look up SPEC in the hash table of the image cache.  */
-  hash = sxhash (spec, 0);
+  hash = sxhash (spec);
   img = search_image_cache (f, spec, hash);
   if (img && img->load_failed_p)
     {
@@ -6231,7 +6235,7 @@ pbm_load (struct frame *f, struct image *img)
                                 PNG
  ***********************************************************************/
 
-#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO)
+#if defined (HAVE_PNG) || defined (HAVE_NS)
 
 /* Indices of image specification fields in png_format, below.  */
 
@@ -6282,10 +6286,10 @@ png_image_p (Lisp_Object object)
   return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
 }
 
-#endif /* HAVE_PNG || HAVE_NS || USE_CAIRO */
+#endif /* HAVE_PNG || HAVE_NS */
 
 
-#if (defined HAVE_PNG && !defined HAVE_NS) || defined USE_CAIRO
+#if defined HAVE_PNG && !defined HAVE_NS
 
 # ifdef WINDOWSNT
 /* PNG library details.  */
@@ -10160,7 +10164,7 @@ static struct image_type const image_types[] =
  { SYMBOL_INDEX (Qsvg), svg_image_p, svg_load, image_clear_image,
    IMAGE_TYPE_INIT (init_svg_functions) },
 #endif
-#if defined HAVE_PNG || defined HAVE_NS || defined USE_CAIRO
+#if defined HAVE_PNG || defined HAVE_NS
  { SYMBOL_INDEX (Qpng), png_image_p, png_load, image_clear_image,
    IMAGE_TYPE_INIT (init_png_functions) },
 #endif
diff --git a/src/json.c b/src/json.c
index 2e50ce5..3002767 100644
--- a/src/json.c
+++ b/src/json.c
@@ -1121,7 +1121,6 @@ syms_of_json (void)
 
   DEFSYM (Qstring_without_embedded_nulls_p, "string-without-embedded-nulls-p");
   DEFSYM (Qjson_value_p, "json-value-p");
-  DEFSYM (Qutf_8_string_p, "utf-8-string-p");
 
   DEFSYM (Qjson_error, "json-error");
   DEFSYM (Qjson_out_of_memory, "json-out-of-memory");
diff --git a/src/lisp.h b/src/lisp.h
index 0448995..3ee6187 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1069,7 +1069,7 @@ DEFINE_GDB_SYMBOL_END (PSEUDOVECTOR_FLAG)
    with PVEC_TYPE_MASK to indicate the actual type.  */
 enum pvec_type
 {
-  PVEC_NORMAL_VECTOR,
+  PVEC_NORMAL_VECTOR,  /* Should be first, for sxhash_obj.  */
   PVEC_FREE,
   PVEC_BIGNUM,
   PVEC_MARKER,
@@ -1095,7 +1095,7 @@ enum pvec_type
   PVEC_MODULE_FUNCTION,
   PVEC_NATIVE_COMP_UNIT,
 
-  /* These should be last, check internal_equal to see why.  */
+  /* These should be last, for internal_equal and sxhash_obj.  */
   PVEC_COMPILED,
   PVEC_CHAR_TABLE,
   PVEC_SUB_CHAR_TABLE,
@@ -3663,7 +3663,7 @@ extern bool sweep_weak_table (struct Lisp_Hash_Table *, 
bool);
 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, int);
+EMACS_UINT sxhash (Lisp_Object);
 Lisp_Object hashfn_eql (Lisp_Object, struct Lisp_Hash_Table *);
 Lisp_Object hashfn_equal (Lisp_Object, struct Lisp_Hash_Table *);
 Lisp_Object hashfn_user_defined (Lisp_Object, struct Lisp_Hash_Table *);
@@ -3823,7 +3823,7 @@ extern void parse_str_as_multibyte (const unsigned char 
*, ptrdiff_t,
 /* Defined in alloc.c.  */
 extern void *my_heap_start (void);
 extern void check_pure_size (void);
-extern void allocate_string_data (struct Lisp_String *, EMACS_INT, EMACS_INT);
+unsigned char *resize_string_data (Lisp_Object, ptrdiff_t, int, int);
 extern void malloc_warning (const char *);
 extern AVOID memory_full (size_t);
 extern AVOID buffer_memory_full (ptrdiff_t);
@@ -3953,6 +3953,7 @@ extern Lisp_Object pure_cons (Lisp_Object, Lisp_Object);
 extern Lisp_Object make_vector (ptrdiff_t, Lisp_Object);
 extern void make_byte_code (struct Lisp_Vector *);
 extern struct Lisp_Vector *allocate_vector (ptrdiff_t);
+extern struct Lisp_Vector *allocate_nil_vector (ptrdiff_t);
 
 /* Make an uninitialized vector for SIZE objects.  NOTE: you must
    be sure that GC cannot happen until the vector is completely
@@ -3988,9 +3989,7 @@ make_uninit_sub_char_table (int depth, int min_char)
 INLINE Lisp_Object
 make_nil_vector (ptrdiff_t size)
 {
-  Lisp_Object vec = make_uninit_vector (size);
-  memclear (XVECTOR (vec)->contents, size * word_size);
-  return vec;
+  return make_lisp_ptr (allocate_nil_vector (size), Lisp_Vectorlike);
 }
 
 extern struct Lisp_Vector *allocate_pseudovector (int, int, int,
@@ -4256,6 +4255,8 @@ extern Lisp_Object module_function_documentation
   (struct Lisp_Module_Function const *);
 extern module_funcptr module_function_address
   (struct Lisp_Module_Function const *);
+extern void *module_function_data (const struct Lisp_Module_Function *);
+extern void module_finalize_function (const struct Lisp_Module_Function *);
 extern void mark_modules (void);
 extern void init_module_assertions (bool);
 extern void syms_of_module (void);
@@ -4615,6 +4616,8 @@ extern void seed_random (void *, ptrdiff_t);
 extern void init_random (void);
 extern void emacs_backtrace (int);
 extern AVOID emacs_abort (void) NO_INLINE;
+extern int emacs_fstatat (int, char const *, void *, int);
+extern int emacs_openat (int, char const *, int, int);
 extern int emacs_open (const char *, int, int);
 extern int emacs_pipe (int[2]);
 extern int emacs_close (int);
diff --git a/src/lread.c b/src/lread.c
index d6d1386..2cf7548 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1356,11 +1356,11 @@ Return t if the file exists and loads successfully.  */)
              ignores suffix order due to load_prefer_newer.  */
           if (!load_prefer_newer && is_elc)
             {
-              result = stat (SSDATA (efound), &s1);
+             result = emacs_fstatat (AT_FDCWD, SSDATA (efound), &s1, 0);
               if (result == 0)
                 {
                   SSET (efound, SBYTES (efound) - 1, 0);
-                  result = stat (SSDATA (efound), &s2);
+                 result = emacs_fstatat (AT_FDCWD, SSDATA (efound), &s2, 0);
                   SSET (efound, SBYTES (efound) - 1, 'c');
                 }
 
@@ -5095,7 +5095,7 @@ that are loaded before your customizations are read!  */);
 If nil, `load' and `read' raise errors when encountering some
 old-style variants of backquote and comma.  If non-nil, these
 constructs are always interpreted as described in the Info node
-`(elisp)Backquotes', even if that interpretation is incompatible with
+`(elisp)Backquote', even if that interpretation is incompatible with
 previous versions of Emacs.  Setting this variable to non-nil makes
 Emacs compatible with the behavior planned for Emacs 28.  In Emacs 28,
 this variable will become obsolete.  */);
diff --git a/src/mini-gmp.c b/src/mini-gmp.c
index bf8a616..2e789a2 100644
--- a/src/mini-gmp.c
+++ b/src/mini-gmp.c
@@ -94,11 +94,13 @@ see https://www.gnu.org/licenses/.  */
 
 #define gmp_clz(count, x) do {                                         \
     mp_limb_t __clz_x = (x);                                           \
-    unsigned __clz_c;                                                  \
-    for (__clz_c = 0;                                                  \
-        (__clz_x & ((mp_limb_t) 0xff << (GMP_LIMB_BITS - 8))) == 0;    \
-        __clz_c += 8)                                                  \
-      __clz_x <<= 8;                                                   \
+    unsigned __clz_c = 0;                                              \
+    int LOCAL_SHIFT_BITS = 8;                                          \
+    if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS)                              \
+      for (;                                                           \
+          (__clz_x & ((mp_limb_t) 0xff << (GMP_LIMB_BITS - 8))) == 0;  \
+          __clz_c += 8)                                                \
+       { __clz_x <<= LOCAL_SHIFT_BITS; }                               \
     for (; (__clz_x & GMP_LIMB_HIGHBIT) == 0; __clz_c++)               \
       __clz_x <<= 1;                                                   \
     (count) = __clz_c;                                                 \
@@ -143,27 +145,27 @@ see https://www.gnu.org/licenses/.  */
        w1 = (mp_limb_t) (__ww >> LOCAL_GMP_LIMB_BITS);                 \
       }                                                                        
\
     else {                                                             \
-    mp_limb_t __x0, __x1, __x2, __x3;                                  \
-    unsigned __ul, __vl, __uh, __vh;                                   \
-    mp_limb_t __u = (u), __v = (v);                                    \
+      mp_limb_t __x0, __x1, __x2, __x3;                                        
\
+      unsigned __ul, __vl, __uh, __vh;                                 \
+      mp_limb_t __u = (u), __v = (v);                                  \
                                                                        \
-    __ul = __u & GMP_LLIMB_MASK;                                       \
-    __uh = __u >> (GMP_LIMB_BITS / 2);                                 \
-    __vl = __v & GMP_LLIMB_MASK;                                       \
-    __vh = __v >> (GMP_LIMB_BITS / 2);                                 \
+      __ul = __u & GMP_LLIMB_MASK;                                     \
+      __uh = __u >> (GMP_LIMB_BITS / 2);                               \
+      __vl = __v & GMP_LLIMB_MASK;                                     \
+      __vh = __v >> (GMP_LIMB_BITS / 2);                               \
                                                                        \
-    __x0 = (mp_limb_t) __ul * __vl;                                    \
-    __x1 = (mp_limb_t) __ul * __vh;                                    \
-    __x2 = (mp_limb_t) __uh * __vl;                                    \
-    __x3 = (mp_limb_t) __uh * __vh;                                    \
+      __x0 = (mp_limb_t) __ul * __vl;                                  \
+      __x1 = (mp_limb_t) __ul * __vh;                                  \
+      __x2 = (mp_limb_t) __uh * __vl;                                  \
+      __x3 = (mp_limb_t) __uh * __vh;                                  \
                                                                        \
-    __x1 += __x0 >> (GMP_LIMB_BITS / 2);/* this can't give carry */    \
-    __x1 += __x2;              /* but this indeed can */               \
-    if (__x1 < __x2)           /* did we get it? */                    \
-      __x3 += GMP_HLIMB_BIT;   /* yes, add it in the proper pos. */    \
+      __x1 += __x0 >> (GMP_LIMB_BITS / 2);/* this can't give carry */  \
+      __x1 += __x2;            /* but this indeed can */               \
+      if (__x1 < __x2)         /* did we get it? */                    \
+       __x3 += GMP_HLIMB_BIT;  /* yes, add it in the proper pos. */    \
                                                                        \
-    (w1) = __x3 + (__x1 >> (GMP_LIMB_BITS / 2));                       \
-    (w0) = (__x1 << (GMP_LIMB_BITS / 2)) + (__x0 & GMP_LLIMB_MASK);    \
+      (w1) = __x3 + (__x1 >> (GMP_LIMB_BITS / 2));                     \
+      (w0) = (__x1 << (GMP_LIMB_BITS / 2)) + (__x0 & GMP_LLIMB_MASK);  \
     }                                                                  \
   } while (0)
 
@@ -768,91 +770,81 @@ mpn_neg (mp_ptr rp, mp_srcptr up, mp_size_t n)
 mp_limb_t
 mpn_invert_3by2 (mp_limb_t u1, mp_limb_t u0)
 {
-  int GMP_LIMB_BITS_MUL_3 = GMP_LIMB_BITS * 3;
-  if (sizeof (unsigned) * CHAR_BIT > GMP_LIMB_BITS * 3)
-    {
-      return (((unsigned) 1 << GMP_LIMB_BITS_MUL_3) - 1) /
-       (((unsigned) u1 << GMP_LIMB_BITS_MUL_3 / 3) + u0);
-    }
-  else if (GMP_ULONG_BITS > GMP_LIMB_BITS * 3)
-    {
-      return (((unsigned long) 1 << GMP_LIMB_BITS_MUL_3) - 1) /
-       (((unsigned long) u1 << GMP_LIMB_BITS_MUL_3 / 3) + u0);
-    }
-  else {
-  mp_limb_t r, p, m, ql;
-  unsigned ul, uh, qh;
+  mp_limb_t r, m;
 
-  assert (u1 >= GMP_LIMB_HIGHBIT);
+  {
+    mp_limb_t p, ql;
+    unsigned ul, uh, qh;
 
-  /* For notation, let b denote the half-limb base, so that B = b^2.
-     Split u1 = b uh + ul. */
-  ul = u1 & GMP_LLIMB_MASK;
-  uh = u1 >> (GMP_LIMB_BITS / 2);
+    /* For notation, let b denote the half-limb base, so that B = b^2.
+       Split u1 = b uh + ul. */
+    ul = u1 & GMP_LLIMB_MASK;
+    uh = u1 >> (GMP_LIMB_BITS / 2);
 
-  /* Approximation of the high half of quotient. Differs from the 2/1
-     inverse of the half limb uh, since we have already subtracted
-     u0. */
-  qh = ~u1 / uh;
+    /* Approximation of the high half of quotient. Differs from the 2/1
+       inverse of the half limb uh, since we have already subtracted
+       u0. */
+    qh = (u1 ^ GMP_LIMB_MAX) / uh;
 
-  /* Adjust to get a half-limb 3/2 inverse, i.e., we want
+    /* Adjust to get a half-limb 3/2 inverse, i.e., we want
 
-     qh' = floor( (b^3 - 1) / u) - b = floor ((b^3 - b u - 1) / u
-         = floor( (b (~u) + b-1) / u),
+       qh' = floor( (b^3 - 1) / u) - b = floor ((b^3 - b u - 1) / u
+          = floor( (b (~u) + b-1) / u),
 
-     and the remainder
+       and the remainder
 
-     r = b (~u) + b-1 - qh (b uh + ul)
+       r = b (~u) + b-1 - qh (b uh + ul)
        = b (~u - qh uh) + b-1 - qh ul
 
-     Subtraction of qh ul may underflow, which implies adjustments.
-     But by normalization, 2 u >= B > qh ul, so we need to adjust by
-     at most 2.
-  */
+       Subtraction of qh ul may underflow, which implies adjustments.
+       But by normalization, 2 u >= B > qh ul, so we need to adjust by
+       at most 2.
+    */
 
-  r = ((~u1 - (mp_limb_t) qh * uh) << (GMP_LIMB_BITS / 2)) | GMP_LLIMB_MASK;
+    r = ((~u1 - (mp_limb_t) qh * uh) << (GMP_LIMB_BITS / 2)) | GMP_LLIMB_MASK;
 
-  p = (mp_limb_t) qh * ul;
-  /* Adjustment steps taken from udiv_qrnnd_c */
-  if (r < p)
-    {
-      qh--;
-      r += u1;
-      if (r >= u1) /* i.e. we didn't get carry when adding to r */
-       if (r < p)
-         {
-           qh--;
-           r += u1;
-         }
-    }
-  r -= p;
+    p = (mp_limb_t) qh * ul;
+    /* Adjustment steps taken from udiv_qrnnd_c */
+    if (r < p)
+      {
+       qh--;
+       r += u1;
+       if (r >= u1) /* i.e. we didn't get carry when adding to r */
+         if (r < p)
+           {
+             qh--;
+             r += u1;
+           }
+      }
+    r -= p;
 
-  /* Low half of the quotient is
+    /* Low half of the quotient is
 
        ql = floor ( (b r + b-1) / u1).
 
-     This is a 3/2 division (on half-limbs), for which qh is a
-     suitable inverse. */
+       This is a 3/2 division (on half-limbs), for which qh is a
+       suitable inverse. */
 
-  p = (r >> (GMP_LIMB_BITS / 2)) * qh + r;
-  /* Unlike full-limb 3/2, we can add 1 without overflow. For this to
-     work, it is essential that ql is a full mp_limb_t. */
-  ql = (p >> (GMP_LIMB_BITS / 2)) + 1;
+    p = (r >> (GMP_LIMB_BITS / 2)) * qh + r;
+    /* Unlike full-limb 3/2, we can add 1 without overflow. For this to
+       work, it is essential that ql is a full mp_limb_t. */
+    ql = (p >> (GMP_LIMB_BITS / 2)) + 1;
 
-  /* By the 3/2 trick, we don't need the high half limb. */
-  r = (r << (GMP_LIMB_BITS / 2)) + GMP_LLIMB_MASK - ql * u1;
+    /* By the 3/2 trick, we don't need the high half limb. */
+    r = (r << (GMP_LIMB_BITS / 2)) + GMP_LLIMB_MASK - ql * u1;
 
-  if (r >= (p << (GMP_LIMB_BITS / 2)))
-    {
-      ql--;
-      r += u1;
-    }
-  m = ((mp_limb_t) qh << (GMP_LIMB_BITS / 2)) + ql;
-  if (r >= u1)
-    {
-      m++;
-      r -= u1;
-    }
+    if (r >= (GMP_LIMB_MAX & (p << (GMP_LIMB_BITS / 2))))
+      {
+       ql--;
+       r += u1;
+      }
+    m = ((mp_limb_t) qh << (GMP_LIMB_BITS / 2)) + ql;
+    if (r >= u1)
+      {
+       m++;
+       r -= u1;
+      }
+  }
 
   /* Now m is the 2/1 inverse of u1. If u0 > 0, adjust it to become a
      3/2 inverse. */
@@ -881,7 +873,6 @@ mpn_invert_3by2 (mp_limb_t u1, mp_limb_t u0)
     }
 
   return m;
-  }
 }
 
 struct gmp_div_inverse
@@ -3332,7 +3323,7 @@ mpz_bin_uiui (mpz_t r, unsigned long n, unsigned long k)
   mpz_fac_ui (t, k);
 
   for (; k > 0; --k)
-      mpz_mul_ui (r, r, n--);
+    mpz_mul_ui (r, r, n--);
 
   mpz_divexact (r, r, t);
   mpz_clear (t);
@@ -3990,13 +3981,18 @@ gmp_popcount_limb (mp_limb_t x)
   unsigned c;
 
   /* Do 16 bits at a time, to avoid limb-sized constants. */
-  for (c = 0; x > 0; x >>= 16)
+  int LOCAL_SHIFT_BITS = 16;
+  for (c = 0; x > 0;)
     {
       unsigned w = x - ((x >> 1) & 0x5555);
       w = ((w >> 2) & 0x3333) + (w & 0x3333);
       w =  (w >> 4) + w;
       w = ((w >> 8) & 0x000f) + (w & 0x000f);
       c += w;
+      if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS)
+       x >>= LOCAL_SHIFT_BITS;
+      else
+       x = 0;
     }
   return c;
 }
@@ -4503,10 +4499,15 @@ mpz_export (void *r, size_t *countp, int order, size_t 
size, int endian,
       limb = u->_mp_d[un-1];
       assert (limb != 0);
 
-      k = 0;
-      do {
-       k++; limb >>= CHAR_BIT;
-      } while (limb != 0);
+      k = (GMP_LIMB_BITS <= CHAR_BIT);
+      if (!k)
+       {
+         do {
+           int LOCAL_CHAR_BIT = CHAR_BIT;
+           k++; limb >>= LOCAL_CHAR_BIT;
+         } while (limb != 0);
+       }
+      /* else limb = 0; */
 
       count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size;
 
@@ -4535,17 +4536,28 @@ mpz_export (void *r, size_t *countp, int order, size_t 
size, int endian,
       for (bytes = 0, i = 0, k = 0; k < count; k++, p += word_step)
        {
          size_t j;
-         for (j = 0; j < size; j++, p -= (ptrdiff_t) endian)
+         for (j = 0; j < size; ++j, p -= (ptrdiff_t) endian)
            {
-             if (bytes == 0)
+             if (sizeof (mp_limb_t) == 1)
                {
                  if (i < un)
-                   limb = u->_mp_d[i++];
-                 bytes = sizeof (mp_limb_t);
+                   *p = u->_mp_d[i++];
+                 else
+                   *p = 0;
+               }
+             else
+               {
+                 int LOCAL_CHAR_BIT = CHAR_BIT;
+                 if (bytes == 0)
+                   {
+                     if (i < un)
+                       limb = u->_mp_d[i++];
+                     bytes = sizeof (mp_limb_t);
+                   }
+                 *p = limb;
+                 limb >>= LOCAL_CHAR_BIT;
+                 bytes--;
                }
-             *p = limb;
-             limb >>= CHAR_BIT;
-             bytes--;
            }
        }
       assert (i == un);
diff --git a/src/mini-gmp.h b/src/mini-gmp.h
index 27e0c06..7cce3f7 100644
--- a/src/mini-gmp.h
+++ b/src/mini-gmp.h
@@ -1,6 +1,6 @@
 /* mini-gmp, a minimalistic implementation of a GNU GMP subset.
 
-Copyright 2011-2015, 2017 Free Software Foundation, Inc.
+Copyright 2011-2015, 2017, 2019 Free Software Foundation, Inc.
 
 This file is part of the GNU MP Library.
 
@@ -53,7 +53,11 @@ void mp_get_memory_functions (void *(**) (size_t),
                              void *(**) (void *, size_t, size_t),
                              void (**) (void *, size_t));
 
-typedef unsigned long mp_limb_t;
+#ifndef MINI_GMP_LIMB_TYPE
+#define MINI_GMP_LIMB_TYPE long
+#endif
+
+typedef unsigned MINI_GMP_LIMB_TYPE mp_limb_t;
 typedef long mp_size_t;
 typedef unsigned long mp_bitcnt_t;
 
diff --git a/src/minibuf.c b/src/minibuf.c
index 8ebdff1..9d870ce 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -697,10 +697,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   else
     histstring = Qnil;
 
-  /* If Lisp form desired instead of string, parse it.  */
-  if (expflag)
-    val = string_to_object (val, defalt);
-
   /* The appropriate frame will get selected
      in set-window-configuration.  */
   unbind_to (count, Qnil);
@@ -711,6 +707,10 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   if (! (NILP (Vhistory_add_new_input) || NILP (histstring)))
     call2 (intern ("add-to-history"), histvar, histstring);
 
+  /* If Lisp form desired instead of string, parse it.  */
+  if (expflag)
+    val = string_to_object (val, defalt);
+
   return val;
 }
 
diff --git a/src/module-env-28.h b/src/module-env-28.h
index dec8704..a2479a8 100644
--- a/src/module-env-28.h
+++ b/src/module-env-28.h
@@ -1,3 +1,11 @@
   /* Add module environment functions newly added in Emacs 28 here.
      Before Emacs 28 is released, remove this comment and start
      module-env-29.h on the master branch.  */
+
+  void (*(*EMACS_ATTRIBUTE_NONNULL (1)
+            get_function_finalizer) (emacs_env *env,
+                                     emacs_value arg)) (void *) EMACS_NOEXCEPT;
+
+  void (*set_function_finalizer) (emacs_env *env, emacs_value arg,
+                                  void (*fin) (void *) EMACS_NOEXCEPT)
+    EMACS_ATTRIBUTE_NONNULL (1);
diff --git a/src/nsfns.m b/src/nsfns.m
index 4d47a90..cbde93b 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -287,12 +287,6 @@ ns_set_background_color (struct frame *f, Lisp_Object arg, 
Lisp_Object oldval)
       error ("Unknown color");
     }
 
-  /* Clear the frame; in some instances the NS-internal GC appears not
-     to update, or it does update and cannot clear old text
-     properly.  */
-  if (FRAME_VISIBLE_P (f))
-    ns_clear_frame (f);
-
   [col retain];
   [f->output_data.ns->background_color release];
   f->output_data.ns->background_color = col;
@@ -324,7 +318,10 @@ ns_set_background_color (struct frame *f, Lisp_Object arg, 
Lisp_Object oldval)
         }
 
       if (FRAME_VISIBLE_P (f))
-        SET_FRAME_GARBAGED (f);
+        {
+          SET_FRAME_GARBAGED (f);
+          ns_clear_frame (f);
+        }
     }
   unblock_input ();
 }
@@ -499,11 +496,11 @@ ns_set_represented_filename (struct frame *f)
 #if defined (NS_IMPL_COCOA) && defined (MAC_OS_X_VERSION_10_7)
   /* Work around for Mach port leaks on macOS 10.15 (bug#38618).  */
   NSURL *fileURL = [NSURL fileURLWithPath:fstr isDirectory:NO];
-  BOOL isUbiquitousItem = YES;
+  NSNumber *isUbiquitousItem = @YES;
   [fileURL getResourceValue:(id *)&isUbiquitousItem
                      forKey:NSURLIsUbiquitousItemKey
                       error:nil];
-  if (isUbiquitousItem)
+  if ([isUbiquitousItem boolValue])
     fstr = @"";
 #endif
 
@@ -1277,14 +1274,20 @@ DEFUN ("x-create-frame", Fx_create_frame, 
Sx_create_frame,
 #ifdef NS_IMPL_COCOA
   tem = gui_display_get_arg (dpyinfo, parms, Qns_appearance, NULL, NULL,
                              RES_TYPE_SYMBOL);
-  FRAME_NS_APPEARANCE (f) = EQ (tem, Qdark)
-    ? ns_appearance_vibrant_dark : ns_appearance_aqua;
-  store_frame_param (f, Qns_appearance, tem);
+  if (EQ (tem, Qdark))
+    FRAME_NS_APPEARANCE (f) = ns_appearance_vibrant_dark;
+  else if (EQ (tem, Qlight))
+    FRAME_NS_APPEARANCE (f) = ns_appearance_aqua;
+  else
+    FRAME_NS_APPEARANCE (f) = ns_appearance_system_default;
+  store_frame_param (f, Qns_appearance,
+                     (!NILP (tem) && !EQ (tem, Qunbound)) ? tem : Qnil);
 
   tem = gui_display_get_arg (dpyinfo, parms, Qns_transparent_titlebar,
                              NULL, NULL, RES_TYPE_BOOLEAN);
   FRAME_NS_TRANSPARENT_TITLEBAR (f) = !NILP (tem) && !EQ (tem, Qunbound);
-  store_frame_param (f, Qns_transparent_titlebar, tem);
+  store_frame_param (f, Qns_transparent_titlebar,
+                     FRAME_NS_TRANSPARENT_TITLEBAR (f) ? Qt : Qnil);
 #endif
 
   parent_frame = gui_display_get_arg (dpyinfo, parms, Qparent_frame, NULL, 
NULL,
@@ -1628,7 +1631,7 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only 
directories.  */)
     dirS = [dirS stringByExpandingTildeInPath];
 
   panel = isSave ?
-    (id)[EmacsSavePanel savePanel] : (id)[EmacsOpenPanel openPanel];
+    (id)[NSSavePanel savePanel] : (id)[NSOpenPanel openPanel];
 
   [panel setTitle: promptS];
 
@@ -3083,29 +3086,6 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
   return ret;
 }
 
-@implementation EmacsSavePanel
-- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
-{
-  BOOL ret = handlePanelKeys (self, theEvent);
-  if (! ret)
-    ret = [super performKeyEquivalent:theEvent];
-  return ret;
-}
-@end
-
-
-@implementation EmacsOpenPanel
-- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
-{
-  // NSOpenPanel inherits NSSavePanel, so passing self is OK.
-  BOOL ret = handlePanelKeys (self, theEvent);
-  if (! ret)
-    ret = [super performKeyEquivalent:theEvent];
-  return ret;
-}
-@end
-
-
 @implementation EmacsFileDelegate
 /* --------------------------------------------------------------------------
    Delegate methods for Open/Save panels
@@ -3141,6 +3121,7 @@ syms_of_nsfns (void)
   DEFSYM (Qframe_title_format, "frame-title-format");
   DEFSYM (Qicon_title_format, "icon-title-format");
   DEFSYM (Qdark, "dark");
+  DEFSYM (Qlight, "light");
 
   DEFVAR_LISP ("ns-icon-type-alist", Vns_icon_type_alist,
                doc: /* Alist of elements (REGEXP . IMAGE) for images of icons 
associated to frames.
diff --git a/src/nsterm.h b/src/nsterm.h
index fb9ac1b..980ca53 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -417,6 +417,9 @@ typedef id instancetype;
    int maximized_width, maximized_height;
    NSWindow *nonfs_window;
    BOOL fs_is_native;
+#ifdef NS_IMPL_COCOA
+   NSBitmapImageRep *drawingBuffer;
+#endif
 @public
    struct frame *emacsframe;
    int rows, cols;
@@ -457,7 +460,13 @@ typedef id instancetype;
 #endif
 - (int)fullscreenState;
 
-/* Non-notification versions of NSView methods.  Used for direct calls.  */
+#ifdef NS_IMPL_COCOA
+- (void)focusOnDrawingBuffer;
+#endif
+- (void)copyRect:(NSRect)srcRect to:(NSRect)dstRect;
+- (void)createDrawingBufferWithRect:(NSRect)rect;
+
+/* Non-notification versions of NSView methods. Used for direct calls.  */
 - (void)windowWillEnterFullScreen;
 - (void)windowDidEnterFullScreen;
 - (void)windowWillExitFullScreen;
@@ -471,6 +480,8 @@ typedef id instancetype;
 {
   NSPoint grabOffset;
 }
+
+- (void)setAppearance;
 @end
 
 
@@ -595,22 +606,6 @@ typedef id instancetype;
 @end
 
 
-/* ==========================================================================
-
-   File open/save panels
-   This and next override methods to handle keyboard input in panels.
-
-   ========================================================================== 
*/
-
-@interface EmacsSavePanel : NSSavePanel
-{
-}
-@end
-@interface EmacsOpenPanel : NSOpenPanel
-{
-}
-@end
-
 @interface EmacsFileDelegate : NSObject
 {
 }
diff --git a/src/nsterm.m b/src/nsterm.m
index 2b6be86..9d427b9 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -287,7 +287,10 @@ struct ns_display_info *x_display_list; /* Chain of 
existing displays */
 long context_menu_value = 0;
 
 /* display update */
+static struct frame *ns_updating_frame;
+static NSView *focus_view = NULL;
 static int ns_window_num = 0;
+static BOOL gsaved = NO;
 static BOOL ns_fake_keydown = NO;
 #ifdef NS_IMPL_COCOA
 static BOOL ns_menu_bar_is_hidden = NO;
@@ -1097,13 +1100,12 @@ ns_update_begin (struct frame *f)
    external (RIF) call; whole frame, called before gui_update_window_begin
    -------------------------------------------------------------------------- 
*/
 {
-#ifdef NS_IMPL_COCOA
   EmacsView *view = FRAME_NS_VIEW (f);
-
   NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_begin");
 
   ns_update_auto_hide_menu_bar ();
 
+#ifdef NS_IMPL_COCOA
   if ([view isFullscreen] && [view fsIsNative])
   {
     // Fix reappearing tool bar in fullscreen for Mac OS X 10.7
@@ -1113,6 +1115,13 @@ ns_update_begin (struct frame *f)
       [toolbar setVisible: tbar_visible];
   }
 #endif
+
+  ns_updating_frame = f;
+#ifdef NS_IMPL_COCOA
+  [view focusOnDrawingBuffer];
+#else
+  [view lockFocus];
+#endif
 }
 
 
@@ -1123,57 +1132,124 @@ ns_update_end (struct frame *f)
    external (RIF) call; for whole frame, called after gui_update_window_end
    -------------------------------------------------------------------------- 
*/
 {
+  EmacsView *view = FRAME_NS_VIEW (f);
+
   NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_end");
 
 /*   if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */
   MOUSE_HL_INFO (f)->mouse_face_defer = 0;
-}
 
+#ifdef NS_IMPL_COCOA
+  [NSGraphicsContext setCurrentContext:nil];
+  [view display];
+#else
+  block_input ();
 
-static BOOL
-ns_clip_to_rect (struct frame *f, NSRect *r, int n)
+  [view unlockFocus];
+  [[view window] flushWindow];
+
+  unblock_input ();
+#endif
+  ns_updating_frame = NULL;
+}
+
+static void
+ns_focus (struct frame *f, NSRect *r, int n)
 /* --------------------------------------------------------------------------
-   Clip the drawing area to rectangle r in frame f.  If drawing is not
-   currently possible mark r as dirty and return NO, otherwise return
-   YES.
+   Internal: Focus on given frame.  During small local updates this is used to
+     draw, however during large updates, ns_update_begin and ns_update_end are
+     called to wrap the whole thing, in which case these calls are stubbed out.
+     Except, on GNUstep, we accumulate the rectangle being drawn into, because
+     the back end won't do this automatically, and will just end up flushing
+     the entire window.
    -------------------------------------------------------------------------- 
*/
 {
-  NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_clip_to_rect");
-  if (r)
+  EmacsView *view = FRAME_NS_VIEW (f);
+
+  NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_focus");
+  if (r != NULL)
     {
       NSTRACE_RECT ("r", *r);
+    }
 
-      if ([NSView focusView] == FRAME_NS_VIEW (f))
+  if (f != ns_updating_frame)
+#ifdef NS_IMPL_COCOA
+    [view focusOnDrawingBuffer];
+#else
+    {
+      if (view != focus_view)
         {
-          [[NSGraphicsContext currentContext] saveGraphicsState];
-          if (n == 2)
-            NSRectClipList (r, 2);
-          else
-            NSRectClip (*r);
+          if (focus_view != NULL)
+            {
+              [focus_view unlockFocus];
+              [[focus_view window] flushWindow];
+            }
 
-          return YES;
+          if (view)
+            [view lockFocus];
+          focus_view = view;
         }
+    }
+#endif
+
+  /* clipping */
+  if (r)
+    {
+#ifdef NS_IMPL_COCOA
+      int i;
+      for (i = 0 ; i < n ; i++)
+        [view setNeedsDisplayInRect:r[i]];
+#endif
+
+      [[NSGraphicsContext currentContext] saveGraphicsState];
+      if (n == 2)
+        NSRectClipList (r, 2);
       else
+        NSRectClip (*r);
+      gsaved = YES;
+    }
+}
+
+
+static void
+ns_unfocus (struct frame *f)
+/* --------------------------------------------------------------------------
+     Internal: Remove focus on given frame
+   -------------------------------------------------------------------------- 
*/
+{
+  NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_unfocus");
+
+  if (gsaved)
+    {
+      [[NSGraphicsContext currentContext] restoreGraphicsState];
+      gsaved = NO;
+    }
+
+#ifdef NS_IMPL_GNUSTEP
+  if (f != ns_updating_frame)
+    {
+      if (focus_view != NULL)
         {
-          NSView *view = FRAME_NS_VIEW (f);
-          int i;
-          for (i = 0 ; i < n ; i++)
-            [view setNeedsDisplayInRect:r[i]];
+          [focus_view unlockFocus];
+          [[focus_view window] flushWindow];
+          focus_view = NULL;
         }
     }
-
-  return NO;
+#endif
 }
 
 
 static void
-ns_reset_clipping (struct frame *f)
-/* Internal: Restore the previous graphics state, unsetting any
-   clipping areas.  */
+ns_clip_to_row (struct window *w, struct glyph_row *row,
+               enum glyph_row_area area, BOOL gc)
+/* --------------------------------------------------------------------------
+     Internal (but parallels other terms): Focus drawing on given row
+   -------------------------------------------------------------------------- 
*/
 {
-  NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_reset_clipping");
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  NSRect clip_rect = ns_row_rect (w, row, area);
 
-  [[NSGraphicsContext currentContext] restoreGraphicsState];
+  ns_focus (f, &clip_rect, 1);
 }
 
 
@@ -1644,6 +1720,7 @@ ns_free_frame_resources (struct frame *f)
   [view release];
 
   xfree (f->output_data.ns);
+  f->output_data.ns = NULL;
 
   unblock_input ();
 }
@@ -2025,17 +2102,13 @@ ns_set_appearance (struct frame *f, Lisp_Object 
new_value, Lisp_Object old_value
     return;
 
   if (EQ (new_value, Qdark))
-    {
-      window.appearance = [NSAppearance
-                            appearanceNamed: NSAppearanceNameVibrantDark];
-      FRAME_NS_APPEARANCE (f) = ns_appearance_vibrant_dark;
-    }
+    FRAME_NS_APPEARANCE (f) = ns_appearance_vibrant_dark;
+  else if (EQ (new_value, Qlight))
+    FRAME_NS_APPEARANCE (f) = ns_appearance_aqua;
   else
-    {
-      window.appearance = [NSAppearance
-                            appearanceNamed: NSAppearanceNameAqua];
-      FRAME_NS_APPEARANCE (f) = ns_appearance_aqua;
-    }
+    FRAME_NS_APPEARANCE (f) = ns_appearance_system_default;
+
+  [window setAppearance];
 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 */
 }
 
@@ -2773,16 +2846,14 @@ ns_clear_frame (struct frame *f)
   r = [view bounds];
 
   block_input ();
-  if (ns_clip_to_rect (f, &r, 1))
-    {
-      [ns_lookup_indexed_color (NS_FACE_BACKGROUND
-                                (FACE_FROM_ID (f, DEFAULT_FACE_ID)), f) set];
-      NSRectFill (r);
-      ns_reset_clipping (f);
-
-      /* as of 2006/11 or so this is now needed */
-      ns_redraw_scroll_bars (f);
-    }
+  ns_focus (f, &r, 1);
+  [ns_lookup_indexed_color (NS_FACE_BACKGROUND
+                           (FACE_FROM_ID (f, DEFAULT_FACE_ID)), f) set];
+  NSRectFill (r);
+  ns_unfocus (f);
+
+  /* as of 2006/11 or so this is now needed */
+  ns_redraw_scroll_bars (f);
   unblock_input ();
 }
 
@@ -2803,46 +2874,15 @@ ns_clear_frame_area (struct frame *f, int x, int y, int 
width, int height)
   NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_clear_frame_area");
 
   r = NSIntersectionRect (r, [view frame]);
-  if (ns_clip_to_rect (f, &r, 1))
-    {
-      [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
+  ns_focus (f, &r, 1);
+  [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
 
-      NSRectFill (r);
+  NSRectFill (r);
 
-      ns_reset_clipping (f);
-    }
+  ns_unfocus (f);
+  return;
 }
 
-static void
-ns_copy_bits (struct frame *f, NSRect src, NSRect dest)
-{
-  NSSize delta = NSMakeSize (dest.origin.x - src.origin.x,
-                             dest.origin.y - src.origin.y);
-  NSTRACE ("ns_copy_bits");
-
-  if (FRAME_NS_VIEW (f))
-    {
-      hide_bell();              // Ensure the bell image isn't scrolled.
-
-      /* FIXME: scrollRect:by: is deprecated in macOS 10.14.  There is
-         no obvious replacement so we may have to come up with our own.  */
-      [FRAME_NS_VIEW (f) scrollRect: src by: delta];
-
-#ifdef NS_IMPL_COCOA
-      /* As far as I can tell from the documentation, scrollRect:by:,
-         above, should copy the dirty rectangles from our source
-         rectangle to our destination, however it appears it clips the
-         operation to src.  As a result we need to use
-         translateRectsNeedingDisplayInRect:by: below, and we have to
-         union src and dest so it can pick up the dirty rectangles,
-         and place them, as it also clips to the rectangle.
-
-         FIXME: We need a GNUstep equivalent.  */
-      [FRAME_NS_VIEW (f) translateRectsNeedingDisplayInRect:NSUnionRect (src, 
dest)
-                                                         by:delta];
-#endif
-    }
-}
 
 static void
 ns_scroll_run (struct window *w, struct run *run)
@@ -2895,8 +2935,12 @@ ns_scroll_run (struct window *w, struct run *run)
   {
     NSRect srcRect = NSMakeRect (x, from_y, width, height);
     NSRect dstRect = NSMakeRect (x, to_y, width, height);
+    EmacsView *view = FRAME_NS_VIEW (f);
 
-    ns_copy_bits (f, srcRect , dstRect);
+    [view copyRect:srcRect to:dstRect];
+#ifdef NS_IMPL_COCOA
+    [view setNeedsDisplayInRect:srcRect];
+#endif
   }
 
   unblock_input ();
@@ -2950,20 +2994,12 @@ ns_shift_glyphs_for_insert (struct frame *f,
     External (RIF): copy an area horizontally, don't worry about clearing src
    -------------------------------------------------------------------------- 
*/
 {
-  //NSRect srcRect = NSMakeRect (x, y, width, height);
+  NSRect srcRect = NSMakeRect (x, y, width, height);
   NSRect dstRect = NSMakeRect (x+shift_by, y, width, height);
 
   NSTRACE ("ns_shift_glyphs_for_insert");
 
-  /* This doesn't work now as we copy the "bits" before we've had a
-     chance to actually draw any changes to the screen.  This means in
-     certain circumstances we end up with copies of the cursor all
-     over the place.  Just mark the area dirty so it is redrawn later.
-
-     FIXME: Work out how to do this properly.  */
-  // ns_copy_bits (f, srcRect, dstRect);
-
-  [FRAME_NS_VIEW (f) setNeedsDisplayInRect:dstRect];
+  [FRAME_NS_VIEW (f) copyRect:srcRect to:dstRect];
 }
 
 
@@ -3083,66 +3119,76 @@ ns_draw_fringe_bitmap (struct window *w, struct 
glyph_row *row,
 
   /* The visible portion of imageRect will always be contained within
      clearRect.  */
-  if (ns_clip_to_rect (f, &clearRect, 1))
+  ns_focus (f, &clearRect, 1);
+  if (! NSIsEmptyRect (clearRect))
     {
-      if (! NSIsEmptyRect (clearRect))
-        {
-          NSTRACE_RECT ("clearRect", clearRect);
+      NSTRACE_RECT ("clearRect", clearRect);
 
-          [ns_lookup_indexed_color(face->background, f) set];
-          NSRectFill (clearRect);
-        }
+      [ns_lookup_indexed_color(face->background, f) set];
+      NSRectFill (clearRect);
+    }
 
-      if (p->which)
+  if (p->which)
+    {
+      EmacsImage *img = bimgs[p->which - 1];
+
+      if (!img)
         {
-          EmacsImage *img = bimgs[p->which - 1];
+          // Note: For "periodic" images, allocate one EmacsImage for
+          // the base image, and use it for all dh:s.
+          unsigned short *bits = p->bits;
+          int full_height = p->h + p->dh;
+          int i;
+          unsigned char *cbits = xmalloc (full_height);
+
+          for (i = 0; i < full_height; i++)
+            cbits[i] = bits[i];
+          img = [[EmacsImage alloc] initFromXBM: cbits width: 8
+                                         height: full_height
+                                             fg: 0 bg: 0
+                                   reverseBytes: NO];
+          bimgs[p->which - 1] = img;
+          xfree (cbits);
+        }
 
-          if (!img)
-            {
-              // Note: For "periodic" images, allocate one EmacsImage for
-              // the base image, and use it for all dh:s.
-              unsigned short *bits = p->bits;
-              int full_height = p->h + p->dh;
-              int i;
-              unsigned char *cbits = xmalloc (full_height);
-
-              for (i = 0; i < full_height; i++)
-                cbits[i] = bits[i];
-              img = [[EmacsImage alloc] initFromXBM: cbits width: 8
-                                             height: full_height
-                                                 fg: 0 bg: 0
-                                       reverseBytes: NO];
-              bimgs[p->which - 1] = img;
-              xfree (cbits);
-            }
 
+      {
+        NSColor *bm_color;
+        if (!p->cursor_p)
+          bm_color = ns_lookup_indexed_color(face->foreground, f);
+        else if (p->overlay_p)
+          bm_color = ns_lookup_indexed_color(face->background, f);
+        else
+          bm_color = f->output_data.ns->cursor_color;
+        [img setXBMColor: bm_color];
+      }
 
-          {
-            NSColor *bm_color;
-            if (!p->cursor_p)
-              bm_color = ns_lookup_indexed_color(face->foreground, f);
-            else if (p->overlay_p)
-              bm_color = ns_lookup_indexed_color(face->background, f);
-            else
-              bm_color = f->output_data.ns->cursor_color;
-            [img setXBMColor: bm_color];
-          }
+      // Note: For periodic images, the full image height is "h + hd".
+      // By using the height h, a suitable part of the image is used.
+      NSRect fromRect = NSMakeRect(0, 0, p->wd, p->h);
 
-          // Note: For periodic images, the full image height is "h + hd".
-          // By using the height h, a suitable part of the image is used.
-          NSRect fromRect = NSMakeRect(0, 0, p->wd, p->h);
+      NSTRACE_RECT ("fromRect", fromRect);
 
-          NSTRACE_RECT ("fromRect", fromRect);
+      /* Because we're drawing into an offscreen buffer which isn't
+         flipped, the images come out upside down.  To work around it
+         we need to do some fancy transforms.  */
+      {
+        NSAffineTransform *transform = [NSAffineTransform transform];
+        [transform translateXBy:0 yBy:NSMaxY(imageRect)];
+        [transform scaleXBy:1 yBy:-1];
+        [transform concat];
 
-          [img drawInRect: imageRect
-                 fromRect: fromRect
-                operation: NSCompositingOperationSourceOver
-                 fraction: 1.0
-               respectFlipped: YES
-                    hints: nil];
-        }
-      ns_reset_clipping (f);
+        imageRect.origin.y = 0;
+      }
+
+      [img drawInRect: imageRect
+             fromRect: fromRect
+            operation: NSCompositingOperationSourceOver
+             fraction: 1.0
+           respectFlipped: YES
+                hints: nil];
     }
+  ns_unfocus (f);
 }
 
 
@@ -3227,60 +3273,52 @@ ns_draw_window_cursor (struct window *w, struct 
glyph_row *glyph_row,
   /* Prevent the cursor from being drawn outside the text area.  */
   r = NSIntersectionRect (r, ns_row_rect (w, glyph_row, TEXT_AREA));
 
-  if (ns_clip_to_rect (f, &r, 1))
+  face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id);
+  if (face && NS_FACE_BACKGROUND (face)
+      == ns_index_color (FRAME_CURSOR_COLOR (f), f))
     {
-      face = FACE_FROM_ID_OR_NULL (f, phys_cursor_glyph->face_id);
-      if (face && NS_FACE_BACKGROUND (face)
-          == ns_index_color (FRAME_CURSOR_COLOR (f), f))
-        {
-          [ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), f) set];
-          hollow_color = FRAME_CURSOR_COLOR (f);
-        }
-      else
-        [FRAME_CURSOR_COLOR (f) set];
-
-      switch (cursor_type)
-        {
-        case DEFAULT_CURSOR:
-        case NO_CURSOR:
-          break;
-        case FILLED_BOX_CURSOR:
-          NSRectFill (r);
-          break;
-        case HOLLOW_BOX_CURSOR:
-          NSRectFill (r);
-          [hollow_color set];
-          NSRectFill (NSInsetRect (r, 1, 1));
-          [FRAME_CURSOR_COLOR (f) set];
-          break;
-        case HBAR_CURSOR:
-          NSRectFill (r);
-          break;
-        case BAR_CURSOR:
-          s = r;
-          /* If the character under cursor is R2L, draw the bar cursor
-             on the right of its glyph, rather than on the left.  */
-          cursor_glyph = get_phys_cursor_glyph (w);
-          if ((cursor_glyph->resolved_level & 1) != 0)
-            s.origin.x += cursor_glyph->pixel_width - s.size.width;
-
-          NSRectFill (s);
-          break;
-        }
+      [ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), f) set];
+      hollow_color = FRAME_CURSOR_COLOR (f);
+    }
+  else
+    [FRAME_CURSOR_COLOR (f) set];
 
-      /* Draw the character under the cursor.  Other terms only draw
-         the character on top of box cursors, so do the same here.  */
-      if (cursor_type == FILLED_BOX_CURSOR || cursor_type == HOLLOW_BOX_CURSOR)
-        draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+  ns_focus (f, &r, 1);
 
-      ns_reset_clipping (f);
-    }
-  else if (! redisplaying_p)
+  switch (cursor_type)
     {
-      /* If this function is called outside redisplay, it probably
-         means we need an immediate update.  */
-      [FRAME_NS_VIEW (f) display];
+    case DEFAULT_CURSOR:
+    case NO_CURSOR:
+      break;
+    case FILLED_BOX_CURSOR:
+      NSRectFill (r);
+      break;
+    case HOLLOW_BOX_CURSOR:
+      NSRectFill (r);
+      [hollow_color set];
+      NSRectFill (NSInsetRect (r, 1, 1));
+      [FRAME_CURSOR_COLOR (f) set];
+      break;
+    case HBAR_CURSOR:
+      NSRectFill (r);
+      break;
+    case BAR_CURSOR:
+      s = r;
+      /* If the character under cursor is R2L, draw the bar cursor
+         on the right of its glyph, rather than on the left.  */
+      cursor_glyph = get_phys_cursor_glyph (w);
+      if ((cursor_glyph->resolved_level & 1) != 0)
+        s.origin.x += cursor_glyph->pixel_width - s.size.width;
+
+      NSRectFill (s);
+      break;
     }
+  ns_unfocus (f);
+
+  /* Draw the character under the cursor.  Other terms only draw
+     the character on top of box cursors, so do the same here.  */
+  if (cursor_type == FILLED_BOX_CURSOR || cursor_type == HOLLOW_BOX_CURSOR)
+    draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
 }
 
 
@@ -3298,14 +3336,12 @@ ns_draw_vertical_window_border (struct window *w, int 
x, int y0, int y1)
 
   face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
 
-  if (ns_clip_to_rect (f, &r, 1))
-    {
-      if (face)
-        [ns_lookup_indexed_color(face->foreground, f) set];
+  ns_focus (f, &r, 1);
+  if (face)
+    [ns_lookup_indexed_color(face->foreground, f) set];
 
-      NSRectFill(r);
-      ns_reset_clipping (f);
-    }
+  NSRectFill(r);
+  ns_unfocus (f);
 }
 
 
@@ -3332,42 +3368,42 @@ ns_draw_window_divider (struct window *w, int x0, int 
x1, int y0, int y1)
 
   NSTRACE ("ns_draw_window_divider");
 
-  if (ns_clip_to_rect (f, &divider, 1))
-    {
-      if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
-        /* A vertical divider, at least three pixels wide: Draw first and
-           last pixels differently.  */
-        {
-          [ns_lookup_indexed_color(color_first, f) set];
-          NSRectFill(NSMakeRect (x0, y0, 1, y1 - y0));
-          [ns_lookup_indexed_color(color, f) set];
-          NSRectFill(NSMakeRect (x0 + 1, y0, x1 - x0 - 2, y1 - y0));
-          [ns_lookup_indexed_color(color_last, f) set];
-          NSRectFill(NSMakeRect (x1 - 1, y0, 1, y1 - y0));
-        }
-      else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
-        /* A horizontal divider, at least three pixels high: Draw first and
-           last pixels differently.  */
-        {
-          [ns_lookup_indexed_color(color_first, f) set];
-          NSRectFill(NSMakeRect (x0, y0, x1 - x0, 1));
-          [ns_lookup_indexed_color(color, f) set];
-          NSRectFill(NSMakeRect (x0, y0 + 1, x1 - x0, y1 - y0 - 2));
-          [ns_lookup_indexed_color(color_last, f) set];
-          NSRectFill(NSMakeRect (x0, y1 - 1, x1 - x0, 1));
-        }
-      else
-        {
-          /* In any other case do not draw the first and last pixels
-             differently.  */
-          [ns_lookup_indexed_color(color, f) set];
-          NSRectFill(divider);
-        }
+  ns_focus (f, &divider, 1);
 
-      ns_reset_clipping (f);
+  if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
+    /* A vertical divider, at least three pixels wide: Draw first and
+       last pixels differently.  */
+    {
+      [ns_lookup_indexed_color(color_first, f) set];
+      NSRectFill(NSMakeRect (x0, y0, 1, y1 - y0));
+      [ns_lookup_indexed_color(color, f) set];
+      NSRectFill(NSMakeRect (x0 + 1, y0, x1 - x0 - 2, y1 - y0));
+      [ns_lookup_indexed_color(color_last, f) set];
+      NSRectFill(NSMakeRect (x1 - 1, y0, 1, y1 - y0));
+    }
+  else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
+    /* A horizontal divider, at least three pixels high: Draw first and
+       last pixels differently.  */
+    {
+      [ns_lookup_indexed_color(color_first, f) set];
+      NSRectFill(NSMakeRect (x0, y0, x1 - x0, 1));
+      [ns_lookup_indexed_color(color, f) set];
+      NSRectFill(NSMakeRect (x0, y0 + 1, x1 - x0, y1 - y0 - 2));
+      [ns_lookup_indexed_color(color_last, f) set];
+      NSRectFill(NSMakeRect (x0, y1 - 1, x1 - x0, 1));
     }
+  else
+    {
+      /* In any other case do not draw the first and last pixels
+         differently.  */
+      [ns_lookup_indexed_color(color, f) set];
+      NSRectFill(divider);
+    }
+
+  ns_unfocus (f);
 }
 
+
 static void
 ns_show_hourglass (struct frame *f)
 {
@@ -3891,15 +3927,27 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
 
       [[NSGraphicsContext currentContext] saveGraphicsState];
 
-      /* Because of the transforms it's far too difficult to work out
-         what portion of the original, untransformed, image will be
-         drawn, so the clipping area will ensure we draw only the
-         correct bit.  */
+      /* Because of the transforms it's difficult to work out what
+         portion of the original, untransformed, image will be drawn,
+         so the clipping area will ensure we draw only the correct
+         bit.  */
       NSRectClip (dr);
 
       [setOrigin translateXBy:x - s->slice.x yBy:y - s->slice.y];
       [setOrigin concat];
-      [img->transform concat];
+
+      NSAffineTransform *doTransform = [NSAffineTransform transform];
+
+      /* We have to flip the image around the X axis as the offscreen
+         bitmap we're drawing to is flipped.  */
+      [doTransform scaleXBy:1 yBy:-1];
+      [doTransform translateXBy:0 yBy:-[img size].height];
+
+      /* ImageMagick images don't have transforms.  */
+      if (img->transform)
+        [doTransform appendTransform:img->transform];
+
+      [doTransform concat];
 
       [img drawInRect:ir fromRect:ir
             operation:NSCompositingOperationSourceOver
@@ -3972,6 +4020,7 @@ static void
 ns_dumpglyphs_stretch (struct glyph_string *s)
 {
   NSRect r[2];
+  NSRect glyphRect;
   int n, i;
   struct face *face;
   NSColor *fgCol, *bgCol;
@@ -3979,82 +4028,57 @@ ns_dumpglyphs_stretch (struct glyph_string *s)
   if (!s->background_filled_p)
     {
       n = ns_get_glyph_string_clip_rect (s, r);
+      ns_focus (s->f, r, n);
 
-      if (ns_clip_to_rect (s->f, r, n))
+      if (s->hl == DRAW_MOUSE_FACE)
         {
-          /* FIXME: Why are we reusing the clipping rectangles? The
-             other terms don't appear to do anything like this.  */
-          *r = NSMakeRect (s->x, s->y, s->background_width, s->height);
+          face = FACE_FROM_ID_OR_NULL (s->f,
+                                       MOUSE_HL_INFO 
(s->f)->mouse_face_face_id);
+          if (!face)
+            face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
+        }
+      else
+        face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
 
-          if (s->hl == DRAW_MOUSE_FACE)
-            {
-              face = FACE_FROM_ID_OR_NULL (s->f,
-                                           MOUSE_HL_INFO 
(s->f)->mouse_face_face_id);
-              if (!face)
-                face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
-            }
-          else
-            face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
+      bgCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
+      fgCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
 
-          bgCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f);
-          fgCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f);
+      glyphRect = NSMakeRect (s->x, s->y, s->background_width, s->height);
 
-          for (i = 0; i < n; ++i)
-            {
-              if (!s->row->full_width_p)
-                {
-                  int overrun, leftoverrun;
-
-                  /* truncate to avoid overwriting fringe and/or scrollbar */
-                  overrun = max (0, (s->x + s->background_width)
-                                 - (WINDOW_BOX_RIGHT_EDGE_X (s->w)
-                                    - WINDOW_RIGHT_FRINGE_WIDTH (s->w)));
-                  r[i].size.width -= overrun;
-
-                  /* truncate to avoid overwriting to left of the window box */
-                  leftoverrun = (WINDOW_BOX_LEFT_EDGE_X (s->w)
-                                 + WINDOW_LEFT_FRINGE_WIDTH (s->w)) - s->x;
-
-                    if (leftoverrun > 0)
-                      {
-                        r[i].origin.x += leftoverrun;
-                        r[i].size.width -= leftoverrun;
-                      }
-                }
+      [bgCol set];
 
-              [bgCol set];
+      /* NOTE: under NS this is NOT used to draw cursors, but we must avoid
+         overwriting cursor (usually when cursor on a tab) */
+      if (s->hl == DRAW_CURSOR)
+        {
+          CGFloat x, width;
 
-              /* NOTE: under NS this is NOT used to draw cursors, but we must 
avoid
-                 overwriting cursor (usually when cursor on a tab).  */
-              if (s->hl == DRAW_CURSOR)
-                {
-                  CGFloat x, width;
+          /* FIXME: This looks like it will only work for left to
+             right languages.  */
+          x = NSMinX (glyphRect);
+          width = s->w->phys_cursor_width;
+          glyphRect.size.width -= width;
+          glyphRect.origin.x += width;
 
-                  x = r[i].origin.x;
-                  width = s->w->phys_cursor_width;
-                  r[i].size.width -= width;
-                  r[i].origin.x += width;
+          NSRectFill (glyphRect);
 
-                  NSRectFill (r[i]);
+          /* Draw overlining, etc. on the cursor. */
+          if (s->w->phys_cursor_type == FILLED_BOX_CURSOR)
+            ns_draw_text_decoration (s, face, bgCol, width, x);
+          else
+            ns_draw_text_decoration (s, face, fgCol, width, x);
+        }
+      else
+        {
+          NSRectFill (glyphRect);
+        }
 
-                  /* Draw overlining, etc. on the cursor.  */
-                  if (s->w->phys_cursor_type == FILLED_BOX_CURSOR)
-                    ns_draw_text_decoration (s, face, bgCol, width, x);
-                  else
-                    ns_draw_text_decoration (s, face, fgCol, width, x);
-                }
-              else
-                {
-                  NSRectFill (r[i]);
-                }
+      /* Draw overlining, etc. on the stretch glyph (or the part
+         of the stretch glyph after the cursor). */
+      ns_draw_text_decoration (s, face, fgCol, NSWidth (glyphRect),
+                               NSMinX (glyphRect));
 
-              /* Draw overlining, etc. on the stretch glyph (or the part
-                 of the stretch glyph after the cursor).  */
-              ns_draw_text_decoration (s, face, fgCol, r[i].size.width,
-                                       r[i].origin.x);
-            }
-          ns_reset_clipping (s->f);
-        }
+      ns_unfocus (s->f);
       s->background_filled_p = 1;
     }
 }
@@ -4204,11 +4228,9 @@ ns_draw_glyph_string (struct glyph_string *s)
             if (next->first_glyph->type != STRETCH_GLYPH)
               {
                 n = ns_get_glyph_string_clip_rect (s->next, r);
-                if (ns_clip_to_rect (s->f, r, n))
-                  {
-                    ns_maybe_dumpglyphs_background (s->next, 1);
-                    ns_reset_clipping (s->f);
-                  }
+                ns_focus (s->f, r, n);
+                ns_maybe_dumpglyphs_background (s->next, 1);
+                ns_unfocus (s->f);
               }
             else
               {
@@ -4223,12 +4245,10 @@ ns_draw_glyph_string (struct glyph_string *s)
            || s->first_glyph->type == COMPOSITE_GLYPH))
     {
       n = ns_get_glyph_string_clip_rect (s, r);
-      if (ns_clip_to_rect (s->f, r, n))
-        {
-          ns_maybe_dumpglyphs_background (s, 1);
-          ns_dumpglyphs_box_or_relief (s);
-          ns_reset_clipping (s->f);
-        }
+      ns_focus (s->f, r, n);
+      ns_maybe_dumpglyphs_background (s, 1);
+      ns_dumpglyphs_box_or_relief (s);
+      ns_unfocus (s->f);
       box_drawn_p = 1;
     }
 
@@ -4237,11 +4257,9 @@ ns_draw_glyph_string (struct glyph_string *s)
 
     case IMAGE_GLYPH:
       n = ns_get_glyph_string_clip_rect (s, r);
-      if (ns_clip_to_rect (s->f, r, n))
-        {
-          ns_dumpglyphs_image (s, r[0]);
-          ns_reset_clipping (s->f);
-        }
+      ns_focus (s->f, r, n);
+      ns_dumpglyphs_image (s, r[0]);
+      ns_unfocus (s->f);
       break;
 
     case STRETCH_GLYPH:
@@ -4251,68 +4269,66 @@ ns_draw_glyph_string (struct glyph_string *s)
     case CHAR_GLYPH:
     case COMPOSITE_GLYPH:
       n = ns_get_glyph_string_clip_rect (s, r);
-      if (ns_clip_to_rect (s->f, r, n))
-        {
-          if (s->for_overlaps || (s->cmp_from > 0
-                                  && ! s->first_glyph->u.cmp.automatic))
-            s->background_filled_p = 1;
-          else
-            ns_maybe_dumpglyphs_background
-              (s, s->first_glyph->type == COMPOSITE_GLYPH);
+      ns_focus (s->f, r, n);
 
-          if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == 
FILLED_BOX_CURSOR)
-            {
-              unsigned long tmp = NS_FACE_BACKGROUND (s->face);
-              NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
-              NS_FACE_FOREGROUND (s->face) = tmp;
-            }
+      if (s->for_overlaps || (s->cmp_from > 0
+                             && ! s->first_glyph->u.cmp.automatic))
+        s->background_filled_p = 1;
+      else
+        ns_maybe_dumpglyphs_background
+          (s, s->first_glyph->type == COMPOSITE_GLYPH);
 
-          {
-            BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH;
+      if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
+        {
+          unsigned long tmp = NS_FACE_BACKGROUND (s->face);
+          NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
+          NS_FACE_FOREGROUND (s->face) = tmp;
+        }
 
-            if (isComposite)
-              ns_draw_composite_glyph_string_foreground (s);
-            else
-              ns_draw_glyph_string_foreground (s);
-          }
+      {
+        BOOL isComposite = s->first_glyph->type == COMPOSITE_GLYPH;
 
-          {
-            NSColor *col = (NS_FACE_FOREGROUND (s->face) != 0
-                            ? ns_lookup_indexed_color (NS_FACE_FOREGROUND 
(s->face),
-                                                       s->f)
-                            : FRAME_FOREGROUND_COLOR (s->f));
-            [col set];
-
-            /* Draw underline, overline, strike-through.  */
-            ns_draw_text_decoration (s, s->face, col, s->width, s->x);
-          }
+        if (isComposite)
+          ns_draw_composite_glyph_string_foreground (s);
+        else
+          ns_draw_glyph_string_foreground (s);
+      }
 
-          if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == 
FILLED_BOX_CURSOR)
-            {
-              unsigned long tmp = NS_FACE_BACKGROUND (s->face);
-              NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
-              NS_FACE_FOREGROUND (s->face) = tmp;
-            }
+      {
+        NSColor *col = (NS_FACE_FOREGROUND (s->face) != 0
+                        ? ns_lookup_indexed_color (NS_FACE_FOREGROUND 
(s->face),
+                                                   s->f)
+                        : FRAME_FOREGROUND_COLOR (s->f));
+        [col set];
+
+        /* Draw underline, overline, strike-through. */
+        ns_draw_text_decoration (s, s->face, col, s->width, s->x);
+      }
 
-          ns_reset_clipping (s->f);
+      if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
+        {
+          unsigned long tmp = NS_FACE_BACKGROUND (s->face);
+          NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face);
+          NS_FACE_FOREGROUND (s->face) = tmp;
         }
+
+      ns_unfocus (s->f);
       break;
 
     case GLYPHLESS_GLYPH:
       n = ns_get_glyph_string_clip_rect (s, r);
-      if (ns_clip_to_rect (s->f, r, n))
-        {
-          if (s->for_overlaps || (s->cmp_from > 0
-                                  && ! s->first_glyph->u.cmp.automatic))
-            s->background_filled_p = 1;
-          else
-            ns_maybe_dumpglyphs_background
-              (s, s->first_glyph->type == COMPOSITE_GLYPH);
-          /* ... */
-          /* Not yet implemented.  */
-          /* ... */
-          ns_reset_clipping (s->f);
-        }
+      ns_focus (s->f, r, n);
+
+      if (s->for_overlaps || (s->cmp_from > 0
+                             && ! s->first_glyph->u.cmp.automatic))
+        s->background_filled_p = 1;
+      else
+        ns_maybe_dumpglyphs_background
+          (s, s->first_glyph->type == COMPOSITE_GLYPH);
+      /* ... */
+      /* Not yet implemented.  */
+      /* ... */
+      ns_unfocus (s->f);
       break;
 
     default:
@@ -4323,11 +4339,9 @@ ns_draw_glyph_string (struct glyph_string *s)
   if (!s->for_overlaps && !box_drawn_p && s->face->box != FACE_NO_BOX)
     {
       n = ns_get_glyph_string_clip_rect (s, r);
-      if (ns_clip_to_rect (s->f, r, n))
-        {
-          ns_dumpglyphs_box_or_relief (s);
-          ns_reset_clipping (s->f);
-        }
+      ns_focus (s->f, r, n);
+      ns_dumpglyphs_box_or_relief (s);
+      ns_unfocus (s->f);
     }
 
   s->num_clips = 0;
@@ -7090,6 +7104,7 @@ not_in_argv (NSString *arg)
          from non-native fullscreen, in other circumstances it appears
          to be a noop.  (bug#28872) */
       wr = NSMakeRect (0, 0, neww, newh);
+      [self createDrawingBufferWithRect:wr];
       [view setFrame: wr];
 
       // To do: consider using [NSNotificationCenter postNotificationName:].
@@ -7172,6 +7187,7 @@ not_in_argv (NSString *arg)
         size_title = xmalloc (strlen (old_title) + 40);
        esprintf (size_title, "%s  —  (%d x %d)", old_title, cols, rows);
         [window setTitle: [NSString stringWithUTF8String: size_title]];
+        [window display];
         xfree (size_title);
       }
   }
@@ -7428,6 +7444,8 @@ not_in_argv (NSString *arg)
   maximizing_resize = NO;
 #endif
 
+  [self createDrawingBufferWithRect:r];
+
   win = [[EmacsWindow alloc]
             initWithContentRect: r
                       styleMask: (FRAME_UNDECORATED (f)
@@ -7469,16 +7487,8 @@ not_in_argv (NSString *arg)
   if (! FRAME_UNDECORATED (f))
     [self createToolbar: f];
 
-#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
-#ifndef NSAppKitVersionNumber10_10
-#define NSAppKitVersionNumber10_10 1343
-#endif
 
-  if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_10
-      && FRAME_NS_APPEARANCE (f) != ns_appearance_aqua)
-    win.appearance = [NSAppearance
-                          appearanceNamed: NSAppearanceNameVibrantDark];
-#endif
+  [win setAppearance];
 
 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
   if ([win respondsToSelector: @selector(titlebarAppearsTransparent)])
@@ -8219,55 +8229,105 @@ not_in_argv (NSString *arg)
 }
 
 
-- (void)viewWillDraw
+- (void)createDrawingBufferWithRect:(NSRect)rect
+  /* Create and store a new NSBitmapImageRep for Emacs to draw
+     into.
+
+     Drawing to an offscreen bitmap doesn't work in GNUstep as there's
+     a bug in graphicsContextWithBitmapImageRep
+     (https://savannah.gnu.org/bugs/?38405).  So under GNUstep we
+     retain the old method of drawing direct to the EmacsView.  */
 {
-  /* If the frame has been garbaged there's no point in redrawing
-     anything.  */
-  if (FRAME_GARBAGED_P (emacsframe))
-    [self setNeedsDisplay:NO];
+#ifdef NS_IMPL_COCOA
+  if (drawingBuffer != nil)
+    [drawingBuffer release];
+
+  drawingBuffer = [[self bitmapImageRepForCachingDisplayInRect:rect] retain];
+#endif
 }
 
-- (void)drawRect: (NSRect)rect
+
+#ifdef NS_IMPL_COCOA
+- (void)focusOnDrawingBuffer
 {
-  const NSRect *rectList;
-  NSInteger numRects;
+  /* Creating the graphics context each time is very slow, but it
+     doesn't seem possible to cache and reuse it.  */
+  [NSGraphicsContext
+    setCurrentContext:
+      [NSGraphicsContext graphicsContextWithBitmapImageRep:drawingBuffer]];
+}
 
-  NSTRACE ("[EmacsView drawRect:" NSTRACE_FMT_RECT "]",
-           NSTRACE_ARG_RECT(rect));
 
-  if (!emacsframe || !emacsframe->output_data.ns)
-    return;
+- (void)windowDidChangeBackingProperties:(NSNotification *)notification
+  /* Update the drawing buffer when the backing scale factor changes.  */
+{
+   CGFloat old = [[[notification userInfo]
+                    objectForKey:@"NSBackingPropertyOldScaleFactorKey"]
+                   doubleValue];
+   CGFloat new = [[self window] backingScaleFactor];
 
-  block_input ();
+   if (old != new)
+     {
+       NSRect frame = [self frame];
+       [self createDrawingBufferWithRect:frame];
+       ns_clear_frame (emacsframe);
+       expose_frame (emacsframe, 0, 0, NSWidth (frame), NSHeight (frame));
+     }
+}
+#endif
 
-  /* Get only the precise dirty rectangles to avoid redrawing
-     potentially large areas of the frame that haven't changed.
 
-     I'm not sure this actually provides much of a performance benefit
-     as it's hard to benchmark, but it certainly doesn't seem to
-     hurt.  */
-  [self getRectsBeingDrawn:&rectList count:&numRects];
-  for (int i = 0 ; i < numRects ; i++)
-    {
-      NSRect r = rectList[i];
+- (void)copyRect:(NSRect)srcRect to:(NSRect)dstRect
+{
+  NSTRACE ("[EmacsView copyRect:To:]");
+  NSTRACE_RECT ("Source", srcRect);
+  NSTRACE_RECT ("Destination", dstRect);
 
-      NSTRACE_RECT ("r", r);
+#ifdef NS_IMPL_COCOA
+  [drawingBuffer drawInRect:dstRect
+                   fromRect:srcRect
+                  operation:NSCompositingOperationCopy
+                   fraction:1.0
+             respectFlipped:NO
+                      hints:nil];
+
+  [self setNeedsDisplayInRect:dstRect];
+#else
+  hide_bell();              // Ensure the bell image isn't scrolled.
 
-      expose_frame (emacsframe,
-                    NSMinX (r), NSMinY (r),
-                    NSWidth (r), NSHeight (r));
-    }
+  ns_focus (emacsframe, &dstRect, 1);
+  [self scrollRect: srcRect
+                by: NSMakeSize (dstRect.origin.x - srcRect.origin.x,
+                                dstRect.origin.y - srcRect.origin.y)];
+  ns_unfocus (emacsframe);
+#endif
+}
 
-  unblock_input ();
 
-  /*
-    drawRect: may be called (at least in Mac OS X 10.5) for invisible
-    views as well for some reason.  Thus, do not infer visibility
-    here.
+- (void)drawRect: (NSRect)rect
+{
+  NSTRACE ("[EmacsView drawRect:" NSTRACE_FMT_RECT "]",
+           NSTRACE_ARG_RECT(rect));
+
+  if (!emacsframe || !emacsframe->output_data.ns)
+    return;
 
-    emacsframe->async_visible = 1;
-    emacsframe->async_iconified = 0;
-  */
+#ifdef NS_IMPL_COCOA
+  [drawingBuffer drawInRect:rect
+                   fromRect:rect
+                  operation:NSCompositingOperationSourceOver
+                   fraction:1
+             respectFlipped:NO
+                      hints:nil];
+#else
+  int x = NSMinX (rect), y = NSMinY (rect);
+  int width = NSWidth (rect), height = NSHeight (rect);
+
+  ns_clear_frame_area (emacsframe, x, y, width, height);
+  block_input ();
+  expose_frame (emacsframe, x, y, width, height);
+  unblock_input ();
+#endif
 }
 
 
@@ -8728,6 +8788,32 @@ not_in_argv (NSString *arg)
 #endif
 }
 
+- (void)setAppearance
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
+  struct frame *f = ((EmacsView *)[self delegate])->emacsframe;
+  NSAppearance *appearance = nil;
+
+  NSTRACE ("[EmacsWindow setAppearance]");
+
+#ifndef NSAppKitVersionNumber10_10
+#define NSAppKitVersionNumber10_10 1343
+#endif
+
+  if (NSAppKitVersionNumber < NSAppKitVersionNumber10_10)
+    return;
+
+  if (FRAME_NS_APPEARANCE (f) == ns_appearance_vibrant_dark)
+    appearance =
+      [NSAppearance appearanceNamed:NSAppearanceNameVibrantDark];
+  else if (FRAME_NS_APPEARANCE (f) == ns_appearance_aqua)
+    appearance =
+      [NSAppearance appearanceNamed:NSAppearanceNameAqua];
+
+  [self setAppearance:appearance];
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 */
+}
+
 - (void)setFrame:(NSRect)windowFrame
          display:(BOOL)displayViews
 {
diff --git a/src/pdumper.c b/src/pdumper.c
index ae8fe01..14f03f4 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -3025,7 +3025,7 @@ dump_vectorlike (struct dump_context *ctx,
                  Lisp_Object lv,
                  dump_off offset)
 {
-#if CHECK_STRUCTS && !defined HASH_pvec_type_E55BD36F8E
+#if CHECK_STRUCTS && !defined HASH_pvec_type_A4A6E9984D
 # error "pvec_type changed. See CHECK_STRUCTS comment in config.h."
 #endif
   const struct Lisp_Vector *v = XVECTOR (lv);
diff --git a/src/print.c b/src/print.c
index 9013ccc..ce8dd62 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1365,6 +1365,22 @@ data_from_funcptr (void (*funcptr) (void))
      interchangeably, so it's OK to assume that here too.  */
   return (void const *) funcptr;
 }
+
+/* Print the value of the pointer PTR.  */
+
+static void
+print_pointer (Lisp_Object printcharfun, char *buf, const char *prefix,
+               const void *ptr)
+{
+  uintptr_t ui = (uintptr_t) ptr;
+
+  /* In theory this assignment could lose info on pre-C99 hosts, but
+     in practice it doesn't.  */
+  uintmax_t up = ui;
+
+  int len = sprintf (buf, "%s 0x%" PRIxMAX, prefix, up);
+  strout (buf, len, len, printcharfun);
+}
 #endif
 
 static bool
@@ -1796,26 +1812,22 @@ print_vectorlike (Lisp_Object obj, Lisp_Object 
printcharfun, bool escapeflag,
     case PVEC_MODULE_FUNCTION:
       {
        print_c_string ("#<module function ", printcharfun);
-        module_funcptr ptr = module_function_address (XMODULE_FUNCTION (obj));
+        const struct Lisp_Module_Function *function = XMODULE_FUNCTION (obj);
+        module_funcptr ptr = module_function_address (function);
        char const *file;
        char const *symbol;
        dynlib_addr (ptr, &file, &symbol);
 
        if (symbol == NULL)
-         {
-           uintptr_t ui = (uintptr_t) data_from_funcptr (ptr);
-
-           /* In theory this assignment could lose info on pre-C99
-              hosts, but in practice it doesn't.  */
-           uintmax_t up = ui;
-
-           int len = sprintf (buf, "at 0x%"PRIxMAX, up);
-           strout (buf, len, len, printcharfun);
-         }
-       else
+          print_pointer (printcharfun, buf, "at", data_from_funcptr (ptr));
+        else
          print_c_string (symbol, printcharfun);
 
-       if (file != NULL)
+        void *data = module_function_data (function);
+        if (data != NULL)
+          print_pointer (printcharfun, buf, " with data", data);
+
+        if (file != NULL)
          {
            print_c_string (" from ", printcharfun);
            print_c_string (file, printcharfun);
@@ -1846,7 +1858,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, 
bool escapeflag)
 {
   char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT),
                max (sizeof " . #" + INT_STRLEN_BOUND (intmax_t),
-                    max ((sizeof "at 0x"
+                    max ((sizeof " with data 0x"
                           + (sizeof (uintmax_t) * CHAR_BIT + 4 - 1) / 4),
                          40)))];
   current_thread->stack_top = buf;
diff --git a/src/sysdep.c b/src/sysdep.c
index c6344d8..e8e8bbf 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -312,8 +312,8 @@ get_current_dir_name_or_unreachable (void)
   if (pwd
       && (pwdlen = strnlen (pwd, bufsize_max)) < bufsize_max
       && IS_DIRECTORY_SEP (pwd[pwdlen && IS_DEVICE_SEP (pwd[1]) ? 2 : 0])
-      && stat (pwd, &pwdstat) == 0
-      && stat (".", &dotstat) == 0
+      && emacs_fstatat (AT_FDCWD, pwd, &pwdstat, 0) == 0
+      && emacs_fstatat (AT_FDCWD, ".", &dotstat, 0) == 0
       && dotstat.st_ino == pwdstat.st_ino
       && dotstat.st_dev == pwdstat.st_dev)
     {
@@ -2449,7 +2449,27 @@ emacs_abort (void)
 }
 #endif
 
-/* Open FILE for Emacs use, using open flags OFLAG and mode MODE.
+/* Assuming the directory DIRFD, store information about FILENAME into *ST,
+   using FLAGS to control how the status is obtained.
+   Do not fail merely because fetching info was interrupted by a signal.
+   Allow the user to quit.
+
+   The type of ST is void * instead of struct stat * because the
+   latter type would be problematic in lisp.h.  Some platforms may
+   play tricks like "#define stat stat64" in <sys/stat.h>, and lisp.h
+   does not include <sys/stat.h>.  */
+
+int
+emacs_fstatat (int dirfd, char const *filename, void *st, int flags)
+{
+  int r;
+  while ((r = fstatat (dirfd, filename, st, flags)) != 0 && errno == EINTR)
+    maybe_quit ();
+  return r;
+}
+
+/* Assuming the directory DIRFD, open FILE for Emacs use,
+   using open flags OFLAGS and mode MODE.
    Use binary I/O on systems that care about text vs binary I/O.
    Arrange for subprograms to not inherit the file descriptor.
    Prefer a method that is multithread-safe, if available.
@@ -2457,17 +2477,23 @@ emacs_abort (void)
    Allow the user to quit.  */
 
 int
-emacs_open (const char *file, int oflags, int mode)
+emacs_openat (int dirfd, char const *file, int oflags, int mode)
 {
   int fd;
   if (! (oflags & O_TEXT))
     oflags |= O_BINARY;
   oflags |= O_CLOEXEC;
-  while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR)
+  while ((fd = openat (dirfd, file, oflags, mode)) < 0 && errno == EINTR)
     maybe_quit ();
   return fd;
 }
 
+int
+emacs_open (char const *file, int oflags, int mode)
+{
+  return emacs_openat (AT_FDCWD, file, oflags, mode);
+}
+
 /* Open FILE as a stream for Emacs use, with mode MODE.
    Act like emacs_open with respect to threads, signals, and quits.  */
 
diff --git a/src/systhread.c b/src/systhread.c
index c3e4e6a..c649ae8 100644
--- a/src/systhread.c
+++ b/src/systhread.c
@@ -81,10 +81,13 @@ sys_thread_equal (sys_thread_t t, sys_thread_t u)
 {
   return t == u;
 }
+void
+sys_thread_set_name (const char *name)
+{
+}
 
 bool
-sys_thread_create (sys_thread_t *t, const char *name,
-                  thread_creation_function *func, void *datum)
+sys_thread_create (sys_thread_t *t, thread_creation_function *func, void 
*datum)
 {
   return false;
 }
@@ -98,10 +101,6 @@ sys_thread_yield (void)
 
 #include <sched.h>
 
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#endif
-
 void
 sys_mutex_init (sys_mutex_t *mutex)
 {
@@ -204,9 +203,28 @@ sys_thread_equal (sys_thread_t t, sys_thread_t u)
   return pthread_equal (t, u);
 }
 
+void
+sys_thread_set_name (const char *name)
+{
+#ifdef HAVE_PTHREAD_SETNAME_NP
+  /* We need to truncate here otherwise pthread_setname_np
+     fails to set the name.  TASK_COMM_LEN is what the length
+     is called in the Linux kernel headers (Bug#38632).  */
+#define TASK_COMM_LEN 16
+  char p_name[TASK_COMM_LEN];
+  strncpy (p_name, name, TASK_COMM_LEN - 1);
+  p_name[TASK_COMM_LEN - 1] = '\0';
+ #ifdef HAVE_PTHREAD_SETNAME_NP_1ARG
+  pthread_setname_np (p_name);
+ #else
+  pthread_setname_np (pthread_self (), p_name);
+ #endif
+#endif
+}
+
 bool
-sys_thread_create (sys_thread_t *thread_ptr, const char *name,
-                  thread_creation_function *func, void *arg)
+sys_thread_create (sys_thread_t *thread_ptr, thread_creation_function *func,
+                   void *arg)
 {
   pthread_attr_t attr;
   bool result = false;
@@ -225,13 +243,7 @@ sys_thread_create (sys_thread_t *thread_ptr, const char 
*name,
     }
 
   if (!pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED))
-    {
-      result = pthread_create (thread_ptr, &attr, func, arg) == 0;
-#if defined (HAVE_SYS_PRCTL_H) && defined (HAVE_PRCTL) && defined (PR_SET_NAME)
-      if (result && name != NULL)
-       prctl (PR_SET_NAME, name);
-#endif
-    }
+    result = pthread_create (thread_ptr, &attr, func, arg) == 0;
 
  out: ;
   int error = pthread_attr_destroy (&attr);
@@ -452,26 +464,24 @@ w32_set_thread_name (DWORD thread_id, const char *name)
 
 static thread_creation_function *thread_start_address;
 
+void
+sys_thread_set_name (const char *name)
+{
+  w32_set_thread_name (GetCurrentThreadId (), name);
+}
+
 /* _beginthread wants a void function, while we are passed a function
    that returns a pointer.  So we use a wrapper.  See the command in
    w32term.h about the need for ALIGN_STACK attribute.  */
 static void ALIGN_STACK
 w32_beginthread_wrapper (void *arg)
 {
-  /* FIXME: This isn't very clean: systhread.c is not supposed to know
-     that ARG is a pointer to a thread_state object, or be familiar
-     with thread_state object's structure in general.  */
-  struct thread_state *this_thread = arg;
-
-  if (this_thread->thread_name)
-    w32_set_thread_name (GetCurrentThreadId (), this_thread->thread_name);
-
   (void)thread_start_address (arg);
 }
 
 bool
-sys_thread_create (sys_thread_t *thread_ptr, const char *name,
-                  thread_creation_function *func, void *arg)
+sys_thread_create (sys_thread_t *thread_ptr, thread_creation_function *func,
+                   void *arg)
 {
   /* FIXME: Do threads that run Lisp require some minimum amount of
      stack?  Zero here means each thread will get the same amount as
diff --git a/src/systhread.h b/src/systhread.h
index 5368acf..005388f 100644
--- a/src/systhread.h
+++ b/src/systhread.h
@@ -112,10 +112,11 @@ extern sys_thread_t sys_thread_self (void)
 extern bool sys_thread_equal (sys_thread_t, sys_thread_t)
   ATTRIBUTE_WARN_UNUSED_RESULT;
 
-extern bool sys_thread_create (sys_thread_t *, const char *,
-                               thread_creation_function *, void *)
+extern bool sys_thread_create (sys_thread_t *, thread_creation_function *,
+                               void *)
   ATTRIBUTE_WARN_UNUSED_RESULT;
 
 extern void sys_thread_yield (void);
+extern void sys_thread_set_name (const char *);
 
 #endif /* SYSTHREAD_H */
diff --git a/src/term.c b/src/term.c
index 8717343..a3aef31 100644
--- a/src/term.c
+++ b/src/term.c
@@ -2568,6 +2568,14 @@ handle_one_term_event (struct tty_display_info *tty, 
Gpm_Event *event,
   else {
     f->mouse_moved = 0;
     term_mouse_click (&ie, event, f);
+    if (tty_handle_tab_bar_click (f, event->x, event->y,
+                                 (ie.modifiers & down_modifier) != 0, &ie))
+      {
+       /* tty_handle_tab_bar_click stores 2 events in the event
+          queue, so we are done here.  */
+       count += 2;
+       return count;
+      }
   }
 
  done:
diff --git a/src/thread.c b/src/thread.c
index f811634..df1a705 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -725,6 +725,9 @@ run_thread (void *state)
   self->m_stack_bottom = self->stack_top = (char *) &stack_pos;
   self->thread_id = sys_thread_self ();
 
+  if (self->thread_name)
+    sys_thread_set_name (self->thread_name);
+
   acquire_global_lock (self);
 
   /* Put a dummy catcher at top-level so that handlerlist is never NULL.
@@ -826,13 +829,13 @@ If NAME is given, it must be a string; it names the new 
thread.  */)
   new_thread->next_thread = all_threads;
   all_threads = new_thread;
 
-  char const *c_name = !NILP (name) ? SSDATA (ENCODE_UTF_8 (name)) : NULL;
+  char const *c_name = !NILP (name) ? SSDATA (ENCODE_SYSTEM (name)) : NULL;
   if (c_name)
     new_thread->thread_name = xstrdup (c_name);
   else
     new_thread->thread_name = NULL;
   sys_thread_t thr;
-  if (! sys_thread_create (&thr, c_name, run_thread, new_thread))
+  if (! sys_thread_create (&thr, run_thread, new_thread))
     {
       /* Restore the previous situation.  */
       all_threads = all_threads->next_thread;
@@ -1111,9 +1114,6 @@ syms_of_threads (void)
       staticpro (&last_thread_error);
       last_thread_error = Qnil;
 
-      Fdefalias (intern_c_string ("thread-alive-p"),
-                intern_c_string ("thread-live-p"), Qnil);
-
       Fprovide (intern_c_string ("threads"), Qnil);
     }
 
diff --git a/src/thread.h b/src/thread.h
index e96a063..a09929f 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -169,8 +169,7 @@ struct thread_state
      interrupter should broadcast to this condition.  */
   sys_cond_t *wait_condvar;
 
-  /* Thread's name in the locale encoding.  Actually used only on
-     WINDOWSNT.  */
+  /* Thread's name in the locale encoding.  */
   char *thread_name;
 
   /* This thread might have released the global lock.  If so, this is
diff --git a/src/w32.c b/src/w32.c
index 62c53fd..a3b9a56 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -4592,6 +4592,27 @@ sys_open (const char * path, int oflag, int mode)
 }
 
 int
+openat (int fd, const char * path, int oflag, int mode)
+{
+  /* Rely on a hack: an open directory is modeled as file descriptor 0,
+     as in fstatat.  FIXME: Add proper support for openat.  */
+  char fullname[MAX_UTF8_PATH];
+
+  if (fd != AT_FDCWD)
+    {
+      if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, path)
+         < 0)
+       {
+         errno = ENAMETOOLONG;
+         return -1;
+       }
+      path = fullname;
+    }
+
+  return sys_open (path, oflag, mode);
+}
+
+int
 fchmod (int fd, mode_t mode)
 {
   return 0;
diff --git a/src/w32.h b/src/w32.h
index b8655ec..f301b38 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -221,6 +221,7 @@ extern void register_child (pid_t, int);
 
 extern void sys_sleep (int);
 extern int sys_link (const char *, const char *);
+extern int openat (int, const char *, int, int);
 
 /* Return total and free memory info.  */
 extern int w32_memory_info (unsigned long long *, unsigned long long *,
diff --git a/src/w32fns.c b/src/w32fns.c
index 75e0d53..61e22e5 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -2146,6 +2146,9 @@ w32_set_undecorated (struct frame *f, Lisp_Object 
new_value, Lisp_Object old_val
                    | SWP_FRAMECHANGED);
       FRAME_UNDECORATED (f) = false;
     }
+
+  f->output_data.w32->dwStyle = GetWindowLong (hwnd, GWL_STYLE);
+
   unblock_input ();
 }
 
diff --git a/src/w32heap.c b/src/w32heap.c
index 3a6c780..ececc73 100644
--- a/src/w32heap.c
+++ b/src/w32heap.c
@@ -597,6 +597,16 @@ free_after_dump_9x (void *ptr)
     }
 }
 
+void *
+sys_calloc (size_t number, size_t size)
+{
+  size_t nbytes = number * size;
+  void *ptr = (*the_malloc_fn) (nbytes);
+  if (ptr)
+    memset (ptr, 0, nbytes);
+  return ptr;
+}
+
 #if defined HAVE_UNEXEC && defined ENABLE_CHECKING
 void
 report_temacs_memory_usage (void)
diff --git a/src/w32term.c b/src/w32term.c
index c38e740..4eb5045 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -560,7 +560,8 @@ static void
 w32_update_window_begin (struct window *w)
 {
   /* Hide the system caret during an update.  */
-  if (w32_use_visible_system_caret && w32_system_caret_hwnd)
+  if (w32_use_visible_system_caret && w32_system_caret_hwnd
+      && w == w32_system_caret_window)
     {
       SendMessageTimeout (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0,
                          0, 6000, NULL);
@@ -657,7 +658,8 @@ w32_update_window_end (struct window *w, bool cursor_on_p,
   /* Unhide the caret.  This won't actually show the cursor, unless it
      was visible before the corresponding call to HideCaret in
      w32_update_window_begin.  */
-  if (w32_use_visible_system_caret && w32_system_caret_hwnd)
+  if (w32_use_visible_system_caret && w32_system_caret_hwnd
+      && w == w32_system_caret_window)
     {
       SendMessageTimeout (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0,
                          0, 6000, NULL);
diff --git a/src/w32term.h b/src/w32term.h
index 5a54f54..737764b 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -371,6 +371,10 @@ struct w32_output
   /* Non-hourglass cursor that is currently active.  */
   HCURSOR current_cursor;
 
+  /* The window style for this frame.  Set up when the frame is
+     created and updated when adding/removing decorations in
+     w32_set_undecorated.  Used by w32_set_window_size to adjust the
+     frame's window rectangle.  */
   DWORD dwStyle;
 
   /* This is the Emacs structure for the display this frame is on.  */
diff --git a/src/window.c b/src/window.c
index ff17cd8..8cdad27 100644
--- a/src/window.c
+++ b/src/window.c
@@ -7976,19 +7976,17 @@ foreach_window_1 (struct window *w, bool (*fn) (struct 
window *, void *),
 /* Return true if window configurations CONFIGURATION1 and CONFIGURATION2
    describe the same state of affairs.  This is used by Fequal.
 
-   IGNORE_POSITIONS means ignore non-matching scroll positions
-   and the like.
+   Ignore non-matching scroll positions and the like.
 
    This ignores a couple of things like the dedication status of
    window, combination_limit and the like.  This might have to be
    fixed.  */
 
-bool
+static bool
 compare_window_configurations (Lisp_Object configuration1,
-                              Lisp_Object configuration2,
-                              bool ignore_positions)
+                              Lisp_Object configuration2)
 {
-  register struct save_window_data *d1, *d2;
+  struct save_window_data *d1, *d2;
   struct Lisp_Vector *sws1, *sws2;
   ptrdiff_t i;
 
@@ -8006,9 +8004,6 @@ compare_window_configurations (Lisp_Object configuration1,
       || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
       || !EQ (d1->selected_frame, d2->selected_frame)
       || !EQ (d1->f_current_buffer, d2->f_current_buffer)
-      || (!ignore_positions
-         && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
-             || !EQ (d1->minibuf_selected_window, 
d2->minibuf_selected_window)))
       || !EQ (d1->focus_frame, d2->focus_frame)
       /* Verify that the two configurations have the same number of windows.  
*/
       || sws1->header.size != sws2->header.size)
@@ -8041,12 +8036,6 @@ compare_window_configurations (Lisp_Object 
configuration1,
             equality.  */
          || !EQ (sw1->parent, sw2->parent)
          || !EQ (sw1->prev, sw2->prev)
-         || (!ignore_positions
-             && (!EQ (sw1->hscroll, sw2->hscroll)
-                 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
-                 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
-                 || NILP (Fequal (sw1->start, sw2->start))
-                 || NILP (Fequal (sw1->pointm, sw2->pointm))))
          || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
          || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
          || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
@@ -8071,7 +8060,7 @@ This function ignores details such as the values of point
 and scrolling positions.  */)
   (Lisp_Object x, Lisp_Object y)
 {
-  if (compare_window_configurations (x, y, true))
+  if (compare_window_configurations (x, y))
     return Qt;
   return Qnil;
 }
diff --git a/src/window.h b/src/window.h
index aa8d2c8..167d1be 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1184,7 +1184,6 @@ extern Lisp_Object window_list (void);
 extern Lisp_Object window_parameter (struct window *, Lisp_Object parameter);
 extern struct window *decode_live_window (Lisp_Object);
 extern struct window *decode_any_window (Lisp_Object);
-extern bool compare_window_configurations (Lisp_Object, Lisp_Object, bool);
 extern void mark_window_cursors_off (struct window *);
 extern bool window_wants_mode_line (struct window *);
 extern bool window_wants_header_line (struct window *);
diff --git a/src/xdisp.c b/src/xdisp.c
index 6b677b6..68a504f 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -1093,44 +1093,60 @@ window_box_height (struct window *w)
 
   /* Note: the code below that determines the mode-line/header-line/tab-line
      height is essentially the same as that contained in the macro
-     CURRENT_{MODE,HEADER}_LINE_HEIGHT, except that it checks whether
-     the appropriate glyph row has its `mode_line_p' flag set,
-     and if it doesn't, uses estimate_mode_line_height instead.  */
+     CURRENT_{MODE,HEADER,TAB}_LINE_HEIGHT, except that it checks whether
+     the appropriate glyph row has its `mode_line_p' flag set, and if
+     it doesn't, uses estimate_mode_line_height instead.  */
 
   if (window_wants_mode_line (w))
     {
-      struct glyph_row *ml_row
-       = (w->current_matrix && w->current_matrix->rows
-          ? MATRIX_MODE_LINE_ROW (w->current_matrix)
-          : 0);
-      if (ml_row && ml_row->mode_line_p)
-       height -= ml_row->height;
+      if (w->mode_line_height >= 0)
+       height -= w->mode_line_height;
       else
-       height -= estimate_mode_line_height (f, CURRENT_MODE_LINE_FACE_ID (w));
+       {
+         struct glyph_row *ml_row
+           = (w->current_matrix && w->current_matrix->rows
+              ? MATRIX_MODE_LINE_ROW (w->current_matrix)
+              : 0);
+         if (ml_row && ml_row->mode_line_p)
+           height -= ml_row->height;
+         else
+           height -= estimate_mode_line_height (f,
+                                                CURRENT_MODE_LINE_FACE_ID (w));
+       }
     }
 
   if (window_wants_tab_line (w))
     {
-      struct glyph_row *tl_row
-       = (w->current_matrix && w->current_matrix->rows
-          ? MATRIX_TAB_LINE_ROW (w->current_matrix)
-          : 0);
-      if (tl_row && tl_row->mode_line_p)
-       height -= tl_row->height;
+      if (w->tab_line_height >= 0)
+       height -= w->tab_line_height;
       else
-       height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
+       {
+         struct glyph_row *tl_row
+           = (w->current_matrix && w->current_matrix->rows
+              ? MATRIX_TAB_LINE_ROW (w->current_matrix)
+              : 0);
+         if (tl_row && tl_row->mode_line_p)
+           height -= tl_row->height;
+         else
+           height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
+       }
     }
 
   if (window_wants_header_line (w))
     {
-      struct glyph_row *hl_row
-       = (w->current_matrix && w->current_matrix->rows
-          ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
-          : 0);
-      if (hl_row && hl_row->mode_line_p)
-       height -= hl_row->height;
+      if (w->header_line_height >= 0)
+       height -= w->header_line_height;
       else
-       height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
+       {
+         struct glyph_row *hl_row
+           = (w->current_matrix && w->current_matrix->rows
+              ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
+              : 0);
+         if (hl_row && hl_row->mode_line_p)
+           height -= hl_row->height;
+         else
+           height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
+       }
     }
 
   /* With a very small font and a mode-line that's taller than
@@ -8557,7 +8573,7 @@ compute_stop_pos_backwards (struct it *it)
    position before that.  This is called when we bump into a stop
    position while reordering bidirectional text.  CHARPOS should be
    the last previously processed stop_pos (or BEGV/0, if none were
-   processed yet) whose position is less that IT's current
+   processed yet) whose position is less than IT's current
    position.  */
 
 static void
@@ -13500,6 +13516,10 @@ tty_handle_tab_bar_click (struct frame *f, int x, int 
y, bool down_p,
     f->last_tab_bar_item = prop_idx;
   else
     {
+      /* Force reset of up_modifier bit from the event modifiers.  */
+      if (event->modifiers & up_modifier)
+        event->modifiers &= ~up_modifier;
+
       /* Generate a TAB_BAR_EVENT event.  */
       Lisp_Object frame;
       Lisp_Object key = AREF (f->tab_bar_items,
@@ -16228,8 +16248,8 @@ set_cursor_from_row (struct window *w, struct glyph_row 
*row,
   bool string_from_text_prop = false;
 
   /* Don't even try doing anything if called for a mode-line or
-     header-line row, since the rest of the code isn't prepared to
-     deal with such calamities.  */
+     header-line or tab-line row, since the rest of the code isn't
+     prepared to deal with such calamities.  */
   eassert (!row->mode_line_p);
   if (row->mode_line_p)
     return false;
@@ -17488,6 +17508,9 @@ try_cursor_movement (Lisp_Object window, struct 
text_pos startp,
       else
        {
          row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
+         /* Skip the tab-line and header-line rows, if any.  */
+         if (row->tab_line_p)
+           ++row;
          if (row->mode_line_p)
            ++row;
          if (!row->enabled_p)
@@ -17560,6 +17583,9 @@ try_cursor_movement (Lisp_Object window, struct 
text_pos startp,
                  || row->mode_line_p)
                {
                  row = w->current_matrix->rows;
+                 /* Skip the tab-line and header-line rows, if any.  */
+                 if (row->tab_line_p)
+                   ++row;
                  if (row->mode_line_p)
                    ++row;
                }
@@ -17624,8 +17650,9 @@ try_cursor_movement (Lisp_Object window, struct 
text_pos startp,
            ;
          else if (rc != CURSOR_MOVEMENT_SUCCESS
              && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
-             /* Make sure this isn't a header line by any chance, since
-                then MATRIX_ROW_PARTIALLY_VISIBLE_P might yield true.  */
+             /* Make sure this isn't a header line nor a tab-line by
+                any chance, since then MATRIX_ROW_PARTIALLY_VISIBLE_P
+                might yield true.  */
              && !row->mode_line_p
              && !cursor_row_fully_visible_p (w, true, true, true))
            {
@@ -18753,11 +18780,14 @@ redisplay_window (Lisp_Object window, bool 
just_this_one_p)
            }
        }
       /* Finally, fall back on the first row of the window after the
-        header line (if any).  This is slightly better than not
-        displaying the cursor at all.  */
+        tab-line and header line (if any).  This is slightly better
+        than not displaying the cursor at all.  */
       if (!row)
        {
          row = matrix->rows;
+         /* Skip the tab-line and header-line rows, if any.  */
+         if (row->tab_line_p)
+           ++row;
          if (row->mode_line_p)
            ++row;
        }
@@ -19161,6 +19191,14 @@ try_window_reusing_current_matrix (struct window *w)
   if (!NILP (Vdisplay_line_numbers))
     return false;
 
+  /* Can't scroll the display of w32 GUI frames when position of point
+     is indicated by the system caret, because scrolling the display
+     will then "copy" the pixels used by the caret.  */
+#ifdef HAVE_NTGUI
+  if (w32_use_visible_system_caret)
+    return false;
+#endif
+
   /* The variable new_start now holds the new window start.  The old
      start `start' can be determined from the current matrix.  */
   SET_TEXT_POS_FROM_MARKER (new_start, w->start);
@@ -19771,7 +19809,9 @@ row_containing_pos (struct window *w, ptrdiff_t charpos,
   ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1;
   int last_y;
 
-  /* If we happen to start on a header-line, skip that.  */
+  /* If we happen to start on a header-line or a tab-line, skip that.  */
+  if (row->tab_line_p)
+    ++row;
   if (row->mode_line_p)
     ++row;
 
@@ -20143,6 +20183,15 @@ try_window_id (struct window *w)
   if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
     GIVE_UP (20);
 
+  /* Can't let scroll_run_hook below run on w32 GUI frames when
+     position of point is indicated by the system caret, because
+     scrolling the display will then "copy" the pixels used by the
+     caret.  */
+#ifdef HAVE_NTGUI
+  if (FRAME_W32_P (f) && w32_use_visible_system_caret)
+    GIVE_UP (25);
+#endif
+
   /* Compute the position at which we have to start displaying new
      lines.  Some of the lines at the top of the window might be
      reusable because they are not displaying changed text.  Find the
@@ -22364,7 +22413,7 @@ find_row_edges (struct it *it, struct glyph_row *row,
       if (STRINGP (it->object)
          /* this is not the first row */
          && row > it->w->desired_matrix->rows
-         /* previous row is not the header line */
+         /* previous row is not the header line or tab-line */
          && !r1->mode_line_p
          /* previous row also ends in a newline from a string */
          && r1->ends_in_newline_from_string_p)
diff --git a/src/xfns.c b/src/xfns.c
index 021efaf..5758bb7 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -3878,8 +3878,6 @@ This function is an internal primitive--use `make-frame' 
instead.  */)
 #ifdef HAVE_HARFBUZZ
   register_font_driver (&xfthbfont_driver, f);
 #endif
-#else  /* not HAVE_XFT */
-  register_font_driver (&ftxfont_driver, f);
 #endif /* not HAVE_XFT */
 #endif /* HAVE_FREETYPE */
 #endif /* not USE_CAIRO */
@@ -4572,6 +4570,8 @@ On MS Windows, this just returns nil.  */)
     return Qnil;
 }
 
+#if !defined USE_GTK || !defined HAVE_GTK3
+
 /* Store the geometry of the workarea on display DPYINFO into *RECT.
    Return false if and only if the workarea information cannot be
    obtained via the _NET_WORKAREA root window property.  */
@@ -4634,8 +4634,6 @@ x_get_net_workarea (struct x_display_info *dpyinfo, 
XRectangle *rect)
   return result;
 }
 
-#ifndef USE_GTK
-
 /* Return monitor number where F is "most" or closest to.  */
 static int
 x_get_monitor_for_frame (struct frame *f,
@@ -5089,6 +5087,8 @@ Internal use only, use `display-monitor-attributes-list' 
instead.  */)
 #elif defined HAVE_GTK3
       scale = gdk_screen_get_monitor_scale_factor (gscreen, i);
 #endif
+      rec.x *= scale;
+      rec.y *= scale;
       rec.width *= scale;
       rec.height *= scale;
       work.x *= scale;
@@ -6362,8 +6362,6 @@ x_create_tip_frame (struct x_display_info *dpyinfo, 
Lisp_Object parms)
 #ifdef HAVE_HARFBUZZ
   register_font_driver (&xfthbfont_driver, f);
 #endif
-#else  /* not HAVE_XFT */
-  register_font_driver (&ftxfont_driver, f);
 #endif /* not HAVE_XFT */
 #endif /* HAVE_FREETYPE */
 #endif /* not USE_CAIRO */
diff --git a/src/xterm.c b/src/xterm.c
index ada3cec..21d99f0 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -8934,6 +8934,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
       if (f)
        x_cr_update_surface_desired_size (f, configureEvent.xconfigure.width,
                                          configureEvent.xconfigure.height);
+      else if (any && configureEvent.xconfigure.window == FRAME_X_WINDOW (any))
+       x_cr_update_surface_desired_size (any,
+                                         configureEvent.xconfigure.width,
+                                         configureEvent.xconfigure.height);
 #endif
 #ifdef USE_GTK
       if (!f
diff --git a/test/data/emacs-module/mod-test.c 
b/test/data/emacs-module/mod-test.c
index 8dc9ff1..ec69489 100644
--- a/test/data/emacs-module/mod-test.c
+++ b/test/data/emacs-module/mod-test.c
@@ -24,6 +24,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 
 #include <errno.h>
 #include <limits.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -86,6 +87,7 @@ static emacs_value
 Fmod_test_sum (emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data)
 {
   assert (nargs == 2);
+  assert ((uintptr_t) data == 0x1234);
 
   intmax_t a = env->extract_integer (env, args[0]);
   intmax_t b = env->extract_integer (env, args[1]);
@@ -373,15 +375,20 @@ Fmod_test_add_nanosecond (emacs_env *env, ptrdiff_t 
nargs, emacs_value *args,
 }
 
 static void
-memory_full (emacs_env *env)
+signal_error (emacs_env *env, const char *message)
 {
-  const char *message = "Memory exhausted";
   emacs_value data = env->make_string (env, message, strlen (message));
   env->non_local_exit_signal (env, env->intern (env, "error"),
                               env->funcall (env, env->intern (env, "list"), 1,
                                             &data));
 }
 
+static void
+memory_full (emacs_env *env)
+{
+  signal_error (env, "Memory exhausted");
+}
+
 enum
 {
   max_count = ((SIZE_MAX < PTRDIFF_MAX ? SIZE_MAX : PTRDIFF_MAX)
@@ -490,6 +497,42 @@ Fmod_test_double (emacs_env *env, ptrdiff_t nargs, 
emacs_value *args,
   return result;
 }
 
+static int function_data;
+static int finalizer_calls_with_correct_data;
+static int finalizer_calls_with_incorrect_data;
+
+static void
+finalizer (void *data)
+{
+  if (data == &function_data)
+    ++finalizer_calls_with_correct_data;
+  else
+    ++finalizer_calls_with_incorrect_data;
+}
+
+static emacs_value
+Fmod_test_make_function_with_finalizer (emacs_env *env, ptrdiff_t nargs,
+                                        emacs_value *args, void *data)
+{
+  emacs_value fun
+    = env->make_function (env, 2, 2, Fmod_test_sum, NULL, &function_data);
+  env->set_function_finalizer (env, fun, finalizer);
+  if (env->get_function_finalizer (env, fun) != finalizer)
+    signal_error (env, "Invalid finalizer");
+  return fun;
+}
+
+static emacs_value
+Fmod_test_function_finalizer_calls (emacs_env *env, ptrdiff_t nargs,
+                                    emacs_value *args, void *data)
+{
+  emacs_value Flist = env->intern (env, "list");
+  emacs_value list_args[]
+    = {env->make_integer (env, finalizer_calls_with_correct_data),
+       env->make_integer (env, finalizer_calls_with_incorrect_data)};
+  return env->funcall (env, Flist, 2, list_args);
+}
+
 /* Lisp utilities for easier readability (simple wrappers).  */
 
 /* Provide FEATURE to Emacs.  */
@@ -546,7 +589,8 @@ emacs_module_init (struct emacs_runtime *ert)
                 env->make_function (env, amin, amax, csym, doc, data))
 
   DEFUN ("mod-test-return-t", Fmod_test_return_t, 1, 1, NULL, NULL);
-  DEFUN ("mod-test-sum", Fmod_test_sum, 2, 2, "Return A + B\n\n(fn a b)", 
NULL);
+  DEFUN ("mod-test-sum", Fmod_test_sum, 2, 2, "Return A + B\n\n(fn a b)",
+         (void *) (uintptr_t) 0x1234);
   DEFUN ("mod-test-signal", Fmod_test_signal, 0, 0, NULL, NULL);
   DEFUN ("mod-test-throw", Fmod_test_throw, 0, 0, NULL, NULL);
   DEFUN ("mod-test-non-local-exit-funcall", Fmod_test_non_local_exit_funcall,
@@ -566,6 +610,10 @@ emacs_module_init (struct emacs_runtime *ert)
   DEFUN ("mod-test-add-nanosecond", Fmod_test_add_nanosecond, 1, 1, NULL, 
NULL);
   DEFUN ("mod-test-nanoseconds", Fmod_test_nanoseconds, 1, 1, NULL, NULL);
   DEFUN ("mod-test-double", Fmod_test_double, 1, 1, NULL, NULL);
+  DEFUN ("mod-test-make-function-with-finalizer",
+         Fmod_test_make_function_with_finalizer, 0, 0, NULL, NULL);
+  DEFUN ("mod-test-function-finalizer-calls",
+         Fmod_test_function_finalizer_calls, 0, 0, NULL, NULL);
 
 #undef DEFUN
 
diff --git a/test/lisp/auth-source-pass-tests.el 
b/test/lisp/auth-source-pass-tests.el
index 10ed9c3..677abb3 100644
--- a/test/lisp/auth-source-pass-tests.el
+++ b/test/lisp/auth-source-pass-tests.el
@@ -353,6 +353,10 @@ HOSTNAME, USER and PORT are passed unchanged to
   (auth-source-pass--with-store '(("bar.com:8080"))
     (should (auth-source-pass-match-entry-p "bar.com:8080" "bar.com" nil 
"8080"))))
 
+(ert-deftest 
auth-source-pass--matching-entries-find-entries-with-a-port-when-passed-multiple-ports
 ()
+  (auth-source-pass--with-store '(("bar.com:8080"))
+    (should (auth-source-pass-match-entry-p "bar.com:8080" "bar.com" nil 
'("http" "https" "80" "8080")))))
+
 (ert-deftest auth-source-pass--matching-entries-find-entries-with-slash ()
   ;; match if entry filename matches user
   (auth-source-pass--with-store '(("foo.com/user"))
diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el
index f7c5580..ec3e4bb 100644
--- a/test/lisp/autorevert-tests.el
+++ b/test/lisp/autorevert-tests.el
@@ -59,8 +59,7 @@
       auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded"
       auto-revert-stop-on-user-input nil
       file-notify-debug nil
-      tramp-verbose 0
-      tramp-message-show-message nil)
+      tramp-verbose 0)
 
 (defconst auto-revert--timeout (1+ auto-revert-interval)
   "Time to wait for a message.")
diff --git a/test/lisp/bookmark-tests.el b/test/lisp/bookmark-tests.el
index 7e0384b..b9c6ff9 100644
--- a/test/lisp/bookmark-tests.el
+++ b/test/lisp/bookmark-tests.el
@@ -25,6 +25,7 @@
 
 (require 'ert)
 (require 'bookmark)
+(require 'cl-lib)
 
 (defvar bookmark-tests-data-dir
   (file-truename
@@ -339,21 +340,21 @@ testing `bookmark-bmenu-list'."
             ,@body)
         (kill-buffer bookmark-bmenu-buffer)))))
 
-(ert-deftest bookmark-bmenu.enu-edit-annotation/show-annotation ()
+(ert-deftest bookmark-test-bmenu-edit-annotation/show-annotation ()
   (with-bookmark-bmenu-test
    (bookmark-set-annotation "name" "foo")
    (bookmark-bmenu-edit-annotation)
    (should (string-match "foo" (buffer-string)))
    (kill-buffer (current-buffer))))
 
-(ert-deftest bookmark-bmenu-send-edited-annotation ()
+(ert-deftest bookmark-test-bmenu-send-edited-annotation ()
   (with-bookmark-bmenu-test
    (bookmark-bmenu-edit-annotation)
    (insert "foo")
    (bookmark-send-edited-annotation)
    (should (equal (bookmark-get-annotation "name") "foo"))))
 
-(ert-deftest bookmark-bmenu-send-edited-annotation/restore-focus ()
+(ert-deftest bookmark-test-bmenu-send-edited-annotation/restore-focus ()
   "Test for https://debbugs.gnu.org/20150 ."
   (with-bookmark-bmenu-test
    (bookmark-bmenu-edit-annotation)
@@ -362,5 +363,73 @@ testing `bookmark-bmenu-list'."
    (should (equal (buffer-name (current-buffer)) bookmark-bmenu-buffer))
    (should (looking-at "name"))))
 
+(ert-deftest bookmark-test-bmenu-toggle-filenames ()
+  (with-bookmark-bmenu-test
+   (should (re-search-forward "/some/file" nil t))
+   (bookmark-bmenu-toggle-filenames)
+   (goto-char (point-min))
+   (should-not (re-search-forward "/some/file" nil t))))
+
+(ert-deftest bookmark-test-bmenu-toggle-filenames/show ()
+  (with-bookmark-bmenu-test
+   (bookmark-bmenu-toggle-filenames t)
+   (should (re-search-forward "/some/file"))))
+
+(ert-deftest bookmark-test-bmenu-show-filenames ()
+  (with-bookmark-bmenu-test
+   (bookmark-bmenu-show-filenames)
+   (should (re-search-forward "/some/file"))))
+
+(ert-deftest bookmark-test-bmenu-hide-filenames ()
+  (with-bookmark-bmenu-test
+   (bookmark-bmenu-hide-filenames)
+   (goto-char (point-min))
+   (should-not (re-search-forward "/some/file" nil t))))
+
+(ert-deftest bookmark-test-bmenu-bookmark ()
+  (with-bookmark-bmenu-test
+   (should (equal (bookmark-bmenu-bookmark) "name"))))
+
+(ert-deftest bookmark-test-bmenu-mark ()
+  (with-bookmark-bmenu-test
+   (bookmark-bmenu-mark)
+   (beginning-of-line)
+   (should (looking-at "^>"))))
+
+(ert-deftest bookmark-test-bmenu-any-marks ()
+  (with-bookmark-bmenu-test
+   (bookmark-bmenu-mark)
+   (beginning-of-line)
+   (should (bookmark-bmenu-any-marks))))
+
+(ert-deftest bookmark-test-bmenu-unmark ()
+  (with-bookmark-bmenu-test
+   (bookmark-bmenu-mark)
+   (goto-char (point-min))
+   (bookmark-bmenu-unmark)
+   (beginning-of-line)
+   (should (looking-at "^  "))))
+
+(ert-deftest bookmark-test-bmenu-delete ()
+  (with-bookmark-bmenu-test
+   (bookmark-bmenu-delete)
+   (bookmark-bmenu-execute-deletions)
+   (should (equal (length bookmark-alist) 0))))
+
+(ert-deftest bookmark-test-bmenu-locate ()
+  (let (msg)
+    (cl-letf (((symbol-function 'message)
+               (lambda (&rest args)
+                 (setq msg (apply #'format args)))))
+      (with-bookmark-bmenu-test
+       (bookmark-bmenu-locate)
+       (should (equal msg "/some/file"))))))
+
+(ert-deftest bookmark-test-bmenu-filter-alist-by-regexp ()
+  (with-bookmark-bmenu-test
+   (bookmark-bmenu-filter-alist-by-regexp regexp-unmatchable)
+   (goto-char (point-min))
+   (should (looking-at "^$"))))
+
 (provide 'bookmark-tests)
 ;;; bookmark-tests.el ends here
diff --git a/test/lisp/calendar/iso8601-tests.el 
b/test/lisp/calendar/iso8601-tests.el
index 430680c..e8b155a 100644
--- a/test/lisp/calendar/iso8601-tests.el
+++ b/test/lisp/calendar/iso8601-tests.el
@@ -24,49 +24,61 @@
 
 (ert-deftest test-iso8601-date-years ()
   (should (equal (iso8601-parse-date "1985")
-                 '(nil nil nil nil nil 1985 nil nil nil)))
+                 '(nil nil nil nil nil 1985 nil -1 nil)))
   (should (equal (iso8601-parse-date "-0003")
-                 '(nil nil nil nil nil -3 nil nil nil)))
+                 '(nil nil nil nil nil -3 nil -1 nil)))
   (should (equal (iso8601-parse-date "+1985")
-                 '(nil nil nil nil nil 1985 nil nil nil))))
+                 '(nil nil nil nil nil 1985 nil -1 nil))))
 
 (ert-deftest test-iso8601-date-dates ()
   (should (equal (iso8601-parse-date "1985-03-14")
-                 '(nil nil nil 14 3 1985 nil nil nil)))
+                 '(nil nil nil 14 3 1985 nil -1 nil)))
   (should (equal (iso8601-parse-date "19850314")
-                 '(nil nil nil 14 3 1985 nil nil nil)))
+                 '(nil nil nil 14 3 1985 nil -1 nil)))
   (should (equal (iso8601-parse-date "1985-02")
-                 '(nil nil nil nil 2 1985 nil nil nil))))
+                 '(nil nil nil nil 2 1985 nil -1 nil))))
 
 (ert-deftest test-iso8601-date-obsolete ()
   (should (equal (iso8601-parse-date "--02-01")
-                 '(nil nil nil 1 2 nil nil nil nil)))
+                 '(nil nil nil 1 2 nil nil -1 nil)))
   (should (equal (iso8601-parse-date "--0201")
-                 '(nil nil nil 1 2 nil nil nil nil))))
+                 '(nil nil nil 1 2 nil nil -1 nil))))
+
+(ert-deftest test-iso8601-date-obsolete-2000 ()
+  ;; These are forms in 5.2.1.3 of the 2000 version of the standard,
+  ;; e) and f).
+  (should (equal (iso8601-parse-date "--12")
+                 '(nil nil nil nil 12 nil nil -1 nil)))
+  (should (equal (iso8601-parse "--12T14")
+                 '(0 0 14 nil 12 nil nil -1 nil)))
+  (should (equal (iso8601-parse-date "---12")
+                 '(nil nil nil 12 nil nil nil -1 nil)))
+  (should (equal (iso8601-parse "---12T14:10:12")
+                 '(12 10 14 12 nil nil nil -1 nil))))
 
 (ert-deftest test-iso8601-date-weeks ()
   (should (equal (iso8601-parse-date "2008W39-6")
-                 '(nil nil nil 27 9 2008 nil nil nil)))
+                 '(nil nil nil 27 9 2008 nil -1 nil)))
   (should (equal (iso8601-parse-date "2009W01-1")
-                 '(nil nil nil 29 12 2008 nil nil nil)))
+                 '(nil nil nil 29 12 2008 nil -1 nil)))
   (should (equal (iso8601-parse-date "2009W53-7")
-                 '(nil nil nil 3 1 2010 nil nil nil))))
+                 '(nil nil nil 3 1 2010 nil -1 nil))))
 
 (ert-deftest test-iso8601-date-ordinals ()
   (should (equal (iso8601-parse-date "1981-095")
-                 '(nil nil nil 5 4 1981 nil nil nil))))
+                 '(nil nil nil 5 4 1981 nil -1 nil))))
 
 (ert-deftest test-iso8601-time ()
   (should (equal (iso8601-parse-time "13:47:30")
-                 '(30 47 13 nil nil nil nil nil nil)))
+                 '(30 47 13 nil nil nil nil -1 nil)))
   (should (equal (iso8601-parse-time "134730")
-                 '(30 47 13 nil nil nil nil nil nil)))
+                 '(30 47 13 nil nil nil nil -1 nil)))
   (should (equal (iso8601-parse-time "1347")
-                 '(0 47 13 nil nil nil nil nil nil))))
+                 '(0 47 13 nil nil nil nil -1 nil))))
 
 (ert-deftest test-iso8601-combined ()
   (should (equal (iso8601-parse "2008-03-02T13:47:30")
-                 '(30 47 13 2 3 2008 nil nil nil)))
+                 '(30 47 13 2 3 2008 nil -1 nil)))
   (should (equal (iso8601-parse "2008-03-02T13:47:30Z")
                  '(30 47 13 2 3 2008 nil nil 0)))
   (should (equal (iso8601-parse "2008-03-02T13:47:30+01:00")
@@ -76,13 +88,13 @@
 
 (ert-deftest test-iso8601-duration ()
   (should (equal (iso8601-parse-duration "P3Y6M4DT12H30M5S")
-                 '(5 30 12 4 6 3 nil nil nil)))
+                 '(5 30 12 4 6 3 nil -1 nil)))
   (should (equal (iso8601-parse-duration "P1M")
-                 '(0 0 0 0 1 0 nil nil nil)))
+                 '(0 0 0 0 1 0 nil -1 nil)))
   (should (equal (iso8601-parse-duration "PT1M")
-                 '(0 1 0 0 0 0 nil nil nil)))
+                 '(0 1 0 0 0 0 nil -1 nil)))
   (should (equal (iso8601-parse-duration "P0003-06-04T12:30:05")
-                 '(5 30 12 4 6 3 nil nil nil))))
+                 '(5 30 12 4 6 3 nil -1 nil))))
 
 (ert-deftest test-iso8601-invalid ()
   (should-not (iso8601-valid-p " 2008-03-02T13:47:30-01"))
@@ -101,88 +113,88 @@
   (should (equal (iso8601-parse-interval "2007-03-01T13:00:00Z/P1Y2M10DT2H30M")
                  '((0 0 13 1 3 2007 nil nil 0)
                    (0 30 15 11 5 2008 nil nil 0)
-                   (0 30 2 10 2 1 nil nil nil))))
+                   (0 30 2 10 2 1 nil -1 nil))))
   (should (equal (iso8601-parse-interval "P1Y2M10DT2H30M/2008-05-11T15:30:00Z")
                  '((0 0 13 1 3 2007 nil nil 0)
                    (0 30 15 11 5 2008 nil nil 0)
-                   (0 30 2 10 2 1 nil nil nil)))))
+                   (0 30 2 10 2 1 nil -1 nil)))))
 
 (ert-deftest standard-test-dates ()
   (should (equal (iso8601-parse-date "19850412")
-                 '(nil nil nil 12 4 1985 nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil -1 nil)))
   (should (equal (iso8601-parse-date "1985-04-12")
-                 '(nil nil nil 12 4 1985 nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil -1 nil)))
 
   (should (equal (iso8601-parse-date "1985102")
-                 '(nil nil nil 12 4 1985 nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil -1 nil)))
   (should (equal (iso8601-parse-date "1985-102")
-                 '(nil nil nil 12 4 1985 nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil -1 nil)))
 
   (should (equal (iso8601-parse-date "1985W155")
-                 '(nil nil nil 12 4 1985 nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil -1 nil)))
   (should (equal (iso8601-parse-date "1985-W15-5")
-                 '(nil nil nil 12 4 1985 nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil -1 nil)))
 
   (should (equal (iso8601-parse-date "1985W15")
-                 '(nil nil nil 7 4 1985 nil nil nil)))
+                 '(nil nil nil 7 4 1985 nil -1 nil)))
   (should (equal (iso8601-parse-date "1985-W15")
-                 '(nil nil nil 7 4 1985 nil nil nil)))
+                 '(nil nil nil 7 4 1985 nil -1 nil)))
 
   (should (equal (iso8601-parse-date "1985-04")
-                 '(nil nil nil nil 4 1985 nil nil nil)))
+                 '(nil nil nil nil 4 1985 nil -1 nil)))
 
   (should (equal (iso8601-parse-date "1985")
-                 '(nil nil nil nil nil 1985 nil nil nil)))
+                 '(nil nil nil nil nil 1985 nil -1 nil)))
 
   (should (equal (iso8601-parse-date "+1985-04-12")
-                 '(nil nil nil 12 4 1985 nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil -1 nil)))
   (should (equal (iso8601-parse-date "+19850412")
-                 '(nil nil nil 12 4 1985 nil nil nil))))
+                 '(nil nil nil 12 4 1985 nil -1 nil))))
 
 (ert-deftest standard-test-time-of-day-local-time ()
   (should (equal (iso8601-parse-time "152746")
-                 '(46 27 15 nil nil nil nil nil nil)))
+                 '(46 27 15 nil nil nil nil -1 nil)))
   (should (equal (iso8601-parse-time "15:27:46")
-                 '(46 27 15 nil nil nil nil nil nil)))
+                 '(46 27 15 nil nil nil nil -1 nil)))
 
   (should (equal (iso8601-parse-time "1528")
-                 '(0 28 15 nil nil nil nil nil nil)))
+                 '(0 28 15 nil nil nil nil -1 nil)))
   (should (equal (iso8601-parse-time "15:28")
-                 '(0 28 15 nil nil nil nil nil nil)))
+                 '(0 28 15 nil nil nil nil -1 nil)))
 
   (should (equal (iso8601-parse-time "15")
-                 '(0 0 15 nil nil nil nil nil nil))))
+                 '(0 0 15 nil nil nil nil -1 nil))))
 
 (ert-deftest standard-test-time-of-day-fractions ()
   (should (equal (iso8601-parse-time "152735,5" t)
-                 '((355 . 10) 27 15 nil nil nil nil nil nil)))
+                 '((355 . 10) 27 15 nil nil nil nil -1 nil)))
   (should (equal (iso8601-parse-time "15:27:35,5" t)
-                 '((355 . 10) 27 15 nil nil nil nil nil nil)))
+                 '((355 . 10) 27 15 nil nil nil nil -1 nil)))
 
   (should (equal (iso8601-parse-time "2320,5" t)
-                 '(30 20 23 nil nil nil nil nil nil)))
+                 '(30 20 23 nil nil nil nil -1 nil)))
   (should (equal (iso8601-parse-time "23:20,8" t)
-                 '(48 20 23 nil nil nil nil nil nil)))
+                 '(48 20 23 nil nil nil nil -1 nil)))
 
   (should (equal (iso8601-parse-time "23,3" t)
-                 '(0 18 23 nil nil nil nil nil nil))))
+                 '(0 18 23 nil nil nil nil -1 nil))))
 
 (ert-deftest nonstandard-test-time-of-day-decimals ()
   (should (equal (iso8601-parse-time "15:27:35.123" t)
-                 '((35123 . 1000) 27 15 nil nil nil nil nil nil)))
+                 '((35123 . 1000) 27 15 nil nil nil nil -1 nil)))
   (should (equal (iso8601-parse-time "15:27:35.123456789" t)
-                 '((35123456789 . 1000000000) 27 15 nil nil nil nil nil nil))))
+                 '((35123456789 . 1000000000) 27 15 nil nil nil nil -1 nil))))
 
 (ert-deftest standard-test-time-of-day-beginning-of-day ()
   (should (equal (iso8601-parse-time "000000")
-                 '(0 0 0 nil nil nil nil nil nil)))
+                 '(0 0 0 nil nil nil nil -1 nil)))
   (should (equal (iso8601-parse-time "00:00:00")
-                 '(0 0 0 nil nil nil nil nil nil)))
+                 '(0 0 0 nil nil nil nil -1 nil)))
 
   (should (equal (iso8601-parse-time "0000")
-                 '(0 0 0 nil nil nil nil nil nil)))
+                 '(0 0 0 nil nil nil nil -1 nil)))
   (should (equal (iso8601-parse-time "00:00")
-                 '(0 0 0 nil nil nil nil nil nil))))
+                 '(0 0 0 nil nil nil nil -1 nil))))
 
 (ert-deftest standard-test-time-of-day-utc ()
   (should (equal (iso8601-parse-time "232030Z")
@@ -222,9 +234,9 @@
 
 (ert-deftest standard-test-date-and-time-of-day ()
   (should (equal (iso8601-parse "19850412T101530")
-                 '(30 15 10 12 4 1985 nil nil nil)))
+                 '(30 15 10 12 4 1985 nil -1 nil)))
   (should (equal (iso8601-parse "1985-04-12T10:15:30")
-                 '(30 15 10 12 4 1985 nil nil nil)))
+                 '(30 15 10 12 4 1985 nil -1 nil)))
 
   (should (equal (iso8601-parse "1985102T235030Z")
                  '(30 50 23 12 4 1985 nil nil 0)))
@@ -232,9 +244,9 @@
                  '(30 50 23 12 4 1985 nil nil 0)))
 
   (should (equal (iso8601-parse "1985W155T235030")
-                 '(30 50 23 12 4 1985 nil nil nil)))
+                 '(30 50 23 12 4 1985 nil -1 nil)))
   (should (equal (iso8601-parse "1985-W155T23:50:30")
-                 '(30 50 23 12 4 1985 nil nil nil))))
+                 '(30 50 23 12 4 1985 nil -1 nil))))
 
 (ert-deftest standard-test-interval ()
   ;; A time interval starting at 20 minutes and 50 seconds past 23
@@ -256,48 +268,48 @@
   ;; This example doesn't seem valid according to the standard.
   ;; "0625" is unambiguous, and means "the year 625".  Weird.
   ;; (should (equal (iso8601-parse-interval "19850412/0625")
-  ;;                '((nil nil nil 12 4 1985 nil nil nil)
-  ;;                  (nil nil nil nil nil 625 nil nil nil)
+  ;;                '((nil nil nil 12 4 1985 nil -1 nil)
+  ;;                  (nil nil nil nil nil 625 nil -1 nil)
   ;;                  (0 17 0 22 9 609 5 nil 0))))
 
   ;; A time interval of 2 years, 10 months, 15 days, 10 hours, 20
   ;; minutes and 30 seconds.
   (should (equal (iso8601-parse-duration "P2Y10M15DT10H20M30S")
-                 '(30 20 10 15 10 2 nil nil nil)))
+                 '(30 20 10 15 10 2 nil -1 nil)))
 
   (should (equal (iso8601-parse-duration "P00021015T102030")
-                 '(30 20 10 15 10 2 nil nil nil)))
+                 '(30 20 10 15 10 2 nil -1 nil)))
   (should (equal (iso8601-parse-duration "P0002-10-15T10:20:30")
-                 '(30 20 10 15 10 2 nil nil nil)))
+                 '(30 20 10 15 10 2 nil -1 nil)))
 
   ;; A time interval of 1 year and 6 months.
   (should (equal (iso8601-parse-duration "P1Y6M")
-                 '(0 0 0 0 6 1 nil nil nil)))
+                 '(0 0 0 0 6 1 nil -1 nil)))
   (should (equal (iso8601-parse-duration "P0001-06")
-                 '(nil nil nil nil 6 1 nil nil nil)))
+                 '(nil nil nil nil 6 1 nil -1 nil)))
 
   ;; A time interval of seventy-two hours.
   (should (equal (iso8601-parse-duration "PT72H")
-                 '(0 0 72 0 0 0 nil nil nil)))
+                 '(0 0 72 0 0 0 nil -1 nil)))
 
   ;; Defined by start and duration
   ;; A time interval of 1 year, 2 months, 15 days and 12 hours,
   ;; beginning on 12 April 1985 at 20 minutes past 23 hours.
   (should (equal (iso8601-parse-interval "19850412T232000/P1Y2M15DT12H")
-                 '((0 20 23 12 4 1985 nil nil nil)
-                   (0 20 11 28 6 1986 nil nil nil)
-                   (0 0 12 15 2 1 nil nil nil))))
+                 '((0 20 23 12 4 1985 nil -1 nil)
+                   (0 20 11 28 6 1986 nil -1 nil)
+                   (0 0 12 15 2 1 nil -1 nil))))
   (should (equal (iso8601-parse-interval "1985-04-12T23:20:00/P1Y2M15DT12H")
-                 '((0 20 23 12 4 1985 nil nil nil)
-                   (0 20 11 28 6 1986 nil nil nil)
-                   (0 0 12 15 2 1 nil nil nil))))
+                 '((0 20 23 12 4 1985 nil -1 nil)
+                   (0 20 11 28 6 1986 nil -1 nil)
+                   (0 0 12 15 2 1 nil -1 nil))))
 
   ;; Defined by duration and end
   ;; A time interval of 1 year, 2 months, 15 days and 12 hours, ending
   ;; on 12 April 1985 at 20 minutes past 23 hour.
   (should (equal (iso8601-parse-interval "P1Y2M15DT12H/19850412T232000")
-                 '((0 20 11 28 1 1984 nil nil nil)
-                   (0 20 23 12 4 1985 nil nil nil)
-                   (0 0 12 15 2 1 nil nil nil)))))
+                 '((0 20 11 28 1 1984 nil -1 nil)
+                   (0 20 23 12 4 1985 nil -1 nil)
+                   (0 0 12 15 2 1 nil -1 nil)))))
 
 ;;; iso8601-tests.el ends here
diff --git a/test/lisp/ffap-tests.el b/test/lisp/ffap-tests.el
index eaf3968..30c8f79 100644
--- a/test/lisp/ffap-tests.el
+++ b/test/lisp/ffap-tests.el
@@ -74,7 +74,7 @@ left alone when opening a URL in an external browser."
              (urls nil)
              (ffap-url-fetcher (lambda (url) (push url urls) nil)))
     (should-not (ffap-other-window "https://www.gnu.org";))
-    (should (equal (current-window-configuration) old))
+    (should (compare-window-configurations (current-window-configuration) old))
     (should (equal urls '("https://www.gnu.org";)))))
 
 (provide 'ffap-tests)
diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el
index e9dc753..39156fb 100644
--- a/test/lisp/filenotify-tests.el
+++ b/test/lisp/filenotify-tests.el
@@ -200,8 +200,7 @@ Return nil when any other file notification watch is still 
active."
 
 (setq file-notify-debug nil
       password-cache-expiry nil
-      tramp-verbose 0
-      tramp-message-show-message nil)
+      tramp-verbose 0)
 
 ;; This should happen on hydra only.
 (when (getenv "EMACS_HYDRA_CI")
@@ -929,17 +928,18 @@ delivered."
            ;; Modify file.  We wait for a second, in order to have
             ;; another timestamp.
             (ert-with-message-capture captured-messages
-              (sleep-for 1)
-              (write-region
-               "another text" nil file-notify--test-tmpfile nil 'no-message)
-
-              ;; Check, that the buffer has been reverted.
-              (file-notify--test-wait-for-events
-               timeout
-               (string-match
-                (format-message "Reverting buffer `%s'." (buffer-name buf))
-                captured-messages))
-              (should (string-match "another text" (buffer-string))))
+              (let ((inhibit-message t))
+                (sleep-for 1)
+                (write-region
+                 "another text" nil file-notify--test-tmpfile nil 'no-message)
+
+                ;; Check, that the buffer has been reverted.
+                (file-notify--test-wait-for-events
+                 timeout
+                 (string-match
+                  (format-message "Reverting buffer `%s'." (buffer-name buf))
+                  captured-messages))
+                (should (string-match "another text" (buffer-string)))))
 
             ;; Stop file notification.  Autorevert shall still work via 
polling.
            (file-notify-rm-watch auto-revert-notify-watch-descriptor)
@@ -953,17 +953,18 @@ delivered."
            ;; have another timestamp.  One second seems to be too
             ;; short.  And Cygwin sporadically requires more than two.
             (ert-with-message-capture captured-messages
-              (sleep-for (if (eq system-type 'cygwin) 3 2))
-              (write-region
-               "foo bla" nil file-notify--test-tmpfile nil 'no-message)
-
-              ;; Check, that the buffer has been reverted.
-              (file-notify--test-wait-for-events
-               timeout
-               (string-match
-                (format-message "Reverting buffer `%s'." (buffer-name buf))
-                captured-messages))
-              (should (string-match "foo bla" (buffer-string))))
+              (let ((inhibit-message t))
+                (sleep-for (if (eq system-type 'cygwin) 3 2))
+                (write-region
+                 "foo bla" nil file-notify--test-tmpfile nil 'no-message)
+
+                ;; Check, that the buffer has been reverted.
+                (file-notify--test-wait-for-events
+                 timeout
+                 (string-match
+                  (format-message "Reverting buffer `%s'." (buffer-name buf))
+                  captured-messages))
+                (should (string-match "foo bla" (buffer-string)))))
 
             ;; Stop autorevert, in order to cleanup descriptor.
             (auto-revert-mode -1))
diff --git a/test/lisp/help-fns-tests.el b/test/lisp/help-fns-tests.el
index 4c808d8..d2dc3d2 100644
--- a/test/lisp/help-fns-tests.el
+++ b/test/lisp/help-fns-tests.el
@@ -56,28 +56,28 @@ Return first line of the output of (describe-function-1 
FUNC)."
     (should (string-match regexp result))))
 
 (ert-deftest help-fns-test-lisp-macro ()
-  (let ((regexp "a Lisp macro in .subr\.el")
+  (let ((regexp "a Lisp macro in .subr\\.el")
         (result (help-fns-tests--describe-function 'when)))
     (should (string-match regexp result))))
 
 (ert-deftest help-fns-test-lisp-defun ()
-  (let ((regexp "a compiled Lisp function in .subr\.el")
+  (let ((regexp "a compiled Lisp function in .subr\\.el")
         (result (help-fns-tests--describe-function 'last)))
     (should (string-match regexp result))))
 
 (ert-deftest help-fns-test-lisp-defsubst ()
-  (let ((regexp "a compiled Lisp function in .subr\.el")
+  (let ((regexp "a compiled Lisp function in .subr\\.el")
         (result (help-fns-tests--describe-function 'posn-window)))
     (should (string-match regexp result))))
 
 (ert-deftest help-fns-test-alias-to-defun ()
-  (let ((regexp "an alias for .set-file-modes. in .subr\.el")
+  (let ((regexp "an alias for .set-file-modes. in .subr\\.el")
         (result (help-fns-tests--describe-function 'chmod)))
     (should (string-match regexp result))))
 
 (ert-deftest help-fns-test-bug23887 ()
   "Test for https://debbugs.gnu.org/23887 ."
-  (let ((regexp "an alias for .re-search-forward. in .subr\.el")
+  (let ((regexp "an alias for .re-search-forward. in .subr\\.el")
         (result (help-fns-tests--describe-function 'search-forward-regexp)))
     (should (string-match regexp result))))
 
@@ -123,4 +123,41 @@ Return first line of the output of (describe-function-1 
FUNC)."
     (goto-char (point-min))
     (should (looking-at "^font-lock-comment-face is "))))
 
+
+;;; Tests for describe-keymap
+(ert-deftest help-fns-test-find-keymap-name ()
+  (should (equal (help-fns-find-keymap-name lisp-mode-map) 'lisp-mode-map))
+  ;; Follow aliasing.
+  (unwind-protect
+      (progn
+        (defvaralias 'foo-test-map 'lisp-mode-map)
+        (should (equal (help-fns-find-keymap-name foo-test-map) 
'lisp-mode-map)))
+    (makunbound 'foo-test-map)))
+
+(ert-deftest help-fns-test-describe-keymap/symbol ()
+  (describe-keymap 'minibuffer-local-must-match-map)
+  (with-current-buffer "*Help*"
+    (should (looking-at "^minibuffer-local-must-match-map is"))))
+
+(ert-deftest help-fns-test-describe-keymap/value ()
+  (describe-keymap minibuffer-local-must-match-map)
+  (with-current-buffer "*Help*"
+    (should (looking-at "^key"))))
+
+(ert-deftest help-fns-test-describe-keymap/not-keymap ()
+  (should-error (describe-keymap nil))
+  (should-error (describe-keymap emacs-version)))
+
+(ert-deftest help-fns-test-describe-keymap/let-bound ()
+  (let ((foobar minibuffer-local-must-match-map))
+    (describe-keymap foobar)
+    (with-current-buffer "*Help*"
+      (should (looking-at "^key")))))
+
+(ert-deftest help-fns-test-describe-keymap/dynamically-bound-no-file ()
+  (setq help-fns-test--describe-keymap-foo minibuffer-local-must-match-map)
+  (describe-keymap 'help-fns-test--describe-keymap-foo)
+  (with-current-buffer "*Help*"
+    (should (looking-at "^help-fns-test--describe-keymap-foo is"))))
+
 ;;; help-fns-tests.el ends here
diff --git a/test/lisp/ibuffer-tests.el b/test/lisp/ibuffer-tests.el
index 8dadb92..2211cae 100644
--- a/test/lisp/ibuffer-tests.el
+++ b/test/lisp/ibuffer-tests.el
@@ -82,7 +82,7 @@
         (test1 '((mode . org-mode)
                  (or (size-gt . 10000)
                      (and (not (starred-name))
-                          (directory . "\<org\>")))))
+                          (directory . "<org>")))))
         (test2 '((or (mode . emacs-lisp-mode) (file-extension . "elc?")
                      (and (starred-name) (name . "elisp"))
                      (mode . lisp-interaction-mode))))
diff --git a/test/lisp/international/ucs-normalize-tests.el 
b/test/lisp/international/ucs-normalize-tests.el
index 82ea207..ec77e65 100644
--- a/test/lisp/international/ucs-normalize-tests.el
+++ b/test/lisp/international/ucs-normalize-tests.el
@@ -299,7 +299,7 @@ implementations:
   (list " var var))
   (dolist (linos (seq-partition newval 8))
     (insert (mapconcat #'number-to-string linos " ") "\n"))
-  (insert ")\)"))
+  (insert "))"))
 
 (defun ucs-normalize-check-failing-lines ()
   (interactive)
diff --git a/test/lisp/net/sasl-scram-rfc-tests.el 
b/test/lisp/net/sasl-scram-rfc-tests.el
index ec283c8..09e05b6 100644
--- a/test/lisp/net/sasl-scram-rfc-tests.el
+++ b/test/lisp/net/sasl-scram-rfc-tests.el
@@ -1,4 +1,4 @@
-;;; sasl-scram-rfc-tests.el --- tests for SCRAM-SHA-1       -*- 
lexical-binding: t; -*-
+;;; sasl-scram-rfc-tests.el --- tests for SCRAM       -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2014-2020 Free Software Foundation, Inc.
 
@@ -19,7 +19,7 @@
 
 ;;; Commentary:
 
-;; Test cases from RFC 5802.
+;; Test cases from RFC 5802 and RFC 7677.
 
 ;;; Code:
 
@@ -47,4 +47,26 @@
     (sasl-scram-sha-1-authenticate-server client (vector nil 
"v=rmF9pqV8S7suAoZWja4dJRkFsKQ=
 "))))
 
+(require 'sasl-scram-sha256)
+
+(ert-deftest sasl-scram-sha-256-test ()
+  ;; The following strings are taken from section 3 of RFC 7677.
+  (let ((client
+         (sasl-make-client (sasl-find-mechanism '("SCRAM-SHA-256"))
+                           "user"
+                           "imap"
+                           "localhost"))
+        (data 
"r=rOprNGfwEbeRWgbNEkqO%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0,s=W22ZaJ0SNY7soEsUEjb6gQ==,i=4096")
+        (c-nonce "rOprNGfwEbeRWgbNEkqO")
+        (sasl-read-passphrase
+         (lambda (_prompt) (copy-sequence "pencil"))))
+    (sasl-client-set-property client 'c-nonce c-nonce)
+    (should
+     (equal
+      (sasl-scram-sha-256-client-final-message client (vector nil data))
+      
"c=biws,r=rOprNGfwEbeRWgbNEkqO%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0,p=dHzbZapWIk4jUhN+Ute9ytag9zjfMHgsqmmiz7AndVQ="))
+
+    ;; This should not throw an error:
+    (sasl-scram-sha-256-authenticate-server client (vector nil 
"v=6rriTRBi23WpRR/wtup+mMhUZUn/dB5nLTJRsjl95G4="))))
+
 ;;; sasl-scram-rfc-tests.el ends here
diff --git a/test/lisp/net/tramp-archive-tests.el 
b/test/lisp/net/tramp-archive-tests.el
index 3229d2b..b3fc129 100644
--- a/test/lisp/net/tramp-archive-tests.el
+++ b/test/lisp/net/tramp-archive-tests.el
@@ -60,7 +60,6 @@
 (setq password-cache-expiry nil
       tramp-cache-read-persistent-data t ;; For auth-sources.
       tramp-copy-size-limit nil
-      tramp-message-show-message nil
       tramp-persistency-file-name nil
       tramp-verbose 0)
 
@@ -971,4 +970,5 @@ If INTERACTIVE is non-nil, the tests are run interactively."
    "^tramp-archive"))
 
 (provide 'tramp-archive-tests)
+
 ;;; tramp-archive-tests.el ends here
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 47d5176..08f5c60 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -67,13 +67,13 @@
 (defvar tramp-remote-path)
 (defvar tramp-remote-process-environment)
 
-;; Needed for Emacs 24.
-(defvar inhibit-message)
 ;; Needed for Emacs 25.
 (defvar connection-local-criteria-alist)
 (defvar connection-local-profile-alist)
 ;; Needed for Emacs 26.
 (defvar async-shell-command-width)
+;; Needed for Emacs 27.
+(defvar shell-command-dont-erase-buffer)
 
 ;; Beautify batch mode.
 (when noninteractive
@@ -100,8 +100,8 @@
       (add-to-list
        'tramp-default-host-alist
        `("\\`mock\\'" nil ,(system-name)))
-      ;; Emacs' Makefile sets $HOME to a nonexistent value.  Needed in
-      ;; batch mode only, therefore.
+      ;; Emacs's Makefile sets $HOME to a nonexistent value.  Needed
+      ;; in batch mode only, therefore.
       (unless (and (null noninteractive) (file-directory-p "~/"))
         (setenv "HOME" temporary-file-directory))
       (format "/mock::%s" temporary-file-directory)))
@@ -112,7 +112,6 @@
       remote-file-name-inhibit-cache nil
       tramp-cache-read-persistent-data t ;; For auth-sources.
       tramp-copy-size-limit nil
-      tramp-message-show-message nil
       tramp-persistency-file-name nil
       tramp-verbose 0)
 
@@ -177,7 +176,6 @@ Print the content of the Tramp connection and debug 
buffers, if
 properly.  BODY shall not contain a timeout."
   (declare (indent 1) (debug (natnump body)))
   `(let ((tramp-verbose (max (or ,verbose 0) (or tramp-verbose 0)))
-        (tramp-message-show-message t)
         (debug-ignored-errors
          (append
           '("^make-symbolic-link not supported$"
@@ -2039,7 +2037,7 @@ properly.  BODY shall not contain a timeout."
       "/method:host:/:/path//foo"))
 
     ;; Forwhatever reasons, the following tests let Emacs crash for
-    ;; Emacs 24 and Emacs 25, occasionally. No idea what's up.
+    ;; Emacs 25, occasionally. No idea what's up.
     (when (tramp--test-emacs26-p)
       (should
        (string-equal (substitute-in-file-name "/method:host://~foo") "/~foo"))
@@ -2238,7 +2236,7 @@ This checks also `file-name-as-directory', 
`file-name-directory',
          (should
           (string-equal
            (file-name-as-directory file)
-           (if (tramp-completion-mode-p)
+           (if non-essential
                file (concat file (if (tramp--test-ange-ftp-p) "/" "./")))))
          (should (string-equal (file-name-directory file) file))
          (should (string-equal (file-name-nondirectory file) "")))))))
@@ -2376,7 +2374,7 @@ This checks also `file-name-as-directory', 
`file-name-directory',
            ;; Check message.
            ;; Macro `ert-with-message-capture' was introduced in Emacs 26.1.
            (with-no-warnings (when (symbol-plist 'ert-with-message-capture)
-             (let ((tramp-message-show-message t))
+             (let (inhibit-message)
                (dolist
                    (noninteractive (unless (tramp--test-ange-ftp-p) '(nil t)))
                  (dolist (visit '(nil t "string" no-message))
@@ -2393,14 +2391,14 @@ This checks also `file-name-as-directory', 
`file-name-directory',
                        tramp--test-messages))))))))
 
            ;; Do not overwrite if excluded.
-           (cl-letf (((symbol-function 'y-or-n-p) (lambda (_prompt) t))
+           (cl-letf (((symbol-function #'y-or-n-p) (lambda (_prompt) t))
                      ;; Ange-FTP.
                      ((symbol-function 'yes-or-no-p) (lambda (_prompt) t)))
              (write-region "foo" nil tmp-name nil nil nil 'mustbenew))
            ;; `mustbenew' is passed to Tramp since Emacs 26.1.
            (when (tramp--test-emacs26-p)
              (should-error
-              (cl-letf (((symbol-function 'y-or-n-p) 'ignore)
+              (cl-letf (((symbol-function #'y-or-n-p) #'ignore)
                         ;; Ange-FTP.
                         ((symbol-function 'yes-or-no-p) 'ignore))
                 (write-region "foo" nil tmp-name nil nil nil 'mustbenew))
@@ -3420,11 +3418,11 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
               :type 'file-already-exists))
            (when (tramp--test-expensive-test)
              ;; A number means interactive case.
-             (cl-letf (((symbol-function 'yes-or-no-p) #'ignore))
+             (cl-letf (((symbol-function #'yes-or-no-p) #'ignore))
                (should-error
                 (make-symbolic-link tmp-name1 tmp-name2 0)
                 :type 'file-already-exists)))
-           (cl-letf (((symbol-function 'yes-or-no-p) (lambda (_prompt) t)))
+           (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_prompt) t)))
              (make-symbolic-link tmp-name1 tmp-name2 0)
              (should
               (string-equal
@@ -3496,11 +3494,11 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
              (add-name-to-file tmp-name1 tmp-name2)
              :type 'file-already-exists)
             ;; A number means interactive case.
-            (cl-letf (((symbol-function 'yes-or-no-p) #'ignore))
+            (cl-letf (((symbol-function #'yes-or-no-p) #'ignore))
               (should-error
                (add-name-to-file tmp-name1 tmp-name2 0)
                :type 'file-already-exists))
-            (cl-letf (((symbol-function 'yes-or-no-p) (lambda (_prompt) t)))
+            (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_prompt) t)))
               (add-name-to-file tmp-name1 tmp-name2 0)
               (should (file-regular-p tmp-name2)))
             (add-name-to-file tmp-name1 tmp-name2 'ok-if-already-exists)
@@ -4242,13 +4240,13 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
   :tags '(:expensive-test)
   (skip-unless (tramp--test-enabled))
   (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
-  ;; `make-process' has been inserted in Emacs 25.1.  It supports file
-  ;; name handlers since Emacs 27.
+  ;; `make-process' supports file name handlers since Emacs 27.
   (skip-unless (tramp--test-emacs27-p))
 
   (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
     (let ((default-directory tramp-test-temporary-file-directory)
-         (tmp-name (tramp--test-make-temp-name nil quoted))
+         (tmp-name1 (tramp--test-make-temp-name nil quoted))
+         (tmp-name2 (tramp--test-make-temp-name 'local quoted))
          kill-buffer-query-functions proc)
       (with-no-warnings (should-not (make-process)))
 
@@ -4278,13 +4276,13 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
       ;; Simple process using a file.
       (unwind-protect
          (with-temp-buffer
-           (write-region "foo" nil tmp-name)
-           (should (file-exists-p tmp-name))
+           (write-region "foo" nil tmp-name1)
+           (should (file-exists-p tmp-name1))
            (setq proc
                  (with-no-warnings
                    (make-process
                     :name "test2" :buffer (current-buffer)
-                    :command `("cat" ,(file-name-nondirectory tmp-name))
+                    :command `("cat" ,(file-name-nondirectory tmp-name1))
                     :file-handler t)))
            (should (processp proc))
            ;; Read output.
@@ -4296,7 +4294,7 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
        ;; Cleanup.
        (ignore-errors
          (delete-process proc)
-         (delete-file tmp-name)))
+         (delete-file tmp-name1)))
 
       ;; Process filter.
       (unwind-protect
@@ -4351,34 +4349,60 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
        ;; Cleanup.
        (ignore-errors (delete-process proc)))
 
-      ;; Process with stderr.  tramp-adb.el doesn't support it (yet).
-      (unless (tramp--test-adb-p)
-       (let ((stderr (generate-new-buffer "*stderr*")))
-         (unwind-protect
+      ;; Process with stderr buffer.
+      (let ((stderr (generate-new-buffer "*stderr*")))
+       (unwind-protect
+           (with-temp-buffer
+             (setq proc
+                   (with-no-warnings
+                     (make-process
+                      :name "test5" :buffer (current-buffer)
+                      :command '("cat" "/")
+                      :stderr stderr
+                      :file-handler t)))
+             (should (processp proc))
+             ;; Read stderr.
+             (with-timeout (10 (tramp--test-timeout-handler))
+               (while (accept-process-output proc 0 nil t)))
+             (delete-process proc)
+             (with-current-buffer stderr
+               (should
+                (string-match "cat:.* Is a directory" (buffer-string)))))
+
+         ;; Cleanup.
+         (ignore-errors (delete-process proc))
+         (ignore-errors (kill-buffer stderr))))
+
+      ;; Process with stderr file.
+      (dolist (tmpfile `(,tmp-name1 ,tmp-name2))
+       (unwind-protect
+           (with-temp-buffer
+             (setq proc
+                   (with-no-warnings
+                     (make-process
+                      :name "test6" :buffer (current-buffer)
+                      :command '("cat" "/")
+                      :stderr tmpfile
+                      :file-handler t)))
+             (should (processp proc))
+             ;; Read stderr.
+             (with-timeout (10 (tramp--test-timeout-handler))
+               (while (accept-process-output proc nil nil t)))
+             (delete-process proc)
              (with-temp-buffer
-               (setq proc
-                     (with-no-warnings
-                       (make-process
-                        :name "test5" :buffer (current-buffer)
-                        :command '("cat" "/")
-                        :stderr stderr
-                        :file-handler t)))
-               (should (processp proc))
-               ;; Read stderr.
-               (with-current-buffer stderr
-                 (with-timeout (10 (tramp--test-timeout-handler))
-                   (while (= (point-min) (point-max))
-                     (while (accept-process-output proc 0 nil t))))
-                 (should
-                  (string-match "^cat:.* Is a directory" (buffer-string)))))
+               (insert-file-contents tmpfile)
+               (should
+                (string-match "cat:.* Is a directory" (buffer-string)))))
 
-           ;; Cleanup.
-           (ignore-errors (delete-process proc))
-           (ignore-errors (kill-buffer stderr))))))))
+         ;; Cleanup.
+         (ignore-errors (delete-process proc))
+         (ignore-errors (delete-file tmpfile)))))))
 
 (ert-deftest tramp-test31-interrupt-process ()
   "Check `interrupt-process'."
-  :tags '(:expensive-test)
+  ;; The test fails from time to time, w/o a reproducible pattern.  So
+  ;; we mark it as unstable.
+  :tags '(:expensive-test :unstable)
   (skip-unless (tramp--test-enabled))
   (skip-unless (tramp--test-sh-p))
   ;; Since Emacs 26.1.
@@ -4388,6 +4412,7 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
   ;; order to establish the connection prior running an asynchronous
   ;; process.
   (let ((default-directory (file-truename tramp-test-temporary-file-directory))
+       (delete-exited-processes t)
        kill-buffer-query-functions proc)
     (unwind-protect
        (with-temp-buffer
@@ -4399,7 +4424,8 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
          (should (interrupt-process proc))
          ;; Let the process accept the interrupt.
          (with-timeout (10 (tramp--test-timeout-handler))
-           (while (accept-process-output proc nil nil 0)))
+           (while (process-live-p proc)
+             (while (accept-process-output proc 0 nil t))))
          (should-not (process-live-p proc))
          ;; An interrupted process cannot be interrupted, again.
          (should-error
@@ -4409,14 +4435,24 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
       ;; Cleanup.
       (ignore-errors (delete-process proc)))))
 
+(defun tramp--test-async-shell-command
+    (command output-buffer &optional error-buffer input)
+  "Like `async-shell-command', reading the output.
+INPUT, if non-nil, is a string sent to the process."
+  (async-shell-command command output-buffer error-buffer)
+  (let ((proc (get-buffer-process output-buffer))
+       (delete-exited-processes t))
+    (when (stringp input)
+      (process-send-string proc input))
+    (with-timeout
+       ((if (getenv "EMACS_EMBA_CI") 30 10) (tramp--test-timeout-handler))
+      (while (or (accept-process-output proc nil nil t) (process-live-p 
proc))))
+    (accept-process-output proc nil nil t)))
+
 (defun tramp--test-shell-command-to-string-asynchronously (command)
   "Like `shell-command-to-string', but for asynchronous processes."
   (with-temp-buffer
-    (async-shell-command command (current-buffer))
-    (with-timeout
-        ((if (getenv "EMACS_EMBA_CI") 30 10) (tramp--test-timeout-handler))
-      (while (accept-process-output
-             (get-buffer-process (current-buffer)) nil nil t)))
+    (tramp--test-async-shell-command command (current-buffer))
     (buffer-substring-no-properties (point-min) (point-max))))
 
 (ert-deftest tramp-test32-shell-command ()
@@ -4435,111 +4471,176 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
          (inhibit-message t)
          kill-buffer-query-functions)
 
-      ;; Test ordinary `shell-command'.
-      (unwind-protect
-         (with-temp-buffer
-           (write-region "foo" nil tmp-name)
-           (should (file-exists-p tmp-name))
-           (shell-command
-            (format "ls %s" (file-name-nondirectory tmp-name))
-            (current-buffer))
-           ;; `ls' could produce colorized output.
-           (goto-char (point-min))
-           (while
-               (re-search-forward tramp-display-escape-sequence-regexp nil t)
-             (replace-match "" nil nil))
-           (should
-            (string-equal
-             (format "%s\n" (file-name-nondirectory tmp-name))
-             (buffer-string))))
-
-       ;; Cleanup.
-       (ignore-errors (delete-file tmp-name)))
+      (dolist (this-shell-command
+              '(;; Synchronously.
+                shell-command
+                ;; Asynchronously.
+                tramp--test-async-shell-command))
 
-      ;; Test `shell-command' with error buffer.
-      (let ((stderr (generate-new-buffer "*stderr*")))
+       ;; Test ordinary `{async-}shell-command'.
        (unwind-protect
            (with-temp-buffer
-             (shell-command "error" (current-buffer) stderr)
-             (should (= (point-min) (point-max)))
+             (write-region "foo" nil tmp-name)
+             (should (file-exists-p tmp-name))
+             (funcall
+              this-shell-command
+              (format "ls %s" (file-name-nondirectory tmp-name))
+              (current-buffer))
+             ;; `ls' could produce colorized output.
+             (goto-char (point-min))
+             (while
+                 (re-search-forward tramp-display-escape-sequence-regexp nil t)
+               (replace-match "" nil nil))
              (should
-              (string-match
-               "error:.+not found"
-               (with-current-buffer stderr (buffer-string)))))
+              (string-equal
+               (format "%s\n" (file-name-nondirectory tmp-name))
+               (buffer-string))))
 
          ;; Cleanup.
-         (ignore-errors (kill-buffer stderr))))
+         (ignore-errors (delete-file tmp-name)))
 
-      ;; Test ordinary `async-shell-command'.
+       ;; Test `{async-}shell-command' with error buffer.
+       (let ((stderr (generate-new-buffer "*stderr*")))
+         (unwind-protect
+             (with-temp-buffer
+               (funcall
+                this-shell-command
+                "echo foo >&2; echo bar" (current-buffer) stderr)
+               (should (string-equal "bar\n" (buffer-string)))
+               ;; Check stderr.
+               (with-current-buffer stderr
+                 (should (string-equal "foo\n" (buffer-string)))))
+
+           ;; Cleanup.
+           (ignore-errors (kill-buffer stderr)))))
+
+      ;; Test sending string to `async-shell-command'.
       (unwind-protect
          (with-temp-buffer
            (write-region "foo" nil tmp-name)
            (should (file-exists-p tmp-name))
-           (async-shell-command
-            (format "ls %s" (file-name-nondirectory tmp-name))
-            (current-buffer))
-           ;; Read output.
-           (with-timeout (10 (tramp--test-timeout-handler))
-             (while (accept-process-output
-                     (get-buffer-process (current-buffer)) nil nil t)))
-           ;; `ls' could produce colorized output.
-           (goto-char (point-min))
-           (while
-               (re-search-forward tramp-display-escape-sequence-regexp nil t)
-             (replace-match "" nil nil))
+           (tramp--test-async-shell-command
+            "read line; ls $line" (current-buffer) nil
+            ;; String to be sent.
+            (format "%s\n" (file-name-nondirectory tmp-name)))
            (should
             (string-equal
-             (format "%s\n" (file-name-nondirectory tmp-name))
+             ;; tramp-adb.el echoes, so we must add the string.
+             (if (tramp--test-adb-p)
+                 (format
+                  "%s\n%s\n"
+                  (file-name-nondirectory tmp-name)
+                  (file-name-nondirectory tmp-name))
+               (format "%s\n" (file-name-nondirectory tmp-name)))
              (buffer-string))))
 
        ;; Cleanup.
-       (ignore-errors (delete-file tmp-name)))
+       (ignore-errors (delete-file tmp-name)))))
+
+  ;; Test `async-shell-command-width'.  It exists since Emacs 26.1,
+  ;; but seems to work since Emacs 27.1 only.
+  (when (and (tramp--test-sh-p) (tramp--test-emacs27-p))
+    (let* ((async-shell-command-width 1024)
+          (cols (ignore-errors
+                  (read (tramp--test-shell-command-to-string-asynchronously
+                         "tput cols")))))
+      (when (natnump cols)
+       (should (= cols async-shell-command-width))))))
+
+;; This test is inspired by Bug#39067.
+(ert-deftest tramp-test32-shell-command-dont-erase-buffer ()
+  "Check `shell-command-dont-erase-buffer'."
+  :tags '(:expensive-test)
+  (skip-unless (tramp--test-enabled))
+  (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
+  ;; Prior Emacs 27, `shell-command-dont-erase-buffer' wasn't working properly.
+  (skip-unless (tramp--test-emacs27-p))
 
-      ;; Test sending string to `async-shell-command'.
+  ;; We check both the local and remote case, in order to guarantee
+  ;; that they behave similar.
+  (dolist (default-directory
+           `(,temporary-file-directory ,tramp-test-temporary-file-directory))
+    (let ((buffer (generate-new-buffer "foo"))
+         ;; Suppress nasty messages.
+         (inhibit-message t)
+         point kill-buffer-query-functions)
       (unwind-protect
-         (with-temp-buffer
-           (write-region "foo" nil tmp-name)
-           (should (file-exists-p tmp-name))
-           (async-shell-command "read line; ls $line" (current-buffer))
-           (process-send-string
-            (get-buffer-process (current-buffer))
-            (format "%s\n" (file-name-nondirectory tmp-name)))
-           ;; Read output.
-           (with-timeout (10 (tramp--test-timeout-handler))
-             (while (accept-process-output
-                     (get-buffer-process (current-buffer)) nil nil t)))
-           ;; `ls' could produce colorized output.
-           (goto-char (point-min))
-           (while
-               (re-search-forward tramp-display-escape-sequence-regexp nil t)
-             (replace-match "" nil nil))
-           ;; We cannot use `string-equal', because tramp-adb.el
-           ;; echoes also the sent string.
-           (should
-            (string-match
-             (format "\\`%s" (regexp-quote (file-name-nondirectory tmp-name)))
-             (buffer-string))))
+         (progn
+           ;; Don't erase if buffer is the current one.  Point is not moved.
+           (let (shell-command-dont-erase-buffer)
+             (with-temp-buffer
+               (insert "bar")
+               (setq point (point))
+               (should (string-equal "bar" (buffer-string)))
+               (should (= (point) (point-max)))
+               (shell-command "echo baz" (current-buffer))
+               (should (string-equal "barbaz\n" (buffer-string)))
+               (should (= point (point)))))
+
+           ;; Erase if the buffer is not current one.
+           (let (shell-command-dont-erase-buffer)
+             (with-current-buffer buffer
+               (erase-buffer)
+               (insert "bar")
+               (setq point (point))
+               (should (string-equal "bar" (buffer-string)))
+               (should (= (point) (point-max)))
+               (with-temp-buffer
+                 (shell-command "echo baz" buffer))
+               (should (string-equal "baz\n" (buffer-string)))
+               (should (= point (point)))))
+
+           ;; Erase if buffer is the current one, but
+           ;; `shell-command-dont-erase-buffer' is set to `erase'.
+           (let ((shell-command-dont-erase-buffer 'erase))
+             (with-temp-buffer
+               (insert "bar")
+               (setq point (point))
+               (should (string-equal "bar" (buffer-string)))
+               (should (= (point) (point-max)))
+               (shell-command "echo baz" (current-buffer))
+               (should (string-equal "baz\n" (buffer-string)))
+               (should (= (point) (point-max)))))
+
+           ;; Don't erase if `shell-command-dont-erase-buffer' is set
+           ;; to `beg-last-out'.  Check point.
+           (let ((shell-command-dont-erase-buffer 'beg-last-out))
+             (with-temp-buffer
+               (insert "bar")
+               (setq point (point))
+               (should (string-equal "bar" (buffer-string)))
+               (should (= (point) (point-max)))
+               (shell-command "echo baz" (current-buffer))
+               (should (string-equal "barbaz\n" (buffer-string)))
+               (should (= point (point)))))
+
+           ;; Don't erase if `shell-command-dont-erase-buffer' is set
+           ;; to `end-last-out'.  Check point.
+           (let ((shell-command-dont-erase-buffer 'end-last-out))
+             (with-temp-buffer
+               (insert "bar")
+               (setq point (point))
+               (should (string-equal "bar" (buffer-string)))
+               (should (= (point) (point-max)))
+               (shell-command "echo baz" (current-buffer))
+               (should (string-equal "barbaz\n" (buffer-string)))
+               (should (= (point) (point-max)))))
+
+           ;; Don't erase if `shell-command-dont-erase-buffer' is set
+           ;; to `save-point'.  Check point.
+           (let ((shell-command-dont-erase-buffer 'save-point))
+             (with-temp-buffer
+               (insert "bar")
+               (goto-char (1- (point-max)))
+               (setq point (point))
+               (should (string-equal "bar" (buffer-string)))
+               (should (= (point) (1- (point-max))))
+               (shell-command "echo baz" (current-buffer))
+               (should (string-equal "barbaz\n" (buffer-string)))
+               (should (= point (point))))))
 
        ;; Cleanup.
-       (ignore-errors (delete-file tmp-name)))
-
-      ;; Test `async-shell-command-width'.  Since Emacs 27.1.
-      (when (ignore-errors
-             (and (boundp 'async-shell-command-width)
-                  (zerop (call-process "tput" nil nil nil "cols"))
-                   (zerop (process-file "tput" nil nil nil "cols"))))
-       (let (async-shell-command-width)
-         (should
-          (string-equal
-           (format "%s\n" (car (process-lines "tput" "cols")))
-           (tramp--test-shell-command-to-string-asynchronously
-            "tput cols")))
-         (setq async-shell-command-width 1024)
-         (should
-          (string-equal
-           "1024\n"
-           (tramp--test-shell-command-to-string-asynchronously
-            "tput cols"))))))))
+       (ignore-errors (kill-buffer buffer))))))
 
 ;; This test is inspired by Bug#23952.
 (ert-deftest tramp-test33-environment-variables ()
@@ -4949,13 +5050,9 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
                (error (ert-skip "`vc-create-repo' not supported")))
              ;; The structure of VC-FILESET is not documented.  Let's
              ;; hope it won't change.
-             (condition-case nil
-                 (vc-register
-                  (list (car vc-handled-backends)
-                        (list (file-name-nondirectory tmp-name2))))
-               ;; `vc-register' has changed its arguments in Emacs
-               ;; 25.1.  Let's skip it for older Emacsen.
-               (error (skip-unless (tramp--test-emacs25-p))))
+             (vc-register
+              (list (car vc-handled-backends)
+                    (list (file-name-nondirectory tmp-name2))))
              ;; vc-git uses an own process sentinel, Tramp's sentinel
              ;; for flushing the cache isn't used.
              (dired-uncache (concat (file-remote-p default-directory) "/"))
@@ -5212,12 +5309,6 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
     (delete-directory tmp-file)
     (should-not (file-exists-p tmp-file))))
 
-(defun tramp--test-emacs25-p ()
-  "Check for Emacs version >= 25.1.
-Some semantics has been changed for there, w/o new functions or
-variables, so we check the Emacs version directly."
-  (>= emacs-major-version 25))
-
 (defun tramp--test-emacs26-p ()
   "Check for Emacs version >= 26.1.
 Some semantics has been changed for there, w/o new functions or
@@ -6146,12 +6237,14 @@ Since it unloads Tramp, it shall be the last test to 
run."
      (and (or (and (boundp x) (null (local-variable-if-set-p x)))
              (and (functionp x) (null (autoloadp (symbol-function x)))))
          (string-match "^tramp" (symbol-name x))
+         ;; `tramp-completion-mode' is autoloaded in Emacs < 28.1.
+         (not (eq 'tramp-completion-mode x))
          (not (string-match "^tramp\\(-archive\\)?--?test" (symbol-name x)))
          (not (string-match "unload-hook$" (symbol-name x)))
          (ert-fail (format "`%s' still bound" x)))))
   ;; The defstruct `tramp-file-name' and all its internal functions
-  ;; shall be purged.  `cl--find-class' must be protected in Emacs 24.
-  (with-no-warnings (should-not (cl--find-class 'tramp-file-name)))
+  ;; shall be purged.
+  (should-not (cl--find-class 'tramp-file-name))
   (mapatoms
    (lambda (x)
      (and (functionp x)
@@ -6193,9 +6286,10 @@ If INTERACTIVE is non-nil, the tests are run 
interactively."
 ;;   do not work properly for `nextcloud'.
 ;; * Fix `tramp-test29-start-file-process' and
 ;;   `tramp-test30-make-process' on MS Windows (`process-send-eof'?).
-;; * Implement `tramp-test31-interrupt-process' for `adb'.
+;; * Implement `tramp-test31-interrupt-process' for `adb'.  Fix `:unstable'.
 ;; * Fix Bug#16928 in `tramp-test43-asynchronous-requests'.  A remote
 ;;   file name operation cannot run in the timer.  Remove `:unstable' tag?
 
 (provide 'tramp-tests)
+
 ;;; tramp-tests.el ends here
diff --git a/test/lisp/progmodes/f90-tests.el b/test/lisp/progmodes/f90-tests.el
index 540082c..b6fbac3 100644
--- a/test/lisp/progmodes/f90-tests.el
+++ b/test/lisp/progmodes/f90-tests.el
@@ -277,4 +277,24 @@ end program prog")
     (forward-line -2)
     (should (= 2 (current-indentation))))) ; type is
 
+(ert-deftest f90-test-bug38415 ()
+  "Test for https://debbugs.gnu.org/38415 ."
+  (with-temp-buffer
+    (f90-mode)
+    (setq-local f90-smart-end 'no-blink)
+    (insert "module function foo(x)
+real :: x
+end")
+    (f90-indent-line)
+    (should (equal " function foo"
+                   (buffer-substring (point) (line-end-position))))
+    (goto-char (point-max))
+    (insert "\nmodule subroutine bar(x)
+real :: x
+end")
+    (f90-indent-line)
+    (should (equal " subroutine bar"
+                   (buffer-substring (point) (line-end-position))))))
+
+
 ;;; f90-tests.el ends here
diff --git a/test/lisp/shadowfile-tests.el b/test/lisp/shadowfile-tests.el
index 650782b..ed23e06 100644
--- a/test/lisp/shadowfile-tests.el
+++ b/test/lisp/shadowfile-tests.el
@@ -70,7 +70,6 @@
 (setq password-cache-expiry nil
       shadow-debug (getenv "EMACS_HYDRA_CI")
       tramp-verbose 0
-      tramp-message-show-message nil
       ;; On macOS, `temporary-file-directory' is a symlinked directory.
       temporary-file-directory (file-truename temporary-file-directory)
       shadow-test-remote-temporary-file-directory
diff --git a/test/lisp/shell-tests.el b/test/lisp/shell-tests.el
index 6d262f8..606de15 100644
--- a/test/lisp/shell-tests.el
+++ b/test/lisp/shell-tests.el
@@ -38,4 +38,11 @@
     (should (equal (shell--parse-pcomplete-arguments)
                    '(("cd" "ba") 1 4)))))
 
+(ert-deftest shell-tests-completion-after-semi ()
+  (with-temp-buffer
+    (shell-mode)
+    (insert "cd ba;")
+    (should (equal (shell--parse-pcomplete-arguments)
+                   '(("cd" "ba" "") 1 4 7)))))
+
 ;;; shell-tests.el ends here
diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el
index 2611519..ae20146 100644
--- a/test/lisp/simple-tests.el
+++ b/test/lisp/simple-tests.el
@@ -427,7 +427,7 @@ See bug#35036."
   (with-temp-buffer
     (switch-to-buffer (current-buffer))
     (setq buffer-undo-list nil)
-    (insert "a\nb\n\c\n")
+    (insert "a\nb\nc\n")
     (goto-char (point-max))
     ;; We use a keyboard macro because it adds undo events in the same
     ;; way as if a user were involved.
@@ -711,5 +711,61 @@ See Bug#21722."
           (when process (delete-process process))
           (when buffer (kill-buffer buffer)))))))
 
+
+;;; Tests for shell-command-dont-erase-buffer
+
+(defmacro with-shell-command-dont-erase-buffer (str output-buffer-is-current 
&rest body)
+  (declare (debug (form &body)) (indent 2))
+  (let ((expected (make-symbol "expected"))
+        (command (make-symbol "command"))
+        (caller-buf (make-symbol "caller-buf"))
+        (output-buf (make-symbol "output-buf")))
+    `(let* ((,caller-buf (generate-new-buffer "caller-buf"))
+            (,output-buf (if ,output-buffer-is-current ,caller-buf
+                           (generate-new-buffer "output-buf")))
+            (emacs (expand-file-name invocation-name invocation-directory))
+            (,command (format "%s -Q --batch --eval '(princ \"%s\")'"
+                              emacs ,str))
+            (inhibit-message t))
+       (unwind-protect
+           ;; Feature must work the same regardless how we specify the 2nd arg 
of `shell-command', ie,
+           ;; as a buffer, buffer name (or t, if the output must go to the 
current buffer).
+           (dolist (output (append (list ,output-buf (buffer-name ,output-buf))
+                                   (if ,output-buffer-is-current '(t) nil)))
+             (dolist (save-pos '(erase nil beg-last-out end-last-out 
save-point))
+               (let ((shell-command-dont-erase-buffer save-pos))
+                 (with-current-buffer ,output-buf (erase-buffer))
+                 (with-current-buffer ,caller-buf
+                   (dotimes (_ 2) (shell-command ,command output)))
+                 (with-current-buffer ,output-buf
+                   ,@body))))
+         (kill-buffer ,caller-buf)
+         (when (buffer-live-p ,output-buf)
+           (kill-buffer ,output-buf))))))
+
+(ert-deftest simple-tests-shell-command-39067 ()
+  "The output buffer is erased or not according to 
`shell-command-dont-erase-buffer'."
+  (let ((str "foo\n"))
+    (dolist (output-current '(t nil))
+      (with-shell-command-dont-erase-buffer str output-current
+        (let ((expected (cond ((eq shell-command-dont-erase-buffer 'erase) str)
+                              ((null shell-command-dont-erase-buffer)
+                               (if output-current (concat str str)
+                                 str))
+                              (t (concat str str)))))
+          (should (string= expected (buffer-string))))))))
+
+(ert-deftest simple-tests-shell-command-dont-erase-buffer ()
+  "The point is set at the expected position after execution of the command."
+  (let* ((str "foo\n")
+         (expected-point `((beg-last-out . ,(1+ (length str)))
+                           (end-last-out . ,(1+ (* 2 (length str))))
+                           (save-point . 1))))
+    (dolist (output-buffer-is-current '(t ni))
+      (with-shell-command-dont-erase-buffer str output-buffer-is-current
+        (when (memq shell-command-dont-erase-buffer '(beg-last-out 
end-last-out save-point))
+          (should (= (point) (alist-get shell-command-dont-erase-buffer 
expected-point))))))))
+
+
 (provide 'simple-test)
 ;;; simple-test.el ends here
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index 059d52b..a583d57 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -244,6 +244,27 @@
               (error-message-string (should-error (version-to-list 
"beta22_8alpha3")))
               "Invalid version syntax: `beta22_8alpha3' (must start with a 
number)"))))
 
+(ert-deftest subr-test-version-list-< ()
+  (should (version-list-< '(0) '(1)))
+  (should (version-list-< '(0 9) '(1 0)))
+  (should (version-list-< '(1 -1) '(1 0)))
+  (should (version-list-< '(1 -2) '(1 -1)))
+  (should (not (version-list-< '(1) '(0))))
+  (should (not (version-list-< '(1 1) '(1 0))))
+  (should (not (version-list-< '(1) '(1 0))))
+  (should (not (version-list-< '(1 0) '(1 0 0)))))
+
+(ert-deftest subr-test-version-list-= ()
+  (should (version-list-= '(1) '(1)))
+  (should (version-list-= '(1 0) '(1)))
+  (should (not (version-list-= '(0) '(1)))))
+
+(ert-deftest subr-test-version-list-<= ()
+  (should (version-list-<= '(0) '(1)))
+  (should (version-list-<= '(1) '(1)))
+  (should (version-list-<= '(1 0) '(1)))
+  (should (not (version-list-<= '(1) '(0)))))
+
 (defun subr-test--backtrace-frames-with-backtrace-frame (base)
   "Reference implementation of `backtrace-frames'."
   (let ((idx 0)
diff --git a/test/lisp/textmodes/conf-mode-tests.el 
b/test/lisp/textmodes/conf-mode-tests.el
index 814cb06..7e87026 100644
--- a/test/lisp/textmodes/conf-mode-tests.el
+++ b/test/lisp/textmodes/conf-mode-tests.el
@@ -162,7 +162,7 @@ image/tiff                  tiff tif
 (ert-deftest conf-test-toml-mode ()
   ;; From `conf-toml-mode' docstring.
   (with-temp-buffer
-    (insert "\[entry]
+    (insert "[entry]
 value = \"some string\"")
     (goto-char (point-min))
     (conf-toml-mode)
diff --git a/test/src/alloc-tests.el b/test/src/alloc-tests.el
index 4eb776a..aa1ab16 100644
--- a/test/src/alloc-tests.el
+++ b/test/src/alloc-tests.el
@@ -51,3 +51,10 @@
     (should-not (eq x y))
     (dotimes (i 4)
       (should (eql (aref x i) (aref y i))))))
+
+;; Bug#39207
+(ert-deftest aset-nbytes-change ()
+  (let ((s (make-string 1 ?a)))
+    (dolist (c (list 10003 ?b 128 ?c ?d (max-char) ?e))
+      (aset s 0 c)
+      (should (equal s (make-string 1 c))))))
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el
index a2cb3e9..48d2e86 100644
--- a/test/src/emacs-module-tests.el
+++ b/test/src/emacs-module-tests.el
@@ -60,8 +60,9 @@
     (should (eq 0
                 (string-match
                  (concat "#<module function "
-                         "\\(at \\(0x\\)?[[:xdigit:]]+\\( from .*\\)?"
-                         "\\|Fmod_test_sum from .*\\)>")
+                         "\\(at \\(0x\\)?[[:xdigit:]]+ "
+                         "with data 0x1234\\( from .*\\)?"
+                         "\\|Fmod_test_sum with data 0x1234 from .*\\)>")
                  (prin1-to-string (nth 1 descr)))))
     (should (= (nth 2 descr) 3)))
   (should-error (mod-test-sum "1" 2) :type 'wrong-type-argument)
@@ -97,6 +98,7 @@ changes."
              (rx bos "#<module function "
                  (or "Fmod_test_sum"
                      (and "at 0x" (+ hex-digit)))
+                 " with data 0x1234"
                  (? " from " (* nonl) "mod-test" (* nonl) )
                  ">" eos)
              (prin1-to-string func)))))
@@ -402,4 +404,24 @@ See Bug#36226."
         (load so nil nil :nosuffix :must-suffix)
       (delete-file so))))
 
+(ert-deftest module/function-finalizer ()
+  "Test that module function finalizers are properly called."
+  ;; We create and leak a couple of module functions with attached
+  ;; finalizer.  Creating only one function risks spilling it to the
+  ;; stack, where it wouldn't be garbage-collected.  However, with one
+  ;; hundred functions, there should be at least one that's
+  ;; unreachable.
+  (dotimes (_ 100)
+    (mod-test-make-function-with-finalizer))
+  (cl-destructuring-bind (valid-before invalid-before)
+      (mod-test-function-finalizer-calls)
+    (should (zerop invalid-before))
+    (garbage-collect)
+    (cl-destructuring-bind (valid-after invalid-after)
+        (mod-test-function-finalizer-calls)
+      (should (zerop invalid-after))
+      ;; We don't require exactly 100 invocations of the finalizer,
+      ;; but at least one.
+      (should (> valid-after valid-before)))))
+
 ;;; emacs-module-tests.el ends here
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
index 60be2c6..c6ceae4 100644
--- a/test/src/fns-tests.el
+++ b/test/src/fns-tests.el
@@ -858,6 +858,22 @@
        (puthash k k h)))
     (should (= 100 (hash-table-count h)))))
 
+(ert-deftest test-sxhash-equal ()
+  (should (= (sxhash-equal (* most-positive-fixnum most-negative-fixnum))
+            (sxhash-equal (* most-positive-fixnum most-negative-fixnum))))
+  (should (= (sxhash-equal (make-string 1000 ?a))
+            (sxhash-equal (make-string 1000 ?a))))
+  (should (= (sxhash-equal (point-marker))
+            (sxhash-equal (point-marker))))
+  (should (= (sxhash-equal (make-vector 1000 (make-string 10 ?a)))
+            (sxhash-equal (make-vector 1000 (make-string 10 ?a)))))
+  (should (= (sxhash-equal (make-bool-vector 1000 t))
+            (sxhash-equal (make-bool-vector 1000 t))))
+  (should (= (sxhash-equal (make-char-table nil (make-string 10 ?a)))
+            (sxhash-equal (make-char-table nil (make-string 10 ?a)))))
+  (should (= (sxhash-equal (record 'a (make-string 10 ?a)))
+            (sxhash-equal (record 'a (make-string 10 ?a))))))
+
 (ert-deftest test-secure-hash ()
   (should (equal (secure-hash 'md5    "foobar")
                  "3858f62230ac3c915f300c664312c63f"))
diff --git a/test/src/regex-emacs-tests.el b/test/src/regex-emacs-tests.el
index 6a661af..ad02710 100644
--- a/test/src/regex-emacs-tests.el
+++ b/test/src/regex-emacs-tests.el
@@ -161,7 +161,7 @@ what failed, if anything; valid values are 'search-failed,
 'compilation-failed and nil.  I compare the beginning/end of each
 group with their expected values.  This is done with either
 BOUNDS-REF or SUBSTRING-REF; one of those should be non-nil.
-BOUNDS-REF is a sequence \[start-ref0 end-ref0 start-ref1
+BOUNDS-REF is a sequence [start-ref0 end-ref0 start-ref1
 end-ref1 ....] while SUBSTRING-REF is the expected substring
 obtained by indexing the input string by start/end-ref.
 
@@ -327,7 +327,7 @@ emacs requires an extra symbol character"
 (defun regex-tests-BOOST-frob-escapes (s ispattern)
   "Mangle \\ the way it is done in frob_escapes() in
 regex-tests-BOOST.c in glibc: \\t, \\n, \\r are interpreted;
-\\\\, \\^, \{, \\|, \} are unescaped for the string (not
+\\\\, \\^, \\{, \\|, \\} are unescaped for the string (not
 pattern)"
 
   ;; this is all similar to (regex-tests-unextend)



reply via email to

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